AngularJS bind class attribute to model - angularjs

I have the following markup:
<div ng-app="app" ng-controller="Ctrl">
<label ng-repeat="role in roles">
<div ng-class="{ big: selectedRoles }">
<input type="checkbox" checklist-model="selectedRoles" checklist-value="role.id" />{{role.text}}</div>
</label>
</div>
I need the class "big" to be set to checked items. The ng-class attribute is not working as expected. Replicated problem in http://jsfiddle.net/qky1ownh/1/.

If you don't want to keep stuffing logic in your view, you could use an object literal to track the changes to the list instead.
$scope.selectedRoles = {
1: true,
2: true,
4: true
};
It allows you to just use ng-model on your checkboxes as well instead of some funky checkbox-list/value type stuff:
<div ng-class="{ big: selectedRoles[role.id] }">
<input type="checkbox" ng-model="selectedRoles[role.id]" />{{role.text}}
</div>
Updated fiddle:
http://jsfiddle.net/qky1ownh/8/

Since selectedRoles is an array of role ids you could just use array.indexOf to find if it in the selected list:-
<div ng-class="{ big: selectedRoles.indexOf(role.id)+1 }">
Since indexOf returns the item's index in the array(zero-based) and -1 when not found just add-up 1 to make it falsy.
Or just add a method in your controller to keep out any logic from the view and the fact that controllers are better testable than template, do :
controller:-
$scope.hasRole = function(id){
return $scope.selectedRoles.indexOf(id) > -1;
}
and use it in the view as:
<div ng-class="{ big: hasRole(role.id) }">

Another option is to apply a selected property to the object.
Fiddle: http://jsfiddle.net/7kfum1uu/
<div ng-class="{ 'big': role.selected }">
<input type="checkbox" ng-model="role.selected">{{role.text}}
</div>

Related

how to check checkbox whether true or false in angularjs using index value

I have checkbox inside the ng-repeat I want check whether checkbox is checked or not using their index value
html
<div ng-repeat="Name in Names">
<input type="checkbox"
ng-change="checkchange(Name .MaterialStream, $index)"
ng-model="Name.MaterialStream" />
</div>
controller
$scope.checkchange=function(index){
$scope.Names[index].active='true';
}
Now I get correct value when I check the checkbox. I have to get active value is true but I have check means active should be change into false in my case it's true here I attached my code help how to do this.
you can bind Name.active directly without using ng-repeat.
<div ng-repeat="Name in Names">
<input type="checkbox" ng-model="Name.active" />
</div>
Since you are binding Name.MaterialStream to checkbox, you can set Name.active based on it in ng-change.
$scope.checkchange=function(index){
$scope.Names[index].active = $scope.Names[index].MaterialStream;
}
ng-model is more than enough to store true false for checkbox, you don't require $index at all, but If you must do it by $index, then also you can utilize the ng-model.
See this Fiddle example out of your code.
In addition: in your above code, definition of checkchange() method doesn't accept the first argument, thats an issue. you shouldn't pass it if you not going to consume it.
To get the value of your checkbox, you simply have to return the model itself.
HTML
<div ng-repeat="Name in Names">
<input type="checkbox" ng-change="checkchange($index)"
ng-model="Name.MaterialStream" />
</div>
JS
$scope.checkchange=function(index){
return $scope.Names[index].MaterialStream;
}
Note that I removed the first argument you passed to the checkchange function as it wasn't used before. In fact, before you checked the index variable but it wouldn't hold the real $index-value.
Here is your Solution . With working example
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.Names = [{value : true}, {value : true},{value : false},{value : false},{value : true}]
$scope.toggleSelection = function(x,index,event) {
// how to check if checkbox is selected or not
//alert(index + ' is ' + event.target.checked);
$scope.Names[index].Active = $scope.Names[index].value;
};
});
<body ng-app="myApp" ng-controller="myCtrl">
<div ng-repeat="Name in Names">
{{$index}}
<input type="checkbox" id="" name="check_box"
value="{{x}}"
ng-change="toggleSelection(x.value,$index,$event)"
ng-model="Name.value" > {{Name.Active}}
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

Angular - ngClass being added to each clicked radio button (instead of ONLY clicked one)

In my angular app I'm using ng-repeat to generate several radio buttons, the ultimate goal is to add a choiceSelected class (ngClass colour styling) to the label of the clicked radio input. I can add the style to the clicked button, BUT that style is added to every other clicked radio button and I end up with 5 coloured labels. Can't understand why.
Here is the HTML code:
<div class="row" ng-repeat="obj in questionObject.choices">
<div class="radio">
<label class="choice" ng-class="{'choiceSelected': isChecked==$index}">
<input type="radio" name="optradio" ng-model="isChecked" ng-value="$index" ng-click="selectAnswer($index,questionObject)">{{obj.body}}</label>
</div>
</div>
<div class="row" ng-repeat="obj in questionObject.choices">
<div class="radio">
<label class="choice" ng-class="{'choiceSelected': isChecked==$index}">
<input type="radio"
name="optradio"
/*********************************************/
ng-model="isChecked"
ng-value="$index"
/*********************************************/
ng-click="selectAnswer($index,questionObject)">{{obj.body}}
</label>
</div>
</div>
Look at the lines inside the comments, clearly tells that your value of the checkbox($index) is binding to the isChecked variable.
By your, condition in ng-class isChecked==$index it is same for all the elements and so the class is applied for all radio buttons.
if you can update the Json of questionObject , can give you alternative option.
Assuming that questionObject contains the following json
[{
"body": "abc"
}, {
"body": "def"
}, {
"body": "aghi"
} ]
You can use the below code to make your result achieve
<div class="row" ng-repeat="obj in questionObject track by $index" >
<div class="radio" >
<label class="choice"
ng-class="{'choiceSelected': isChecked==$index}">
<input type="radio"
name="optradio"
ng-value="obj.body"
ng-click="selectAnswer($index,obj)">
{{obj.body}}
</label>
</div>
The method selectAnswer should make your work simple. Use this
$scope.selectAnswer=function(number,obj)
{
$scope.isChecked=number;
}
LIVE DEMO
NOTE: In your code the selectAnswer method call in HTML passes the
questionObject fully
Update 1
Reason for manually defining isChecked
Angular looks for the the value of isChecked in the scope because you have used ng-class in the

angularjs clear backing field when input box hides

I have a page that will hide/show additional elements when an option is selected:
<div ng-app>
<div ng-controller="ctrl">
opt: <select ng-model="model.opt" ng-options="item.id as item.text for item in model.opts"></select>
<br/> <span ng-show="model.opt > 1">
alt: <input type="checkbox" ng-model="model.alt" />
</span>
<div> <pre>{{ model | json }}</pre>
</div>
</div>
</div>
http://jsfiddle.net/v7wsdj74/
How would I setup to get notification when the "ng-hide" is evaluated so that the model fields being hidden can be set back to some default values (in this case null)?
Thanks
Perhaps something like this?
scope.$watch('myParameter', (value) => {
// if myParameter is false set it to null?
}
What you can do, is reset the model on changes:
<select ng-model="..." ng-options="..." ng-change="model.alt = null"></select>
https://jsfiddle.net/bfrola/wzpha8c3/
You can also define a more complex reset function and use ng-change="reset()". Hope this helps.

Select at least one checkbox validation

I have the array of checkboxes from which I want to select at least one checkbox and want to display the validation error
How can I do that? Here is my code
<div class="form-group" ng-class="{ 'has-error' : submitted && form.field.$invalid }">
<div class="col-md-12"><label for="field" >Select at leat one</label></div>
<div class="col-md-2" data-ng-repeat="i in [1,2,3,4]">
<label><input type="checkbox" name="field[$index]" value="{{i}}" data-ng-model="form.field[$index]" required/>Choice {{i+1}}</label>
</div>
<div ng-show="submitted && form.field.$invalid" class="help-block">
<p ng-show="form.field.$error.required">Please select at least one choice<p>
</div>
</div>
</div>
You can use native javascript functions to iterate over your array. First that come in mind are Array.prototype.some() and Array.prototype.filter().
With some, you can determine if one item in your array validates true and with filter you can find all the elements that pass a custom expression and check if the newly created array has a certain length.
E.g.:
var atleastOne = this.form.field.some(function(element) {
return element;
});
if(atleastOne) {
window.alert("validated with some");
}
var filtered = this.form.field.filter(function(element) {
if(element) { return element; }
});
if(filtered.length > 0) {
window.alert('validated with filter');
}
You can flag the variables that show the errors based on the results of your validation. A working demo can be found here.
You can create your checkbox list object array properly then bind it. Please find the demo
<div ng-controller="ChckbxsCtrl">
<div ng-repeat="chk in items">
<div style="width:500px;height:100px;border:1px solid #000;">
<B>{{chk.group}}</B><br>
<label ng-repeat="vale in chk.values">
<input type="checkbox" ng-model="vale.val" />
{{vale.label}}</label>
</div>
<span ng-show="chk.isValid">Select at least one option from {{chk.group}}</span>
</br> </div>
</br>

ngClass not rendering properly

I am loading a todos list, every todo has a flag field which if true the ng-class should apply. When loading data into the page ng-class is applied if I use ng-class="{'completed': todo.isCompleted=='true'}", but then it doesn't work when I play with the checkboxes.
On the other hand if I use ng-class="{'completed': todo.isCompleted==true}" instead (without the quotes on the true), it loads the data without applying the ng-class at the beginning, means loading all as if they are false, but then it works fine when playing with the checkboxes.
It has been driving me crazy, couldn't figure out why.
<ul id="todo-list">
<li ng-repeat="todo in todos" ng-class="{'completed': todo.isCompleted==true}" class="editing">
<div class="view" >
<input class="toggle" type="checkbox" ng-click="complete(todo)" ng-model="todo.isCompleted" ng-checked="{{todo.isCompleted}}">
<label ng-hide="isEditing" ng-dblclick="isEditing = !isEditing">{{todo.title}}</label>
<button class="destroy" ng-click="remove(todo)"></button>
</div>
<input class="edit" ng-show="isEditing" ng-model="todo.title" ng-blur="isEditing = !isEditing;edit(todo);">
</li>
</ul>
Controller
$scope.complete = function(todo) {
$scope.insertTodo(todo, UPDATE);
};
Any help is appreciated.
Have you tried to change
ng-class="{'completed': todo.isCompleted==true}"
to
ng-class="{'completed': todo.isCompleted}"
Or, one of those
ng-class="todo.isCompleted ? 'completed' : ''"
ng-class="{true: 'completed', false: ''}[todo.isCompleted]"
So, it looks like your server is returning the boolean values as strings, that's why your bindings don't work...
You can either change your server's return values (preferred) or add ng-true-value and ng-false-value to your check box and keep the binding on ng-class using the string comparison:
<ul id="todo-list">
<li ng-repeat="todo in todos" ng-class="{'completed': todo.isCompleted=='true'}" class="editing">
<div class="view" >
<input class="toggle" type="checkbox" ng-click="complete(todo)" ng-model="todo.isCompleted" ng-checked="{{todo.isCompleted}}" ng-true-value="'true'" ng-false-value="'false'">
<label ng-hide="isEditing" ng-dblclick="isEditing = !isEditing">{{todo.title}}</label>
<button class="destroy" ng-click="remove(todo)"></button>
</div>
<input class="edit" ng-show="isEditing" ng-model="todo.title" ng-blur="isEditing = !isEditing;edit(todo);">
</li>
</ul>
Hope that helps

Resources