Checked checkbox ng-change not firing first time - angularjs

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)"
/>

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>

AngularUI Bootstrap typeahead showing "No Results" instead of drop down objects

My AngularUI bootstrap typeahead is returning "No Results Found" even though it should be reading through an array of Objects.
in uib-typeahead I have uib-typeahead="number for number in getNumbers($viewValue)"
and in my controller I have
$scope.getNumbers = function($viewValue) {
...stuff to retrieve numbers...
return array
}
where console.log(array) shows [Object, Object, Object...]
I'm just trying to show the bits of code that I think are relevant. Is this where the problem is? Why is the dropdown returning No Results found?
<input
type="text"
class="form-control"
name="number"
ng-model="numberinfo.number"
uib-typeahead="number for number in getNumbers($viewValue)"
typeahead-template-url="/tpl.html"
typeahead-loading="Loadinglocations"
typeahead-on-select="numberSelect($item, 10)"
typeahead-wait-ms="3"
typeahead-min-length="3"
typeahead-no-results="noResults"
required>
<i ng-show="loadingLocations" class="glyphicon glyphicon-refresh">Loading...</i>
<div ng-show="noResults">
<i class="glyphicon glyphicon-remove"></i> No Results Found.
</div>
<script type="text/ng-template" id="/tpl.html">
<a>
<div>
<span style="display:block;" class="registration"
ng-bind-html="match.model.number | uibTypeaheadHighlight:query"></span>
</div>
</a>
</script>
your controller is consoling the object but your uib-typehead is not getting it its could be because of this parameter
$scope.getNumbers = function($viewValue)
change it to
$scope.getNumbers = function(viewValue)

ng-models name collision inside ng-repeat

http://plnkr.co/edit/2UFfaG?p=preview
I used this sample code to build a simple app and I noticed that the edit function doesn't work when you are using ng-models that are repeated in a loop. I know this, because I tried using ng-models outside of the ng-repeat loop and it worked perfectly. So when you have two instances of ng-models with the same name, you get a blank data back when you try to get the values back from the view.
This is my view:
<ul ng-repeat="notes in notes">
<li>
<span ng-hide="editing" ng-click="editing = true">{{note.name}} | {{note.content}}</span>
<form ng-show="editing" ng-submit="editing = false">
<label>Name:</label>
<input type="text" ng-model="name" placeholder="Name" ng-required/>
<label>Content:</label>
<input type="date" ng-model="content" placeholder="Content" ng-required/>
<br/>
<button class="btn" ng-click="edit(note.id)">Save</button>
</form>
</li>
</ul>
This is my edit method:
$scope.edit = function (id) {
var note = notesRef.child(id);
var newNote= {
name : $scope.name,
content : $scope.content
}
};
note.update(newNote);
};
When I refer to a ng-model inside of ng-repeat, I can only get the value null for some reason. I get the correct value when I refer to ng-models outside of the ng-repeat for some reason.
How do we solve this problem? What's the simplest solution?
The problem is that the item belongs to the scope of the repeat.
If you changed your ng-model to:
<ul ng-repeat="notes in notes">
<li>
<span ng-hide="editing" ng-click="editing = true">{{note.name}} | {{note.content}}</span>
<form ng-show="editing" ng-submit="editing = false">
<label>Name:</label>
<input type="text" ng-model="note.name" placeholder="Name" ng-required/>
<label>Content:</label>
<input type="date" ng-model="note.content" placeholder="Content" ng-required/>
<br/>
<button class="btn" ng-click="edit(note)">Save</button>
</form>
</li>
</ul>
Where it's now note.name / note.content.
Then instead of padding the note.id to the edit button, you pass in the entire note i.e ng-click="edit(note)"
Then your controller will get passed the entire note.
$scope.edit = function (note) {
// send note to server via $http, changes to `note` are already made directly to the note itself
};
Hope that makes sense.
it should be like this. As we know ng-repeats directive create their own new scope.
bday.editing
<ul ng-repeat="bday in bdays">
<li>
<span ng-hide="bday.editing" ng-click="bday.editing = true">{{bday.name}} | {{bday.date}}</span>
<form ng-show="bday.editing" ng-submit="bday.editing = false">
<label>Name:</label>
<input type="text" **ng-model="bday.name"** placeholder="Name" ng-required/>
<label>Date:</label>
<input type="date" **ng-model="bday.date"** placeholder="Date" ng-required/>
<br/>
<button class="btn" type="submit">Save</button>
</form>
</li>
</ul>
and here what I understand from your question is that you want to edit only the item on which you have click. this is the solution for the same.
One more solution for the same problem is that create a new function that take one argument that is "bday". make edit true only for this item and set editing false for all others element. this solution is for that case if user doesn't submit the form and click on other item.

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