11

Say we have a set of projects exposed via the Project service:

{ id: '123', name: 'Yeoman', watchers: '1233', ... }
{ id: '123', name: 'Grunt', watchers: '4343', ... }

Then, we have a form to choose your favorite project:

Select favorite project:
%label.radio(ng-repeat="project in Project.query()")
  %input(type="radio" ng-model="data.favoriteProject" value="{{project.id}}") {{project.name}}

This sets choices.favoriteProject to the id value of the chosen project. Often, we need to access the related object, not just the id:

John's favorite project:
{{Project.get(data.favoriteProject).name}}

What I'm looking for is a way to bind the radios and checkboxes straight to the object itself, not the id, so we could do

John's favorite project:
{{data.favoriteProject.name}}

instead. This is possible with select directive via ng-options, but how can we do this with radios and checkboxes? I'd still like to use the ids for matching instead of references, if possible.

To clarify, here's an example what I'm looking for

Select favorite project:
%label.radio(ng-repeat="project in Project.query()")
  %input(type="radio" ng-model="data.favoriteProject" value="{{project}}" ng-match="id") {{project.name}}

It says: "Please bind data.favoriteProject to the actual project object and use the id to check if they match (instead of references)".

2 Answers 2

15

[Update]

I've completely changed my answer after discovering the ngValue directive, which appears to be undocumented. It allows you to bind objects instead of just strings as values for ngModel on the radio button inputs.

<label ng-repeat="project in projects">
  <input type="radio" ng-model="data.favoriteProject"
    ng-value="project">{{project.name}}</input>
</label>

<p>Your favorite project is {{data.favoriteProject.name}}.</p>

This uses references to check rather than just IDs, but I think in most cases, this is what people will be looking for. If you do very strictly only want to match based on IDs, you can use the [Old Answer], below, or even better, just create a function--e.g. projectById(projectId) that you can use for looking up a project based on its ID.

I've updated the JSFiddle to demonstrate: http://jsfiddle.net/BinaryMuse/pj2GR/


[Old Answer]

Perhaps you can utilize the ng-change attribute of the radio button directive to achieve what you want. Consider this HTML:

<p>Select your favorite project:</p>
<label ng-repeat="project in projects">
  <input type="radio" ng-model="data.favoriteProjectId" value="{{project.id}}"
         ng-change="data.favoriteProject = project">
    {{project.name}}
  </input>
</label>

<p>Your favorite project is {{data.favoriteProject.name}}.</p>

You could also call a function inside ng-change, for example setfavoriteProject(project)--but I did not do that here for simplicity's sake.

Here is a working jsFiddle to demonstrate the technique: http://jsfiddle.net/BinaryMuse/pj2GR/7/

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

8 Comments

Thank you! I really like this solution. It's simple, yet it works neatly! I'll leave the question open for other solutions for now. The problem with this is that there's duplication of data (the id) and we have to manage setting the value ourselves.
Why use projects[$index] instead of just the project object?
I made that refactoring in the jsFiddle, but forgot to update the post. Thanks!
There's a slight problem with checkboxes with this approach. ng-change fires on check AND uncheck so the favoriteProject gets set even if we are unchecking.
Interesting that the ng-model is more or less a throw-away here.
|
1

No ng-change needed (and I'm not sure, if it is a good practise to write inline-code like this. On the other hand angulars directives are not too far from it theirselves). Why not just do something like this (works with ng-repeat as well):

Fiddle: http://jsfiddle.net/JohannesJo/VeZxh/3/

Code:

<body ng-app="app">
<div ng-controller='controller'>
<input type = "radio" ng-model = "oSelected"  value = "{{aData[0]}}">
<input type = "radio" ng-model = "oSelected"  value = "{{aData[1]}}">
<div>test:     {{oSelected}}</div>
</div>
</body>


app = angular.module('app',[]);

app.controller('controller', function($scope){
$scope.aData = [
    {o:1},
    {o:2}
];
$scope.oSelected = {};
});

Edit: I maybe should mention that this doesn't work for checkboxes, as value will either be true or false. Also a shared model will lead to all checkboxes either being checked or unchecked at the same time.

1 Comment

see ng-value solution, it is pretty much flexible

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.