ngClass not rendering properly - angularjs

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

Related

Input validation: Validation message and ng-disabled buttons not working as expected

I have the following code which I'm trying to validate using AngularJS:
<div ng-form="transWizard" novalidate>
<div style="word-wrap:break-word; padding-top:4px; padding-left:14px">
<p style="font-family:'MetricWeb-Regular'; font-size:17.5px;"><span style="font-family:'MetricWeb-Semibold'">Question {{carousel.currentQuestionIndex+1}}:</span> {{carousel.currentQuestionObject.question}}</p>
<ul style="padding-left:30px;">
<li ng-repeat="query in carousel.currentQuestionObject.choices" style="padding-bottom:5px;">
<input class="TWInputField" name="inputname"
type="{{carousel.currentQuestionObject.inputType}}" id="{{query.id}}"
ng-model="query.selected" ng-change="carousel.changeOnSelection(query.selected, query.id)"
value="" ng-value="true" ng-required="{{carousel.currentQuestionObject.inputType === 'radio' || carousel.currentQuestionObject.inputType === 'text' ? true : false}}">
<label for="{{query.id}}" style="font-family:'MetricWeb-Regular';font-size:17px;cursor:pointer"> {{query.question}}</label>
</li>
</ul>
<p class="msg-required" ng-show="transWizard.inputname.$invalid">
Input is required.
</p>
</div>
<div class="carousel-wizard-btn-container">
<div class="carousel-wizard-buttons" ng-click="carousel.wizardPrevious()" ng-hide="carousel.currentQuestionIndex == 0">Previous</div>
<div class="carousel-wizard-buttons" ng-click="carousel.wizardNext()" ng-hide="carousel.currentQuestionIndex == carousel.wizardQuestionSet.length - 1" ng-disabled="transWizard.$invalid">Next</div>
<div class="carousel-wizard-buttons" ng-click="carousel.showResults()" ng-show="carousel.currentQuestionIndex == carousel.wizardQuestionSet.length - 1" ng-disabled="transWizard.$invalid">Finish</div>
</div>
</div>
As you can see, I'm not using the <form> tag, but I've read that it's possible to validate even without using forms thanks to the ng-form directive.
My conditions are to require input only if type is radio or text.
However, when I executed this, I got the following:
ng-disabled is not working for the Next button. I can still click it even though I haven't selected any answers for the required sections.
Validation message only disappears when I click the last item in a set of radio buttoned-questions.
Am I missing something here?
Please help. Thank you.
your validation will not work as expected because u are using same name for input controls in ng-repeat.
you can use ng-form inside ng-repeat like this.
<div ng-form="transWizard" novalidate>
<li ng-repeat="query in carousel.currentQuestionObject.choices" style="padding-bottom:5px;">
<ng-form name="innerForm" >
<input class="TWInputField" name="inputname" type=" {{carousel.currentQuestionObject.inputType}}" id="{{query.id}}" ng-model="query.selected" ng-change="carousel.changeOnSelection(query.selected, query.id)" value="" ng-value="true" ng-required="{{carousel.currentQuestionObject.inputType === 'radio' || carousel.currentQuestionObject.inputType === 'text' ? true : false}}">
<label for="{{query.id}}" style="font-family:'MetricWeb-Regular';font-size:17px;cursor:pointer"> {{query.question}}</label>
<p class="msg-required" ng-show="innerForm.inputname.$invalid">
Input is required.
</p>
</ng-form>
</li>
</div>

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.

Checked checkbox ng-change not firing first time

This is my code:
$scope.toggleBandPics = function(bandid){
for (var picid in $scope.bands[bandid]['pics']) {
$scope.bands[bandid]['pics'][picid]['show'] = ($scope.bands[bandid]['pics'][picid]['show'] == 'true'? 'false': 'true');
}
}
<span ng-repeat="band in bands">
<div class="bandsfilter">
<span ng-show="bButtons">
<input class="checkbox"
name="{{band.urlbandname}}"
type="checkbox"
id="{{band.urlbandname}}"
ng-model="band.checked"
ng-checked="{{band.checked}}==true"
ng-true-value="{{band.checked}}==true"
ng-false-value="{{band.checked}}==false"
ng-change="toggleBandPics({{band.bandid}})"
/>
{{band.bandname}} ({{band.noOfPicsPerBand}})
<span id="counter{{band.bandid}}" class="hidden">
{{band.noOfPicsPerBand}}
</span>
<span>
</div>
</span>
<span ng-repeat="band in bands">
<span ng-repeat="picture in band.pics">
<div class='picture' ng-show="picture.show=='true'" ng-cloack>
<a class="shadowbox{{picture.bandid}} photo" rel="shadowbox[{{humanconcertdate}}]" title="{{picture.bandname}}, {{humanconcertdate}}, {{venuename}}" href="/concert2/{{band.concertid}}/{{band.bandid}}/{{picture.filename}}">
<img src="/concert2/{{picture.concertid}}/{{picture.bandid}}/{{picture.filename}}" alt="{{picture.bandname}}, {{humanconcertdate}}, {{venuename}}" />
</a>
</div>
</span>
</span>
Now, when I run this ng-change is fired except for the first time that a checked checkbox is unchecked. When it is checked again (so when it is clicked for the second time) it does fire.
Firstly, you don't need angular expression ({{}}) inside ng-
Secondly, model'll be default set by value boolean. you don't need ng-true-value or ng-false-value to set that. If you need other value except boolean you can use that
Try like this
<input class="checkbox"
name="{{band.urlbandname}}"
type="checkbox"
id="{{band.urlbandname}}"
ng-model="band.checked"
ng-change="toggleBandPics(band.bandid)"
/>

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>

ngRepeat orderBy update after ngModel is updated

I have a list of text fields with a button below it. I can add text fields to that list dynamically with AngularJS.
The text field by default has an empty value. But I want to order the position of the list item as soon as I update the value of that text field. But when I do that the orderBy isn't triggered.
How can I make this happen?
Here's a quick demo: http://jsfiddle.net/fqnKt/214/
I just wanted to specifically note why the example was wrong (because I had the same issue even though I was using the orderBy directive).
DO NOT USE
track by $index
In your ng-repeat
I think that this is what you want:
<div ng-app="myApp">
<div ng-controller="MyCtrl">
<ul>
<li ng-repeat="item in items | orderBy:'name'">
<input type="text" ng-model="item.name" /> {{item.name}}
</li>
</ul>
<input ng-model="newItem" type="text"></input>
<button ng-click="add(newItem)">Add</button>
</div>
</div>
Working Example

Resources