How to set a default value for AngularJS ng-repeat? - angularjs

<li ng-repeat="item in quantityList track by $index" ng-model="isPageValid='true'">
<input value="item.quantity" ng-blur="validateQuantity(item)" ng-model="item.quantity">
</li>
I'm trying to set a default value for a status variable each time an ng-repeat loop occurs. I've tried ng-model, but that doesn't work. For instance,
I'd like to set isPageValid="true" before each time the ng-repeat loop runs. 'True' is will be the default value, and the validation function will test whether isPageValid should be set to 'false'.
I'd like the ng-repeat loop to run each time the ng-blur is exercised.
NOTE: I understand the way I'm using ng-model is incorrect, but this is just to illustrate the issue.
HTML:
<li ng-repeat="item in quantityList track by $index" ng-model="isPageValid='true'">
<input value="item.quantity" ng-blur="validateQuantity(item)" ng-model="item.quantity">
</li>
JS:
scope.validateQuantity = function(item){
var qty = item.quantity;
if(parseInt(qty) >=1 && parseInt(qty) <= 200){
item.isQuantityValid = true;
}else{
item.isQuantityValid = false;
scope.isPageValid = false;
}
}
The loop creates a list of input boxes. The objective is to create a global validation value called isPageValid which is 'false' if the validation by the JS fails for any input box. Note, when ng-blur is exercised, the JS validation runs and loop should re-run.

I believe ng-init could help...
<ul ng-init="isPageValid='true'">
<li ng-repeat="item in quantityList track by $index" >
<input ng-blur="validateQuantity(item)" ng-model="item.quantity">
</li>
</ul>
Note that it would be better practice to initialise isPageValid in the controller that is in the same scope as your validateQuantity function.

Here is an example of how you could initialise isPageValid in your controller and update the value after each call to validateQuantity...
In your controller:
scope.isPageValid = true;
function updatePageValid() {
scope.isPageValid = scope.quantityList.every(item => item.isQuantityValid);
}
scope.validateQuantity = function(item) {
var qty = parseInt(item.quantity);
item.isQuantityValid = (qty >= 1 && qty <= 200);
updatePageValid();
});

Related

ng-class not working with ng-repeat

I have a situation where I have to add class according to the condition and the ng-class is working according to it even the condition in the ng-class is true.
<ul id="" class="clowd_wall" dnd-list="vm.cardData[columns.id].data"
dnd-drop="vm.callback(item,{targetList: vm.cardData[columns.id].data, targetIndex: index, event: event,item:item,type:'folder',eventType:'sort','root':'folder',current_parent:'folder'})" ng-model="vm.cardData[columns.id].data">
<div class="emptyCol" ng-if="vm.cardData[columns.id].data.length==0">Empty</div>
<li class="dndPlaceholder"></li>
<li class="cont____item" ng-repeat="card in vm.cardData[columns.id].data | orderBy:vm.sort" dnd-draggable="card"
dnd-effect-allowed="move"
dnd-allowed-types="card.allowType"
dnd-moved="vm.cardData[columns.id].data.splice($index, 1)"
dnd-selected="vm.tree.selected = card" ng-class="{emptyCard:card.data.length==0,zoomin:vm.zoomin=='zoomin',emptyCard:!card.data}">
<div class="item" style="height:79%">
<ng-include ng-init = "root = columns.id" src="'app/partials/card.html'"></ng-include>
</div>
</li>
</ul>
ng-class="{'emptyCard': (!card.data || !vm.cardData[columns.id].data.length),'zoomin':(vm.zoomin=='zoomin')}">
Seems like you want to use vm.cardData[columns.id].data.length instead of card.data.length
Your question is not clear as don't know what card.data will contain and ".data" will be present for each iteration
If it is array then this will work "card.data.length" and if there is no "data" key in "card" then ".length" will through error i.e. if card.data itself undefined then it will not have "length" property.
Try to add condition in ng-class one by one then you will be able to figure out which condition is causing problem.
Made some small change
ng-class="{emptyCard: card.data.length==0 || !card.data,zoomin: vm.zoomin=='zoomin'}"
If you have multiple expression, try old fashioned, if it looks best:
Controller:
$scope.getcardClass = function (objCard, strZoomin) {
if (!card.data) {
return 'emptyCard';
} else if (strZoomin =='zoomin') {
return 'zoomin';
} else if (card.data.length == 0) {
return 'emptyCard';
}
};
HTML:
ng-class="vm.getcardClass(card, vm.zoomin)"
NOTE: Replace vm with your controller object.

AngularJS ng-checked isn't updating checkbox when model changed in javascript

I have a filtered list of objects being repeated with ng-repeat with an input checkbox beside each item. When the list isn't filtered (as it is when the page is loaded) then I don't want the checkboxes checked. If the list is filtered I do want the checkboxes checked (the checkboxes form a treeview via CSS).
The checkbox has ng-checked="{{site.isChecked}}". When the list is filtered I am updating the isChecked variable on the objects within the filter javascript code, but this isn't updating the checkbox value. If the item is filtered out so it's removed from screen and then filtered back in again the updated isChecked value will come through to the screen.
The HTML is as follows:
<ul>
<li ng-repeat="site in sites | filterSites:searchBuildings">
<input type="checkbox" ng-checked="{{site.isChecked}}" id="item-f{{site.id}}" /><label for="item-f{{site.id}}">{{site.site}}</label>
<ul>
<li ng-repeat="building in site.filteredBuildings">
{{building.address}}
</li>
</ul>
</li> </ul>
The JS is:
var filtered = [];
searchBuildings = searchBuildings.toLowerCase();
angular.forEach(sites, function (site) {
var added = false;
var siteMatch = false;
site.isChecked = true;
if (site.site.toLowerCase().indexOf(searchBuildings) !== -1)
siteMatch = true;
angular.forEach(site.buildings, function (building) {
if (siteMatch == true || building.search.toLowerCase().indexOf(searchBuildings) !== -1) {
if (added == false) {
added = true;
filtered.push(site);
site.filteredBuildings = [];
}
site.filteredBuildings.push(building);
}
});
});
return filtered;
Sorry if the code isn't very pretty - I'm new to AngularJS and JS and still trying to work out how things link together.
Thanks
You should use ng-model there that would provide you two way binding. Checking and unchecking the value would update the value of site.isChecked
<input type="checkbox" ng-model="site.isChecked" id="item-f{{site.id}}"/>

dynamically change options in dropdown list in angular js

i tried to create dynamically changing dropdown list in angularJS
angulars.js
var option1Options = ["Class","Category","Option","Question","Group"];
var option2Options = [["Group","ProductModel"],
["Class","ProductModel"],
["Class","Group","ProductModel"],
["Group","ProductModel"],
["ProductModel"]];
$scope.myCtrl= function()
{
$scope.options1 = option1Options;
$scope.options2 = [];
$scope.getOptions2 = function(){
var key = $scope.options1.indexOf($scope.child);
$scope.options2 = option2Options[2];
};
}
page.html
<div id="CreateChild" ng-controller="myCtrl">
<select ng-model="child" ng-options="option for option in options1" ng-change="getOptions2()">
</select>
<select ng-model="parent" ng-options="option for option in options2">
</select>
</div>
in angulars.js i was unable to get the index of first dropdown list array. the value of key is assigned as -1 and the option2 is assigned as undefined.
can any one help me with this
I did a small workaround for this requirement, though it is not a straight answer, I believe this would help you...
Add this to your controller...
$scope.getOptions1Idx = function(){
var mySelectedOption = $scope.child;
var i = 0;
for(i=0;i< option1Options.length;i++){
if(option1Options[i]==mySelectedOption){
break;
}
}
return i;
}
and change your getOptions2 function as follows
$scope.getOptions2 = function(){
$scope.options2 = option2Options[getOptions1Idx()];
};
This can be done in much better fashion by avoiding for loop provided if you choose to change your array structure with predefined index some thing like var option1Options = [{id:0,option:"Class"},{id:1,option:"Category"},{id:2,option:"Option"},{id:3,option:"Question","Group"}];
Had a very similar problem with this. In terms of styling I found my way around it by creating a list instead of a select option
<div class='btn-group'>
<button class='form-control col-md-3' data-toggle='dropdown'>
{{value}} <span class='caret'></span>
</button>
<ul class='dropdown-menu'>
<li ng-repeat='type in callType' class='col-md-3'>
<a href='#' ng-click='select(type)'>{{type.name}}</a>
</li>
</ul>
</div>
Then the controller is used to take in the objects, call a method to change each object and then set a default for the drop down list. You can see it at the link below.
http://plnkr.co/edit/nwXmMif8vjj92pQmalb2

AngularJS - how to highlight/add class to a max value

Let say I have a very simple data that Im looping through with ng-repeat.
Now, how can I highlight (add a css class) to a highest value in the data.
Data:
$scope.marks = [
{point:'11'},
{point:'2'},
{point:'23'}
];
html:
<ul>
<li ng-repeat="value in marks" class={{here add class for value 23}}> //how to add class to li with max value, in this case it is 23
{{ value.point}}
</li>
</ul>
Many thanks for your help
PLUNKR
You can use calculate the max value in a watch:
$scope.$watchCollection('marks', function(items) {
$scope.maxPoint = -1; // assuming we won't have negative values
angular.forEach(items, function(item) {
if (parseInt(item.point) > $scope.maxPoint) {
$scope.maxPoint = item.point;
}
});
});
Then use ngClass directive in your markup:
<li ng-repeat="value in marks" ng-class="{max : value.point == maxPoint}">
{{ value.point}}
</li>
Like Petr pointed out this won't perform well. Calculating the max value on changes is a better way. Here's a working plunk : http://plnkr.co/edit/F8yjoWR0ZWVF4tcck1rH?p=preview

Angularjs - Pagination appear after search filter

I am newbie on AngularJS.
Search result can be displayed in one page but why the next and previous button is showing ?
http://jsfiddle.net/2ZzZB/1473/
<input type="text" id="txtNotessearch" ng-model="search_notes" class="form-control input-sm" placeholder="SEARCH">
...
<ul>
<li ng-repeat="item in data | filter:search_notes | startFrom:currentPage*pageSize | limitTo:pageSize">
{{item}}
</li>
</ul>
Correct me, if I am wrong.
Because NumberOfPages is not filtered.
Instead of using $scope.data.length, you should use the length after the filter.
function MyCtrl($scope, $filter) { //Do not forget to inject $filter
$scope.currentPage = 0;
$scope.pageSize = 10;
$scope.data = [];
$scope.numberOfPages=function(){
var myFilteredData = $filter('filter')($scope.data,$scope.search_notes); //Filter the data
return Math.ceil(myFilteredData.length/$scope.pageSize);
}
for (var i=0; i<45; i++) {
$scope.data.push("Item "+i);
}
}
In addition, I would modify the ng-disable next button to
button "ng-disabled="(currentPage + 1) == numberOfPages()"
And I would add to search_notes onchange currentPage=1.
Here you have the fiddle
http://jsfiddle.net/rLots5zd/
In case, you want to hide the next and previous button when the result can be displayed in one page, please see the fiddle here: http://jsfiddle.net/rLots5zd/3/

Resources