Question

In my AngularJS application, I am displaying contacts data in a grid. My typical contacts JSON looks like as below ...

[
    { type: "IM", value: "mavaze123", default: true },
    { type: "IM", value: "mvaze2014", default: false },
    { type: "IM", value: "mavaze923", default: false },
    { type: "IM", value: "mvaze8927", default: false },
    { type: "Email", value: "mavaze123@abc.com", default: true },
    { type: "Email", value: "mvaze2014@xyz.net", default: false } 
]

The last property 'default' is actually a radio button, selection of which should alter the original default value of the corresponding contact type in above JSON. There can be one default from each type of contact i.e. we can group radio buttons based on the contact type.

<div ng-repeat="contact in contacts">
    <div>{{contact.type}}</div>
    <div>{{contact.value}}</div>
    <div><input type="radio" name="{{contact.type}}" ng-model="contact.default" ng-value="true"/></div>
</div>

Note: The above code is not the exact one, but approximately same, as it will appear inside a custom grid component.

Now when I load my view/edit form page with above JSON, it correctly shows the radio state of all contacts. The problem comes, after page load, when user selects another contact as default. This actually changes the model value of default to true for newly selected contact however the model value of original default contact still remains true, even though its radio state changes to uncheck/blur (because they are having same 'name' value).

I thought to write a directive, but I am unable get it triggered on radio on-blur/uncheck event.

There are various posts on binding boolean values to radio buttons, but I am unable to get it work in my scenario, as I want to update model values for individual radio button in a radio group. See there is no single model representing a radio group.

Original State of radio buttonsModel changes on selection of radio buttonPrevious model remains unchanged on selection of other radio button

Was it helpful?

Solution 2

I added an attribute directive in my input statement ...

<div ng-repeat="contact in contacts">
    <div>{{contact.type}}</div>
    <div>{{contact.value}}</div>
    <div><input type="radio" name="{{contact.type}}" ng-model="contact.default" ng-value="true" boolean-grid-model /></div>
</div>

And my custom directive ...

myModule.directive('booleanGridModel') {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, elem, attrs, controller) {
           var radioSelected = scope.$eval(attrs.ngModel);
           if(radioSelected) {
               var selectedContact = scope.contact;
               _.each(scope.contacts, function(contact) {
                  if(contact.type === selectedContact.type) {
                      _.isEqual(contact, selectedContact) ? contact.default = true : contact.default = false;
                  }
               });
           }
       }
    };
}

OTHER TIPS

I think you should change your design to separate the contacts from contactTypes and store the key to the default contact in contact type.

In your current design, there are duplicated values for default and that's not the desired way to work with radio.

$scope.contacts = [
        { type: "IM", value: "mavaze123" },
        { type: "IM", value: "mvaze2014" },
        { type: "IM", value: "mavaze923" },
        { type: "IM", value: "mvaze8927" },
        { type: "Email", value: "mavaze123@abc.com" },
        { type: "Email", value: "mvaze2014@xyz.net" } 
   ];

    $scope.contactTypes = {
        "IM": { default:"mavaze123"}, //the default is contact with value = mavaze123
        "Email": { default:"mavaze123@abc.com"}
   };

You Html:

<div ng-repeat="contact in contacts">
            <div>{{contact.type}}</div>
            <div>{{contact.value}}</div>
            <div><input type="radio" name="{{contact.type}}" ng-model="contactTypes[contact.type].default" ng-value="contact.value"/></div>
        </div>

DEMO

I assume that the key of contact is value, you could use an Id for your contact.

WHy you declare ng-value="true" please remove that

<div><input type="radio" name="{{contact.type}}" ng-model="contact.default" ng-value="{{contact.default}}"/></div>

Please use $scope.$apply() in your value changing code

Like something below

$scope.$apply(function ChangeType()
{
/Code
});

And you need to change name="{{contact.type}}" to name="contact.type{{$index}}" Because some types are same name.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top