1

I would like to build a directive which emulates radio button behaviour, this seems fairly trivial if you control the radio buttons externally, but I want to do it so that the radio buttons control themselves. This means they become self-contained bits of code.

Angular Directives are not my strong point, but here is what I have come up with so far:

HTML:

<test-radiobutton name="test" value="1" label="Testing" checked="false"></test-radiobutton>
<test-radiobutton name="test" value="2" label="Testing 2" checked="false"></test-radiobutton>

Template:

<div>
    <div class="test_radiobutton_box" ng-class="{'checked': checked}" ng-click="toggleChecked()"></div>
    <div class="test_radiobutton_label">{{ label }}</div>
</div>

And the JS:

.directive("testRadiobutton", function() {
    return {
        restrict: "AE",
        scope: {
            label: "@label",
            name: "@name",
            value: "@value",
            checked: "=checked"
        },
        templateUrl: "../../test_components/test-radiobutton/test-radiobutton.html",
        controller: function ($scope) {
            $scope.toggleChecked = function () {
                $('test-radiobutton[name='+$scope.name+']').attr("checked", "false");

                $('test-radiobutton[name='+$scope.name+'][value='+$scope.value+']').each(function (index) {
                    $(this).attr("checked", "true");
                });
            };
        },
        link: function(scope, element, attributes){

        }
    };
});

The problem is that the other radio buttons aren't deselecting when you select a new one with the same name, the jQuery is looping through the elements correctly and finds the other elements (tested using .each()) but doesn't toggle their values.

Obviously I'm not doing this how Angular intends so how would I do this?

EDIT - to reflect using a service (still not working)

New controller within directive uses my new radio button service.

controller: function ($scope, RadioButtonService) {
    $scope.toggleChecked = function () {
        RadioButtonService.selectRadio($scope.name, $scope.value);
    };
},

And my service:

angular.module("test_components.testRadiobutton.service", [])
.factory("RadioButtonService", function () {
    return {
        deselectAllRadios: function (radio_name) {
            $('test-radiobutton[name='+radio_name+']').each(function (index) {
                console.log("deselecting");
                angular.element($(this)).scope().checked = false;
            });
        },
        selectRadio: function (radio_name, radio_value) {
            this.deselectAllRadios(radio_name);
            $('test-radiobutton[name='+radio_name+'][value='+radio_value+']').each(function (index) {
                console.log('test-radiobutton[name='+radio_name+'][value='+radio_value+']');
                angular.element($(this)).scope().checked = true;
            });
        }
    };
});

The console outputs correctly, manually referencing the elements with jQuery works too but the checkbox value just won't change.

5
  • Any reason not to use the existing Angular radio buttons? docs.angularjs.org/api/ng/input/input%5Bradio%5D Commented Dec 15, 2014 at 15:13
  • Maybe you should create a factory, which is part of your Module and controls different groups (name) of radio buttons. Commented Dec 15, 2014 at 15:14
  • @rayners it is probably because he needs custom styling. Or maybe it is just a practice. Commented Dec 15, 2014 at 15:14
  • where is the ng-model ? .You must use ng-model instead of name attributes Commented Dec 15, 2014 at 15:15
  • I needed custom styling, my old version used lots of HTML markup and CSS but it felt clumsy so I moved to PolymerJS but that doesn't work in older browsers (I need to support Chrome 18) so AngularJS Directives were used. I don't quite understand them however which is where the main issue is. Commented Dec 15, 2014 at 15:22

2 Answers 2

1

I know a two ways of how I would do this. I recommend the first one.

1. Create service

Create a simple factory service which is part of your module. Let it manage your radio buttons and groups of them. I suggest this over the next method.

2. Access scope of the other element

You can access scope of another directive like this:

angular.element($("#your-element")).scope();

You just have to iterate through all of your selected objects then access the scope and change the value. It shouldn't be too hard.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks @user50992, I've kind of used a combination of both but it's still not working, I've updated my question to show this - any more tips?
1

I ended up making the directive accept an object of radio buttons, then I used ng-repeat to render them, that gave my directive's controller access to all of the radios, from there onwards it was a simple case of using the clicked button's $index to toggle the $scope.radios[i].isChecked value depending on whether it was the one clicked or not.

This method is extremely simple, not sure why I tried it my original way.

1 Comment

Apologies for the delay, you would be best off using something like this example here: fredonism.com/archive/radio-button-group.aspx which is very similar to how I've done it (but a bit better)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.