I am new to AngularJs and I am curious on what is the best approach to getting then index of an ngrepeat on an input and comparing to see if the new string is different from the original value:
js:
var checkIfDataSampleHasChanged = document.getElementById('dsField' + i).value;
console.log(checkIfDataSampleHasChanged);
console.log($scope.currentSchema)
if (checkIfDataSampleHasChanged != $scope.currentSchema.sDataSamples.dsName) {
console.log("hello there")
$scope.currentSchema.sDataSamples.dsName = checkIfDataSampleHasChanged;
}
html:
<fieldset ng-repeat="ds in currentSchema.sDataSamples track by $index">
<label for="{{dsField$index}}" style="width:400px;">
Data Sample Name ({{ds.dsFileName}}):</label>
<input name="{{dsField$index}}" type="text" style="width: 400px;" ng-model="currentSchema.sDataSamples[$index].dsName" value="{{ds.dsName}}" />
<br>
<br>
</fieldset>
You can use a data to hold the initial value and then compare the changed value. You can do this in pure angularjs constructs without using document.getElementById and other hacks:
angular
.module('app', [])
.controller('AppController', function ($scope) {
var initialSample = [
{id: 1, name: 'Abc'},
{id: 2, name: 'def'},
{id: 3, name: 'ghi'},
{id: 4, name: 'jkl'},
{id: 5, name: 'mno'}
];
$scope.sample = angular.merge([], initialSample);
$scope.checkIfValueChanged = function ($index) {
var isValChanged = initialSample[$index].name !== $scope.sample[$index].name;
console.log(isValChanged);
if (isValChanged) {
alert("Value has changed");
} else {
alert("Value has not changed");
}
};
$scope.changeVal = function(){
var randInt = Math.floor(Math.random() * 5);
console.log(randInt);
$scope.sample[randInt].name = "Lorem ipsum";
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
<div ng-app='app' ng-controller='AppController'>
<ul>
<li ng-repeat="item in sample" ng-click="checkIfValueChanged($index)">
{{item.name}}
</li>
</ul>
<button ng-click="changeVal()"> Change random value </button>
</div>
Related
I'm using angularjs and I have data like this :
$scope.users = [{
name: "Pratik"
queue: [{number: "199"},{number: "111"}],
status: "OK"
}]
My view :
.available{
background-color: #00226f;
color: #f8f8f8;
}
<div class="col-xs-12 col-sm-3" ng-repeat="user in users">
<span ng-class="{'available': user.queue[0].number == 111}" class="badges ">111</span>
</div>
My problem is that I want to assign the class "available" if the queue array in users contains the number "111" at any index. In the users array the number:"111" may appear at any index so in the view I can't always use user.queue[1].number == 111 or user.queue[1].number == 111 to assign the class. I want a solution which will check if the queue array contains number:"111" and assign the class of available accordingly.
I tried to do it like this : ng-class="{'available': user.queue[i].number == 111}" but it's not working. How do I do it?
This my current workaround to apply the class:
ng-class="{'available': user.queue[0].number == 111 || user.queue[1].number == 111}"
try below code snippet
can achieve by using lodash js also using _.filter
_.filter(array, { 'number': '111' } )
Ref: https://lodash.com/docs/4.17.11#find
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.findObjectByKey = function(array, key, value) {
for (var i = 0; i < array.length; i++) {
if (array[i][key] === value) {
return array[i];
}
}
return null;
};
$scope.users = [{
name: "Pratik",
queue: [{number: "199"},{number: "666"}],
status: "OK"
},
{
name: "Pratik 2",
queue: [{number: "111"},{number: "555"}],
status: "OK 2"
},
{
name: "Pratik 3",
queue: [{number: "999"},{number: "888"}],
status: "OK 3"
}
];
$scope.searcInArray = function(array){
// var obj = $scope.findObjectByKey(array, 'number', '111');
// using loadsh
var obj = _.filter(array, { 'number': '111' } );
return obj.length > 0;
};
}
.available{
background-color: #00226f;
color: #f8f8f8;
}
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
</head>
<body>
<div ng-app="myApp" ng-controller="MyCtrl">
<div class="col-xs-12 col-sm-3" ng-repeat="user in users">
<span ng-class="{'available' : searcInArray(user.queue)}" class="badges ">111</span>
</div>
</div>
</body>
</html>
You have to add use ng-repeat to loop all queue and find how has item.number == '111'
<div class="col-xs-12 col-sm-3" ng-repeat="user in users">
<div ng-repeat="item in user.queue">
<span ng-class="{'available': item.number == '111'}" class="badges ">111</span>
</div>
</div>
NOTE!
if you want show only the item.number == '111' you can use ng-hide/show
To check that condition where 111 appears at any index the easy fix could be to call a function that will check that property in the array and return true or false based on the condition. Something like below:
var app = angular.module('myApp', []);
app.controller('MainCtrl', ['$scope', function($scope){
$scope.users = [{
name: "Pratik",
queue: [{
number: "111"
}, {
number: "119"
}],
status: "OK"
},
{
name: "Pratik123",
queue: [{
number: "199"
}, {
number: "185"
}],
status: "OK"
}];
$scope.checkQueue = function(queue){
return queue.find(({number})=>number === '111');
}
}]);
.available {
background-color: #00226f;
color: #f8f8f8;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MainCtrl">
<div class="col-xs-12 col-sm-3" ng-repeat="user in users">
<span ng-class="{'available': checkQueue(user.queue)}" class="badges ">{{user.name}}</span>
</div>
</div>
i listed category from json data.i have listed number of sub category under category but i want to list only 3 sub category under category.if i click view more option i want to list corresponding sub category depends on category in modal popup.
i have returned created div depends on parentid zero
$scope.cat = categories.filter(function(category) {
return category && category.parentid === 0
});
i have updated my code in plunker.
http://plnkr.co/edit/Vh1NzYf0qjUkIygLUEJk?p=preview
You can do it by simlpe filter:
<div ng-repeat="childItem in content | filter: item.id | limitTo: 3">
Demo 1 plunker
It also will get rid of using ng-if="childItem.parentid === item.id"
Example:
<div ng-repeat="item in cat">
{{item.name}}
<div ng-repeat="childItem in content | filter: item.id | limitTo: 3">
<div style="margin-left: 20px;" >
{{childItem.name}}
</div>
</div>
</div>
If you want to handle view more, you can write:
<div ng-repeat="childItem in content | filter: item.id | limitTo: limit">
and:
$scope.limit = 3;
$scope.viewMore = function(){
$scope.limit = 100;
}
Demo 2 plunker
[EDIT]
if you want to update view more per sub-category, you need bind limit to your data:
<body ng-controller="MainCtrl">
<div ng-repeat="item in cat">
{{item.name}}
<div ng-repeat="childItem in content | filter: item.id | limitTo: item.limit">
<div style="margin-left: 20px;" >
{{childItem.name}}
</div>
</div>
<a href="" ng-click="viewMore(item)"
ng-if="item.limit == 3">view more</a>
</div>
</body>
and:
$scope.viewMore = function(item){
item.limit = 100;
}
Demo 3 plunker
Update
If you want a show more functionality refer the below Plunkr.
Plunkr
This will do the job. I have added a custom filter that takes the parent.Id as an argument and check the child's parent Id (which was done before by the ng-if). Then I use angular's limit to: 3 filter to limit the results to only 3 items.
Plunkr
Code:
$scope.searchMe = function(statusId) {
return function(user) {
return user.parentid === statusId;
}
}
and the ng-repeat should look like
<div ng-repeat="item in cat">
{{item.name}}
<div ng-repeat="childItem in content | filter: searchMe(item.id) | limitTo: 3">
<div style="margin-left: 20px;">
{{childItem.name}}
</div>
</div>
<a ng-click="open_modalpopup()">view more</a>
</div>
References:
Limit To
passing arguements to angularJS filters
UPDATE -
As per your latest requirement -
if i click view more i want to list all corresponding sub category
depends on category
I update the plnkr to show all categories in a popup once user clicked on View More button.
Updated Plnkr - http://plnkr.co/edit/OUvzqWdfZuQnZpbXWSRW?p=preview
As per your requirement I believe you need to show/hide sub categories on the basis of button click available under specific category.
I re arranged your data and rather than saving it into multiple objects, I am using a singular object newcat to store and manage the UI.
Working Plnkr -
http://plnkr.co/edit/F6MlkMWOJ2b7isRAM1u6?p=preview
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
var data = [{
id: 1,
name: 'mobile',
parentid: 0
}, {
id: 2,
name: 'samsung',
parentid: 1
}, {
id: 3,
name: 'moto',
parentid: 1
}, {
id: 4,
name: 'redmi',
parentid: 1
}, {
id: 5,
name: 'honor',
parentid: 1
}, {
id: 6,
name: 'nokia',
parentid: 1
},
{
id: 7,
name: 'tv',
parentid: 0
}, {
id: 8,
name: 'tv1',
parentid: 7
}, {
id: 9,
name: 'tv2',
parentid: 7
}, {
id: 10,
name: 'tv3',
parentid: 7
}, {
id: 11,
name: 'tv4',
parentid: 7
}, {
id: 12,
name: 'tv5',
parentid: 7
}];
var categories = data;
$scope.title = 'Show Hide Subcategories';
$scope.cat = categories.filter(function(category) {
return category && category.parentid === 0
});
$scope.newcat = angular.extend($scope.cat, {});
angular.forEach($scope.cat, function(cat, key){
var tmpIndex = 0;
var tmpdata = categories.filter(function(category) {
if(cat.id === category.parentid) {
category.indexVal = tmpIndex;
category.isShow = tmpIndex < 3 ? true : false;
tmpIndex++;
return true;
}
})
$scope.newcat[key]['subCat'] = tmpdata;
$scope.newcat[key]['moreclicked'] = false;
})
$scope.showMore = function(index) {
if(!$scope.newcat[index]['moreclicked']) {
angular.forEach($scope.newcat[index].subCat, function(subcat, key) {
subcat.isShow = true;
})
$scope.newcat[index]['moreclicked'] = true;
}
else {
angular.forEach($scope.newcat[index].subCat, function(subcat, key) {
if(key > 2)
subcat.isShow = false;
})
$scope.newcat[index]['moreclicked'] = false;
}
};
});
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>
document.write('<base href="' + document.location + '" />');
</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.5.x" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.11/angular.min.js" data-semver="1.5.11"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<h3 ng-bind="title"></h3>
<div ng-repeat="cat in newcat">
<b>{{cat.name}}</b>
<div ng-repeat="subcat in cat.subCat">
<div style="margin-left: 20px;" ng-if="subcat.isShow">
{{subcat.name}}
</div>
</div>
<button ng-click="showMore($index)" ng-bind="!cat.moreclicked ? 'View More': 'View Less'"></button>
</div>
</body>
</html>
I have multiple input fields that I am currently filtering a ng-repeat by like so
...
<input class="form-control" type="text" ng-model="itemFilter.id" />
<input class="form-control" type="text" ng-model="itemFilter.attr1" />
<input class="form-control" type="text" ng-model="itemFilter.attr2" />
...
<tr ng-repeat="item in $scope.items | filter:itemFilter | orderBy: '-id' track by $index"> <td>{{item.id}}</td>
</tr>
...
How can I filter on the tokens from each the inputs?
For example, if itemFilter.id = "1 2 3" the ng-repeat would include ids that contain 1,2, or 3
As #Andrei mentioned, you have to write your own custom filter to achieve the desired functionality. The code below illustrates how it could be created and how the parameters could be passed to perform custom filtering logic.
The idea here is to build an array of tokens for each object property using split() and then check if item satisfy the filters using filter() on filters array:
(function (angular) {
'use strict';
angular.module("demo", [])
.filter("filterByTokens", function () {
return function (items, obj) {
var separator = obj.separator || ' ';
var keys = Object.keys(obj).filter(function (key) {
return key !== 'separator'
});
//create filters array
var filters = keys.map(function (key) {
return {
key: key,
values: (obj[key] || '').split(separator).filter(function (val) {
return !!val;
})
}
});
if (!filters.length) return items;
return items.filter(function (item) {
return filters.filter(function (f) {
return !f.values || !f.values.length || (f.values.indexOf(item[f.key].toString()) > -1);
}).length === filters.length; // we want to check if all filters are satisfied
});
};
})
.controller('Demo', [function Demo() {
var vm = this;
vm.itemFilter = {id:'1 3 5 2 6', name: 'Test5 Test6', separator: ' '};
vm.items = [
{id: 1, name: 'Test1'}, {id: 2, name: 'Test2'}, {id: 3, name: 'Test3'},
{id: 4, name: 'Test4'}, {id: 5, name: 'Test5'}, {id: 6, name: 'Test6'},
];
}]);
})(angular);
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<div ng-app="demo" ng-controller="Demo as vm">
<hr/>
<input class="form-control" type="text" ng-model="vm.itemFilter.id" placeholder="itemFilter.ids"/>
<input class="form-control" type="text" ng-model="vm.itemFilter.name" placeholder="vm.itemFilter.names"/>
<hr/>
<code>Filter: {{vm.itemFilter}}</code>
<hr/>
<div ng-repeat="item in vm.items | filterByTokens:vm.itemFilter | orderBy: '-id' track by item.id">
<span>
{{item.id}}
</span>
<span>
{{item.name}}
</span>
</div>
</div>
P.S.: Possibly not the most performant solution, but just a demonstration of how this could be achieved using filters.
Here, I used $watch to display the counter value.
But the counter value not increased yet,
To Count,
$scope.$watch('items', function(items){
var selectedItems = 0;
angular.forEach(items, function(item){
selectedItems += item.selected ? 1 : 0;
})
$scope.selectedItems = selectedItems;
}, true);
In UI,
<div class="col-sm-4" ng-repeat="item in items">
<label class="chkbox-holder cbox mbot10" for="List-{{$index}}"><input ng-model="item.Selected" type="checkbox" id="List-{{$index}}"><label for="List-{{$index}}"></label>{{item.name}}</label>
</div>
To display the counter value,
<div>Selected Items Length: {{selectedItems}}</div>
But still the counter is 0;
JSON Value from http service is,
[
{
"id": 1,
"refCode": "",
"name": "pragadees"
},
{
"id": 2,
"refCode": "",
"name": "pragadees"
}......]
Can anyone please help on this.
You've just got a typo error. Your markup is bound to item.Selected while your JavaScript is checking for item.selected. Renaming them properly solves your problem. I'd recommend using lower key inside ot html.
<input ng-model="item.selected" type="checkbox" id="List-{{$index}}">
^-- See here
Demo
first of all, you got a typo in your ng-model, it is item.selected not item.Selected that's maybe why it does not match nothing...
And this is how i'll write it, using basic angular two way data binding, no extra counters, watches, triggers, ....
angular.module('myApp', []);
angular.module('myApp').controller('Ctrl', ['$scope', function($scope) {
$scope.items = [{
name: "Doe"
}, {
name: "Adam"
}, {
name: "Ado"
}, {
name: "Brown"
}, {
name: "Heather"
}, {
name: "Stan"
}];
$scope.itemsSelected = function() {
return $scope.items.filter(function(i) {
return i.selected
}).length;
}
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp" ng-controller="Ctrl">
<h2>current active selected options {{ itemsSelected() }}</h2>
<ul>
<div ng-repeat="item in items">
<label for="List-{{$index}}">
<input ng-model="item.selected" type="checkbox" id="List-{{$index}}">
<label for="List-{{$index}}"></label>{{item.name}}</label>
</div>
</ul>
</body>
You can use ng-change instead:
var app = angular.module("app", []);
app.controller("myCtrl", function($scope) {
$scope.items = [
{name: 'A', value: 'a'},
{name: 'B', value: 'b'},
{name: 'C', value: 'c'},
{name: 'D', value: 'd'},
{name: 'E', value: 'e'}
];
$scope.counter = 0;
$scope.change = function(e) {
if(e){
$scope.counter +=1;
}else{
if($scope.counter > 0) $scope.counter -=1;
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="myCtrl">
<div class="col-sm-4" ng-repeat="item in items">
<label class="chkbox-holder cbox mbot10" for="List-{{$index}}">
<input ng-model="item.Selected" type="checkbox" id="List-{{$index}}"
ng-change="change(item.Selected)">
<label for="List-{{$index}}"></label>{{item.name}}</label>
</div>
Counter: {{counter}}
</div>
I'm building an AngularJS app. I have this array:
$scope.products = [
{name: 'cake (just it!)'},
{name: 'orange cake'},
{name: 'cheesecake'}
];
then I use ng-repeat for show it.
<li ng-repeat="product in products | filter : { name : word }">
{{ $product.name }}
</li>
I want to add a filter that will search the beginning of each word inside the phrase, so if I do this:
$scope.word = 'ca';
It will return the following array:
$scope.products = [
{name: 'cake (just it!)'},
{name: 'orange cake'}
];
You could do it using a custom filter as mentioned below
var app = angular.module("sampleApp", []);
app.controller("sampleController", ["$scope",
function($scope) {
$scope.products = [{
name: 'cake (just it!)'
}, {
name: 'orange cake'
}, {
name: 'cheesecake'
}, {
name: 'cheese'
}, {
name: 'cheeseca ca'
}];
}
]);
app.filter("nameFilter", function() {
return function(names, contains) {
return names.filter(function(obj) {
var expString = '(\\w*\\s|^)' + contains + '';
var exp = new RegExp(expString, "g");
if (exp.test(obj.name))
return name;
});
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="sampleApp">
<div ng-controller="sampleController">
<ul>
<li ng-repeat="product in products | nameFilter : 'ca' ">
{{product.name}}
</li>
</ul>
</div>
</div>