angularjs clear backing field when input box hides - angularjs

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.

Related

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

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

AngularJS bind class attribute to model

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>

ngDisabled not working for radio group bound no nested model - AngularJS

I am trying to implement two way data binding using a model that is an array of objects in this format:
$rootScope["bBoxProps"] =[{
"bType": "sBusinessType",
"id":"sBusinessType",
"title":"business",
"options":[
{
"optId":"nyi",
"name":"nyi",
"isSelected":true,
"isDisabled":false,
"isInvalid":false
},
{
"optId":"local",
"name":"local",
"isSelected":false,
"isDisabled":false,
"isInvalid":false
}
],
"disabled":false,
"invalid":false
},{...},{...}];
To a radio group of two radio buttons within an ngRepeat as shown below:
<div class="buyBox" id="{{bBox.id}}" ng-repeat="bBox in bBoxProps" ng-class="{disabledBb: bBox.disabled, invalidBb: bBox.invalid}">
<div class="bbTitle"><h3>{{bBox.title | uppercase}}</h3></div>
<div class="bbSelect">
<div class="bbSelectTop bbSelectOpt">
<input type="radio" name="{{bBox.id}}" id="{{bBox.options[0].optId}}" class="css-checkbox" ng-click="pmFlow(state,this,bBox.options[0])" ng-checked="bBox.options[0].isSelected" ng-disabled="bBox.options[0].isDisabled==true" ng-class="{invalidBbOpt: bBox.options[0].isInvalid}"/>
<label for="{{bBox.options[0].optId}}" class="bbLabel"><div class="bbLabelText">{{bBox.options[0].name | uppercase}}</div></label>
</div>
<div class="bbSelectBottom bbSelectOpt">
<input type="radio" name="{{bBox.id}}" id="{{bBox.options[1].optId}}" class="css-checkbox" ng-click="pmFlow(state,this,bBox.options[1])" ng-checked="bBox.options[1].isSelected" ng-disabled="bBox.options[1].isDisabled==true" ng-class="{invalidBbOpt: bBox.options[1].isInvalid}"/>
<label for="{{bBox.options[1].optId}}" class="bbLabel"><div class="bbLabelText">{{bBox.options[1].name | uppercase}}</div></label>
</div>
</div>
</div>
Everything is working fine, except the "isDisabled" suboption is not binding to the radio button. When I set the flag to false through JavaScript, it does not reflect on the HTML and the radio button remains unchanged.
Am I doing something fundamentally wrong with the implementation or is something wrong with ngDisabled?
Solved the issue.. added ng-value and ng-model:
<div class="buyBox" id="{{bBox.id}}" ng-repeat="bBox in bBoxProps" ng-class="{disabledBb: bBox.disabled, invalidBb: bBox.invalid}">
<div class="bbTitle"><h3>{{bBox.title | uppercase}}</h3></div>
<div class="bbSelect">
<div class="bbSelectTop bbSelectOpt">
<input type="radio" name="{{bBox.id}}" id="{{bBox.options[0].optId}}" class="css-checkbox" ng-click="pmFlow(state,this,bBox.options[0])" ng-checked="bBox.options[0].isSelected==true" ng-model="bBox.options[0].isSelected" ng-disabled="bBox.options[0].isDisabled" ng-class="{invalidBbOpt: bBox.options[0].isInvalid}" ng-value="true"/>
<label for="{{bBox.options[0].optId}}" class="bbLabel"><div class="bbLabelText">{{bBox.options[0].name}}</div></label>
</div>
<div class="buyOr">OR</div>
<div class="bbSelectBottom bbSelectOpt">
<input type="radio" name="{{bBox.id}}" id="{{bBox.options[1].optId}}" class="css-checkbox" ng-click="pmFlow(state,this,bBox.options[1])" ng-checked="bBox.options[1].isSelected==true" ng-model="bBox.options[1].isSelected" ng-disabled="bBox.options[1].isDisabled" ng-class="{invalidBbOpt: bBox.options[1].isInvalid}" ng-value="true"/>
<label for="{{bBox.options[1].optId}}" class="bbLabel"><div class="bbLabelText">{{bBox.options[1].name}}</div></label>
</div>
</div>
</div>

Resources