admin管理员组

文章数量:1244306

I feel like i'm just missing something here, but I can't see what. I can't seem to get the value of the radio button to behave in the same way as the checkboxes. What am I doing wrong?

Here's a demo: /

Here's an idea of what my HTML looks like

<tr ng-repeat="contact in ContactsList">
    <td>{{contact.name}}</td>
    <td>{{contact.email}}</td>
    <td ng-class="{'success':contact.isPrimary}">
        <input type="radio" name="radio-primary" ng-model="contact.isPrimary" />
    </td>
    <td ng-class="{'success':contact.isTechnical}">
        <input type="checkbox" ng-model="contact.isTechnical" />
    </td>
</tr>

And here's my Controller

function MyCtrl($scope) {
    $scope.ContactsList = [{
        name: "John Doe",
        email: "[email protected]",
        isPrimary: false,
        isTechnical: true
    }, {
        name: "Jane Doe",
        email: "[email protected]",
        isPrimary: true,
        isTechnical: false
    }, {
        name: "Bill Murray",
        email: "[email protected]",
        isPrimary: false,
        isTechnical: false
    }, {
        name: "Someone Dude",
        email: "[email protected]",
        isPrimary: false,
        isTechnical: false
    }];
}

I feel like i'm just missing something here, but I can't see what. I can't seem to get the value of the radio button to behave in the same way as the checkboxes. What am I doing wrong?

Here's a demo: http://jsfiddle/vwJ6a/2/

Here's an idea of what my HTML looks like

<tr ng-repeat="contact in ContactsList">
    <td>{{contact.name}}</td>
    <td>{{contact.email}}</td>
    <td ng-class="{'success':contact.isPrimary}">
        <input type="radio" name="radio-primary" ng-model="contact.isPrimary" />
    </td>
    <td ng-class="{'success':contact.isTechnical}">
        <input type="checkbox" ng-model="contact.isTechnical" />
    </td>
</tr>

And here's my Controller

function MyCtrl($scope) {
    $scope.ContactsList = [{
        name: "John Doe",
        email: "[email protected]",
        isPrimary: false,
        isTechnical: true
    }, {
        name: "Jane Doe",
        email: "[email protected]",
        isPrimary: true,
        isTechnical: false
    }, {
        name: "Bill Murray",
        email: "[email protected]",
        isPrimary: false,
        isTechnical: false
    }, {
        name: "Someone Dude",
        email: "[email protected]",
        isPrimary: false,
        isTechnical: false
    }];
}
Share Improve this question asked Jun 19, 2014 at 13:00 Chris BarrChris Barr 34.1k28 gold badges102 silver badges152 bronze badges 3
  • I know your pain - I had a similar issue a few weeks back - might be helpful: stackoverflow./questions/23817649/… – tymeJV Commented Jun 19, 2014 at 13:02
  • @tymeJV There's no marked answer on that question - did you ever find a solution? – Chris Barr Commented Jun 19, 2014 at 13:26
  • 1 Just what I posted in the edited question - everything else seemed to fail out....had no idea radio's with Angular would be so....unlogical (in my mind anways) – tymeJV Commented Jun 19, 2014 at 13:43
Add a ment  | 

3 Answers 3

Reset to default 5

Nice question! I was stuck on a similar problem and implemented kind of a work around. First of all, I don't think that you want the radio buttons to behave in the same way like the checkboxes. Checkboxes allow multiple values while radios don't. Probably that was clear, I just want to state it in order to prevent a misunderstanding.

The AngularJS documentation gives some explanation on the usage of radio buttons. https://docs.angularjs/api/ng/input/input[radio] The explanation doesn't take a real "dynamic" environment in account. As you can see, the colours are prefixed in the example. I assume, that you want your table to be pletely dynamic, without prefixing anything.

The first thing I did are the following changes in the HTML:

<form name="myForm" ng-controller="MyCtrl">
    <h4>Primary: {{GetPrimaryContact().email}}</h4>

    <table class="table table-bordered table-striped">
        <thead>
        <tr>
            <th>Name</th>
            <th>Email</th>
            <th>Primary</th>
            <th>Technical</th>
            <th>Sales</th>
            <th>Billing</th>
            <th>Emergency</th>
        </tr>
        </thead>
        <tbody>
        <tr ng-repeat="contact in ContactsList">
            <td>{{contact.name}}</td>
            <td>{{contact.email}}</td>
            <td ng-class="{'success':contact.isPrimary == 'true'}">
                <input type="radio" name="radio-primary" ng-model="contact.isPrimary" value="true" ng-change="update($index)" />
            </td>
            <td ng-class="{'success':contact.isTechnical}">
                <input type="checkbox" ng-model="contact.isTechnical" />
            </td>
            <td ng-class="{'success':contact.isSales}">
                <input type="checkbox" ng-model="contact.isSales" />
            </td>
            <td ng-class="{'success':contact.isBilling}">
                <input type="checkbox" ng-model="contact.isBilling" />
            </td>
            <td ng-class="{'success':contact.isEmergency}">
                <input type="checkbox" ng-model="contact.isEmergency" />
            </td>
        </tr>
        </tbody>
    </table>
</form>

The success class-check pares isPrimary to string 'true'. I am not able to use real boolean values when working with paring on radio buttons.

Additionally, there is a value="true" now which is required for the parison (It checks the line, where isPrimary is in fact true). Last thing is a new method in the ng-change part. We need this, because we need to tell the controller that the other values are false, when one value changes to true. This is why we also give the $index of the ng-repeat iteration to the method, because the value which is currently changed to true doesn't need to be false again.

Here is the new Controller:

function MyCtrl($scope) {
    $scope.ContactsList = [{
        name: "John Doe",
        email: "[email protected]",
        isPrimary: 'false',
        isTechnical: true,
        isSales: false,
        isBilling: true,
        isEmergency: true
    }, {
        name: "Jane Doe",
        email: "[email protected]",
        isPrimary: 'true',
        isTechnical: false,
        isSales: false,
        isBilling: true,
        isEmergency: true
    }, {
        name: "Bill Murray",
        email: "[email protected]",
        isPrimary: 'false',
        isTechnical: false,
        isSales: true,
        isBilling: false,
        isEmergency: false
    }, {
        name: "Someone Dude",
        email: "[email protected]",
        isPrimary: 'false',
        isTechnical: false,
        isSales: false,
        isBilling: false,
        isEmergency: true
    }];

    $scope.GetPrimaryContact = function () {
        return _.findWhere($scope.ContactsList, {
            isPrimary: 'true'
        });
    };

    $scope.update = function(index) {
        for (var i=0;i<$scope.ContactsList.length;i++) {
            if (index != i) {
                $scope.ContactsList[i].isPrimary = 'false';
            }
        }
    };
}

The controller includes the changes, that isPrimary uses Strings instead of Booleans and the new update() method. Here is a link to a working demo in jsfiddle: http://jsfiddle/vwJ6a/20/

Update:

Chris and me found obviously a way, to use real boolean values for the radio button in ng-repeat. In order to use it, ng-value="true" has to be used instead of value="true". value does not seem to work, I got the idea here: AngularJS - Binding radio buttons to models with boolean values

The HTML part will look like this:

<form name="myForm" ng-controller="MyCtrl">
    <h4>Primary: {{GetPrimaryContact().email}}</h4>

    <table class="table table-bordered table-striped">
        <thead>
        <tr>
            <th>Name</th>
            <th>Email</th>
            <th>Primary</th>
            <th>Technical</th>
            <th>Sales</th>
            <th>Billing</th>
            <th>Emergency</th>
        </tr>
        </thead>
        <tbody>
        <tr ng-repeat="contact in ContactsList">
            <td>{{contact.name}}</td>
            <td>{{contact.email}}</td>
            <td ng-class="{'success':contact.isPrimary}">
                <input type="radio" name="radio-primary" ng-value="true" ng-model="contact.isPrimary" ng-checked="contact.isPrimary" ng-change="UpdatePrimary(contact)" />
            </td>
            <td ng-class="{'success':contact.isTechnical}">
                <input type="checkbox" ng-model="contact.isTechnical" />
            </td>
            <td ng-class="{'success':contact.isSales}">
                <input type="checkbox" ng-model="contact.isSales" />
            </td>
            <td ng-class="{'success':contact.isBilling}">
                <input type="checkbox" ng-model="contact.isBilling" />
            </td>
            <td ng-class="{'success':contact.isEmergency}">
                <input type="checkbox" ng-model="contact.isEmergency" />
            </td>
        </tr>
        </tbody>
    </table>
</form>

and the controller like this:

function MyCtrl($scope) {
    $scope.ContactsList = [{
        name: "John Doe",
        email: "[email protected]",
        isPrimary: false,
        isTechnical: true,
        isSales: false,
        isBilling: true,
        isEmergency: true
    }, {
        name: "Jane Doe",
        email: "[email protected]",
        isPrimary: true,
        isTechnical: false,
        isSales: false,
        isBilling: true,
        isEmergency: true
    }, {
        name: "Bill Murray",
        email: "[email protected]",
        isPrimary: false,
        isTechnical: false,
        isSales: true,
        isBilling: false,
        isEmergency: false
    }, {
        name: "Someone Dude",
        email: "[email protected]",
        isPrimary: false,
        isTechnical: false,
        isSales: false,
        isBilling: false,
        isEmergency: true
    }];

    $scope.GetPrimaryContact = function () {
        return _.findWhere($scope.ContactsList, {
            isPrimary: true
        });
    };

    $scope.UpdatePrimary = function(contact) {
        _.each($scope.ContactsList, function(x) {
            x.isPrimary = (x.email === contact.email);
        });
    };
}

Here is a demo in jsfiddle: http://jsfiddle/vwJ6a/24/

The main difference is checkboxes allow multiples selections while radio buttons dont. That's why radio buttons should share the same model. In your case, the ngModels point to different objects.

This is how I would get around it:

<td ng-class="{'success':primaryContact.email == contact.email}">
    <input type="radio" name="radio-primary" ng-model="primaryContact.email" 
    ng-value="contact.email"/>
</td>

JS

$scope.primaryContact = {
    email:"[email protected]"
};

Updated Fiddle

I believe if you add value="1" to your radio input line, you'll get the results you're looking for.

<input type="radio" value="1" name="radio-primary" ng-model="contact.isPrimary" />

本文标签: javascriptAngular radio button model inside ngrepeatStack Overflow