I am stuck in a situation where i have to find the data using filter in ng-repeat
Situation :
Data is an array of objects with name and status and status has property a
now want to filter objects having property status.a as started and in progress
I have tried multiple solution
Sol1:
ng-repeat="item in items | filter: {status :{a:'Not Started'},status: {a:'In Progress'}}
returns result : status.a of In Progress only
Sol2:
<p ng-repeat="item in items | filter: {status :{a:'Not Started' , a:'In Progress'}}">
{{ item.name }}
</p>
returns same result : status.a of In Progress only
html
<div ng-controller="mainCtrl">
<h1>List 1</h1>
<ul>
<li class="clearfix">
<label>
<input ng-model="tracks.ns"
ng-true-value="'Not Started'"
ng-false-value="''"
type="checkbox">
Not started
</label>
</li>
<li class="clearfix">
<label> <input ng-model="tracks.ip" ng-true-value="'In Progress'" ng-false-value="''" type="checkbox">In-progress </label>
</li>
<li class="clearfix">
<label> <input ng-model="tracks.do" ng-true-value="'Done'" ng-false-value="''" type="checkbox">Done </label>
</li>
</ul>
{{tracks.ns}}
<p ng-repeat="item in filteredItems">{{ item.name }}</p>
<h1>List 2</h1>
<p ng-repeat="item in items | filter: {status :{a:'Not Started' , a:'In Progress'}}">{{ item.name }}</p>
</div>
js
$scope.items = [{
name: "Alvi",
status: {
a: 'Not Started'
}
}, {
name: "Krane",
status: {
a: 'Done'
}
}, {
name: "Tate",
status: {
a: 'In Progress'
}
}, {
name: "Lorus",
status: {
a: 'In Progress'
}
}];
$scope.tracks = {ns: '',ip: '',done : ''}
Questions:
Can I achieve the desire result without custom filter ?
If yes than how without custom filter?
plunker: http://plnkr.co/edit/njsoPu1LHLmNmEx6lCew?p=preview
Use a function in the filter expression:
<p ng-repeat="item in items | filter : customFn">
{{ item.name }} {{ item.status }}
</p>
JS
$scope.customFn = function(value, index, array) {
console.log(value, index, array);
if (!value) return true;
if (value.status.a == 'Not Started') return true;
if (value.status.a == 'In Progress') return true;
//else
return false;
}
For more information, see AngularJS Filter Component Reference - filter
The DEMO on PLNKR
Related
I'm loading data from a database and save it to an array as follows:
$scope.allGroups = [{id: 1, groupName: group1}, {id: 2, groupName: group2}, ..]
In my view, I'm trying to select multiple group names as follows:
<div
class="drag-container avaliable-groups-connect groups-container schedule-container"
>
<div class="group" ng-repeat="m in allGroups">
<input type="checkbox" ng-model="m.selected" />
<span>{{ m.groupName }}</span>
</div>
</div>
I want to save selected items (m.selected) to an array one-by-one and bind that array to ng-model="schedule.selectedGroups"
How can I perform that? Thank you..
<div class="group" ng-repeat="m in allGroups" ng-init="m.selected = false">
<input type="checkbox" ng-model="m.selected" />
<span>{{ m.groupName }}</span>
</div>
Now your checkbox ng-model with modify the variable to true or false and in your js code
you can do like below.
$scope.schedule.selectedGroups = $scope.allGroups.filter(function (data) {
return data.selected === true;
});
I have tried to filter blank string item from ng-repeat. But didn't succeeded. Can someone please help me at this.
JSFiddel Link
HTML Code:
<div ng-app ng-controller="myCtrl">
<ul>
<li ng-repeat="detail in details | filter: filter2 ">
<p>{{detail.name}}</p>
</li>
</ul>
</div>
JS Code:
function myCtrl($scope) {
$scope.details = [{
name: 'Bill',
shortDescription: null
}, {
name: 'Sally',
shortDescription: 'A girl'
},{
name: 'Tally',
shortDescription: ''
}];
}
function filter2(detail){
if (item.shortDescription.length == 0){
return true;
}
else{
return false;
}
}
Expected Result:
/*
Expected Result
Bill
Sally
*/
<div ng-app ng-controller="myCtrl">
<ul>
<li ng-repeat="detail in details" ng-if="detail.shortDescription">
<p>{{detail.name}}</p>
</li>
</ul>
</div>
fiddle
I'm developoing a web app and stuck here:
Part of the HTML:
<div class="input-group">
<select name="select" class="form-control input-group-select" ng-options="key as key for (key , value) in pos" ng-model="word.pos" ng-change="addPos()">
<option value="">Choose a POS</option>
</select>
<span class="sort"><i class="fa fa-sort"></i></span>
</div>
<ul class="listGroup" ng-show="_pos.length > 0">
<li class="list" ng-repeat="item in _pos track by $index">
<span>
{{item.pos}}
<span class="btn btn-danger btn-xs" ng-click="delPos($index)">
<span class="fa fa-close"></span>
</span>
</span>
<!-- I wanna add the input which can add more list item to the item.pos-->
<div class="input-group">
<a class="input-group-addon add" ng-class=" word.newWordExp ? 'active' : ''" ng-click="addItemOne()"><span class="fa fa-plus"></span></a>
<input type="text" class="form-control exp" autocomplete="off" placeholder="Add explanation" ng-model="word.newWordExp" ng-enter="addExpToPos()">
{{word.newWordExp}}
</div>
</li>
</ul>
Part of the js:
$scope._pos = [];
$scope.addPos = function () {
console.log("You selected something!");
if ($scope.word.pos) {
$scope._pos.push({
pos : $scope.word.pos
});
}
console.dir($scope._pos);
//console.dir($scope.word.newWordExp[posItem]);
};
$scope.delPos = function ($index) {
console.log("You deleted a POS");
$scope._pos.splice($index, 1);
console.dir($scope._pos);
};
$scope.addItemOne = function (index) {
//$scope.itemOne = $scope.newWordExp;
if ($scope.word.newWordExp) {
console.log("TRUE");
$scope._newWordExp.push({
content: $scope.word.newWordExp
});
console.dir($scope._newWordExp);
$scope.word.newWordExp = '';
} else {
console.log("FALSE");
}
};
$scope.deleteItemOne = function ($index) {
$scope._newWordExp.splice($index, 1);
};
So, what am I wannt to do is select one option and append the value to $scope._pos, then display as a list with all of my selection.
And in every list item, add an input filed and add sub list to the $scope._pos value.
n.
explanation 1
explanation 2
explanation 3
adv.
explanation 1
explanation 2
So I don't know how to generate dynamic ng-model and use the value in javascript.
Normaly should like ng-model="word.newExplanation[item]" in HTML, but in javascript, $scope.word.newExplanation[item] said "item is not defined".
can any one help?
If I've understood it correclty you could do it like this:
Store your lists in an array of object this.lists.
The first object in the explanation array is initialized with empty strings so ng-repeat will render the first explanation form.
Then loop over it with ng-repeat. There you can also add dynamically the adding form for your explanation items.
You can also create append/delete/edit buttons inside the nested ng-repeat of your explanation array. Append & delete is already added in the demo.
Please find the demo below or in this jsfiddle.
angular.module('demoApp', [])
.controller('appController', AppController);
function AppController($filter) {
var vm = this,
explainTmpl = {
name: '',
text: ''
},
findInList = function (explain) {
return $filter('filter')(vm.lists, {
explanations: explain
})[0];
};
this.options = [{
name: 'option1',
value: 0
}, {
name: 'option2',
value: 1
}, {
name: 'option3',
value: 2
}];
this.lists = [];
this.selectedOption = this.options[0];
this.addList = function (name, option) {
var list = $filter('filter')(vm.lists, {
name: name
}); // is it in list?
console.log(name, option, list, list.length == 0);
//vm.lists
if (!list.length) {
vm.lists.push({
name: name,
option: option,
explanations: [angular.copy(explainTmpl)]
});
}
};
this.append = function (explain) {
console.log(explain, $filter('filter')(vm.lists, {
explanations: explain
}));
var currentList = findInList(explain);
currentList.explanations.push(angular.copy(explainTmpl));
}
this.delete = function (explain) {
console.log(explain);
var currentList = findInList(explain),
index = currentList.explanations.indexOf(explain);
if (index == 0 && currentList.explanations.length == 1) {
// show alert later, can't delete first element if size == 1
return;
}
currentList.explanations.splice(index, 1);
};
}
AppController.$inject = ['$filter'];
<link href="http://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet"/>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demoApp" ng-controller="appController as ctrl">
<select ng-model="ctrl.selectedOption" ng-options="option.name for option in ctrl.options"></select>
<input ng-model="ctrl.listName" placeholder="add list name" />
<button class="btn btn-default" title="add list" ng-click="ctrl.addList(ctrl.listName, ctrl.selectedOption)"><i class="fa fa-plus"></i>
</button>
<div class="list-group">Debug output - current lists:<pre>{{ctrl.lists|json:2}}</pre>
<div class="list-group-item" ng-repeat="list in ctrl.lists">
<h2>Explanations of list - {{list.name}}</h2>
<h3>Selected option is: {{ctrl.selectedOption}}</h3>
<div class="list-group" ng-repeat="explain in list.explanations">
<div class="list-group-item">
<p class="alert" ng-if="!explain.title">No explanation here yet.</p>
<div class="well" ng-if="explain.title || explain.text">
<h4>
{{explain.title}}
</h4>
<p>{{explain.text}}</p>
</div>Title:
<input ng-model="explain.title" placeholder="add title" />Text:
<input ng-model="explain.text" placeholder="enter text" />
<button class="btn btn-primary" ng-click="ctrl.append(explain)">Append</button>
<button class="btn btn-primary" ng-click="ctrl.delete(explain)">Delete</button>
</div>
</div>
</div>
</div>
</div>
Here I am using angular.js to show a list of people
<div class="recipient" ng-repeat="person in people">
<img src="{{person.img}}" /> person.name
<div class="email">person.email</div>
</div>
$scope.people = [{id:1}, {id:2}, {id:3}, {id:4}];
The looks is like below
What I want to do is I can select multiple items and by click a OK button, I can get a list of selected items. so If I select id 1 and id 2, then I want to get return a list of [{id:1},{id:2}]
How could I implement it in angular.js
Well I guess that if you're looping through a collection of people using a ng-repeat, you could add the ng-click directive on each item to toggle a property of you're object, let's say selected.
Then on the click on your OK button, you can filter all the people that have the selected property set to true.
Here's the code snippet of the implementation :
<div class="recipient" ng-repeat="person in people" ng-click="selectPeople(person)">
<img src="{{person.img}}" /> person.name
<div class="email">person.email</div>
</div>
<button ng-click="result()">OK</button>
function demo($scope) {
$scope.ui = {};
$scope.people = [{
name: 'Janis',
selected: false
}, {
name: 'Danyl',
selected: false
}, {
name: 'tymeJV',
selected: false
}];
$scope.selectPeople = function(people) {
people.selected = !people.selected;
};
$scope.result = function() {
$scope.ui.result = [];
angular.forEach($scope.people, function(value) {
if (value.selected) {
$scope.ui.result.push(value);
}
});
};
}
.recipient {
cursor: pointer;
}
.select {
color:green;
}
.recipient:hover {
background-color:blue;
}
<script src="https://code.angularjs.org/1.2.25/angular.js"></script>
<div ng-app ng-controller="demo">
<div class="recipient" ng-repeat="person in people" ng-click="selectPeople(person)" ng-class="{ select: person.selected }">
<div class="name">{{ person.name }}</div>
</div>
<button ng-click="result()">OK</button>
Result :
<ul>
<li ng-repeat="item in ui.result">{{ item.name }}</li>
</ul>
</div>
If you only want to show checked or unchecked you could just apply a filter, but you would need to toggle the filter value from undefined to true if you didn't wan't to get stuck not being able to show all again.
HTML:
<button ng-click="filterChecked()">Filter checked: {{ checked }}</button>
<div class="recipient" ng-repeat="person in people | filter:checked">
<input type='checkbox' ng-model="person.isChecked" />
<img ng-src="{{person.img}}" />{{ person.name }}
<div class="email">{{ person.email }}</div>
</div>
Controller:
// Apply a filter that shows either checked or all
$scope.filterChecked = function () {
// if set to true or false it will show checked or not checked
// you would need a reset filter button or something to get all again
$scope.checked = ($scope.checked) ? undefined : true;
}
If you want to get all that have been checked and submit as form data you could simply loop through the array:
Controller:
// Get a list of who is checked or not
$scope.getChecked = function () {
var peopleChkd = [];
for (var i = 0, l = $scope.people.length; i < l; i++) {
if ($scope.people[i].isChecked) {
peopleChkd.push(angular.copy($scope.people[i]));
// Remove the 'isChecked' so we don't have any DB conflicts
delete peopleChkd[i].isChecked;
}
}
// Do whatever with those checked
// while leaving the initial array alone
console.log('peopleChkd', peopleChkd);
};
Check out my fiddle here
Notice that person.isChecked is only added in the HTML.
I have this html :
<div class="{{ article.contributor }}" ng-repeat="article in articles">
Which gave me this :
<div class="["harry", "eddy", "john"]">
But I want this :
<div class="harry eddy john">
What is the best way to do this ?
Thank you very much
Try joining the array, like this:
<div class="{{ article.contributor.join(' ') }}" ng-repeat="article in articles">
Ohhh the choices... joyous choices.
Quick and dirty...
<div class="{{ typeof article.contributors === 'array' ? article.contributors.join(' ') : article.contributors }}" ng-repeat="article in articles"></div>
As a filter...
myAppname.module.filter('spaceSeperatedValues', function() {
return function(data){
//handles if just a string (e.g., 'John')
return data === 'array' ? data.join(' ') : data;
}
}
<div class="{{ article.contributors | spaceSeperatedValues }}" ng-repeat="article in articles"></div>
As a controller function..
app.module.controller('ArticleController', ['$scope'], function ($scope) {
$scope.articles = [{ text : 'my article text', contributors : ['harry', 'eddy', 'john'] }]
$scope.spaceSeperatedValues = function(data) {
//handles if just a string (e.g., 'John')
return data === 'array' ? data.join(' ') : data;
}
}
<div ng-controller="ArticleController">
<div class="{{ spaceSeperatedValues(article.contributors) }}" ng-repeat="article in articles"></div>
</div>
Have not checked this code in a debugger... <-- disclaimer. :D