ng-repeat filter on boolean - angularjs

I am trying to filter on a boolean value in an ng-repeat.
List of unregistered users:
<h3>Unregistered Users</h3>
<div ng-repeat="user in users | filter:!user.registered">
<div class="row-fluid">
<div class="span2">
{{user.name}}
</div>
</div>
</div>
List of registered users:
<h3>Registered Users</h3>
<div ng-repeat="user in users | filter:user.registered">
<div class="row-fluid">
<div class="span2">
{{user.name}}
</div>
</div>
</div>
Is there a good way to filter based on registered and !registered.

filter by obj expression:
<h3>Unregistered Users</h3>
<div ng-repeat="user in users | filter:{registered:false}">
<div class="row-fluid">
<div class="span2">
{{user.name}}
</div>
</div>
</div>
JSFiddle: http://jsfiddle.net/alfrescian/9ytDN/

Create a method in the controller which returns true or false based on the logic you need and specify that function in the filter.
Something like this:
$scope.isRegistered = function(item) {
return item.registered;
};
<h3>Unregistered Users</h3>
<div ng-repeat="user in users | filter:!isRegistered ">
<div class="row-fluid">
<div class="span2">
{{user.name}}
</div>
</div>
</div>

In case an item does not have a boolean property set, you can find the item with a property not set to true by using '!' with quotes. e.x. filter: {property:'!'+true}.
Example:
$scope.users = [
{
name : 'user1 (registered)',
registered : true
},
{
name : 'user2 (unregistered)'
},
{
name : 'user3 (registered)',
registered : true
},
{
name : 'user4 (unregistered)'
}
To get unregistered users filter:
<h3>Unregistered Users</h3>
<div ng-repeat="user in users | filter:{registered:'!'+true}">
<div class="row-fluid">
<div class="span2">
{{user.name}}
</div>
</div>
</div>

Had the same question. Alfrescian solution didn't work for me on Angular 1.1.5.
Found this fiddle: http://jsfiddle.net/buehler/HCjrQ/
.filter('onlyBooleanValueFilter', [function(){
return function(input, param){
var ret = [];
if(!angular.isDefined(param)) param = true;
angular.forEach(input, function(v){
// 'active' is a hard-coded field name
if(angular.isDefined(v.active) && v.active === param){
ret.push(v);
}
});
return ret;
};
}])
You would need to adjust the code of the filter according to your field.

Slight modification to Websirnik's answer, this allows any column name for the dataset:
.filter('onlyBooleanValueFilter', [function () {
return function (input, column, trueOrFalse) {
var ret = [];
if (!angular.isDefined(trueOrFalse)) {
trueOrFalse = false;
}
angular.forEach(input, function (v) {
if (angular.isDefined(v[column]) && v[column] === trueOrFalse) {
ret.push(v);
}
});
return ret;
};
}])
Markup:
<div repeat="row in your.dataset | onlyBooleanValueFilter: 'yourColumn' : true">
...your stuff here....
</div>

Related

How to make unique ng-model in ng-repeat

I want to make each test(ng-model) like test1, test2 unique in below code..
<div ng-repeat="item in Array">
<div>{{item.Name}}</div>
<a ng-click="openClose(test)>show/hide</a>
<div ng-show="test">{{item.Des}}</div>
</div>
$scope.openClose = function (modalName) {
$scope[modalName] = $scope[modalName] ? false : true;
}
You can maintain the show / hide using the $index value you get for each element when you use ng-repeat.
angular.module('app',[]).controller('mainCtrl', function($scope){
$scope.Array = [{Name:'abc'},{Name:'zzz'},{Name:'yyy'},{Name:'xxx'}];
$scope.openClose = function (index) {
if($scope.selectedValue == index){
$scope.selectedValue = -1;
}else{
$scope.selectedValue = index;
}
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='app' ng-controller='mainCtrl'>
<div ng-repeat="item in Array">
<div>{{item.Name}}</div>
<a ng-click="openClose($index)">show/hide</a>
<div ng-show='$index === selectedValue'>Hide Show content</div>
</div>
</div>

How to show another scope value in view corresponding to other value?

I am newbie to angular. I have two scope variables i.e,$scope.jsonData and $scope.dbdatas. I want to show value from $scope.jsonData corresponding to $scope.dbdatas.name. Please check my code. I have mentioned my desire output in the code.
View:
<div ng-app="myApp">
<div ng-controller="TestCtrl">
<div class="col-md-4 col-lg-4 col-xs-6" style="padding: 10px" ng-repeat="dbdata in dbdatas">
<div>
{{dbdata.name}} : <span class="list_text">{{dbdata.value}}</span>
<!--something like {{dbdata.name}} : <span show-value class="list_text">{{dbdata.value}}</span>-->
</div>
</div>
</div>
var app = angular.module('myApp', []);
app.controller('TestCtrl',function($scope){
$scope.jsonData=[{"_id":"56f90a9a51ec8f20e786a9e7","name":"Eleget","options":[{"key":"Y","value":"Once"},{"key":"M","value":"More than once"}]},{"_id":"56f90a9a51fs8f20e786a9e7","name":"MoliRet","options":[{"key":"L","value":"Let"},{"key":"R","value":"Ret"}]}];
$scope.dbdatas=[{name:'MoliRet',value:'L'},{name:'MoliRet',value:'R'},{name:'Eleget',value:'M'}];
});
/*app.directive('showValue',function(){
return{
restrict:'A',
link:function(scope,ele,attr){
}
}
});*/
Current Output
MoliRet : L
MoliRet : R
Eleget : M
Desire Output
MoliRet: Let
MoliRet: Ret
Eleget: More than once
Working Fiddle
HTML:
<div ng-app="myApp">
<div ng-controller="TestCtrl">
<div class="col-md-4 col-lg-4 col-xs-6" style="padding: 10px" ng-repeat="item in jsonData">
<div ng-repeat='option in item.options'>
<div ng-show="isInArray(option.key)">
{{item.name}}: {{option.value}}
</div>
</div>
</div>
</div>
</div>
JavaScript:
var app = angular.module('myApp', []);
app.controller('TestCtrl',function($scope){
$scope.isInArray = function(key){
var returnValue = false;
for(var i=0;i<$scope.dbdatas.length;i++){
if($scope.dbdatas[i].value==key){
returnValue = true;
break;
}
}
return returnValue
}
$scope.jsonData=[{"_id":"56f90a9a51ec8f20e786a9e7","name":"Eleget","options":[{"key":"Y","value":"Once"},{"key":"M","value":"More than once"}]},{"_id":"56f90a9a51fs8f20e786a9e7","name":"MoliRet","options":[{"key":"L","value":"Let"},{"key":"R","value":"Ret"}]}];
$scope.dbdatas=[{name:'MoliRet',value:'L'},{name:'MoliRet',value:'R'},{name:'Eleget',value:'M'}];
});
Output:
Eleget: More than once
MoliRet: Let
MoliRet: Ret
Hope that solve your problem.
You can use angular.ForEach to match data from both scope variables and push the data to an array $scope. Please take a look at the solution below.
<div ng-app="myApp">
<div ng-controller="TestCtrl">
<div class="col-md-4 col-lg-4 col-xs-6" style="padding: 10px" ng-repeat="dbdata in dbdatas">
<div>
{{dbdata.name}} : <span class="list_text">{{dbdata.value}}</span>
</div>
</div>
<div ng-repeat="expect1 in expectations">{{expect1.name}}: {{expect1.value}}</div>
</div>
</div>
$scope.dbdatas=[{name:'MoliRet',value:'L'},{name:'MoliRet',value:'R'},{name:'Eleget',value:'M'}];
$scope.expectations= [];
angular.forEach($scope.dbdatas,function(value1){
angular.forEach($scope.jsonData,function(value2){
if(value1.name == value2.name){
angular.forEach(value2.options,function(value3){
if(value3.key == value1.value){
$scope.expectations.push({
"name" : value2.name,
"value": value3.value});
}
});
}
});
});
Expected output will be
MoliRet: Let
MoliRet: Ret
Eleget: More than once
I would suggest you have to store a unique options table in one json and use angular custom service filter to handle the relative key 'look at the plunker'. you can use this custom filter in any controller and view.
Here is custom filter
app.filter('myFilter', ['$filter', function ($filter) {
return function (data, param) {
var output = $filter('filter')(data, {key:param},true);
return (param && output.length) ? output[0].value : '';
};
}]);
Here is a working plunker
.Hope that help.

How filter in a view

i have this Code in my view
<div ng-repeat="config in configs">
<div ng-repeat="test in tests ">
{{test[config.Name]}}</li>
</div>
</div>
it works fine. But how can I filter test?
<div ng-repeat="test in Tests | filter:{[config.Name]:'Test'} ">
dont work. How can I filter the column config.Name?
Thanks for your Help
Stefan
Add that function to your controller:
$scope.createFilter = function(property, value) {
var result = {};
result[property] = value;
return result;
};
and use it in the view:
<div ng-repeat="test in Tests | filter: createFilter(config.Name, 'Test')">
Try this, I hope that could help you:
JS :
$scope.conf = [];
$scope.conf.Name = 'Test';
HTML:
<div ng-repeat="config in configs | filter:conf:strict">
<div ng-repeat="test in tests ">
{{test[config.Name]}}</li>
</div>
</div>
That's a tricky one, but if you put the filter value in a variable first that might work?
<div ng-repeat="config in configs" ng-init="$filter = {}; $filter[config.Name] = 'Test'}">
<div ng-repeat="test in tests | filter : $filter">
{{test[config.Name]}}</li>
</div>
</div>

Why are changes in my arrays in my controller not being reflected in my view?

This is branching off of my last question: How to call $scope.$apply() using “controller as” syntax
I am using TypeScript in conjunction with Angular
Problem: I have an ng-repeat in my view
<!-- Simple View -->
<div ng-hide="wordTrack.showDetailedView">
<div class="col-md-12" id="wordTrackResult" style="padding: 10px; overflow-y: auto; overflow-x: hidden;">
<div class="wordListWellWrapper row" ng-repeat="words in wordTrack.wordList">
<div class="col-md-5 wordListWell form-control" ng-class="(words.IsPositive)? 'posWordWell': 'negWordWell' ">
<strong class="wordListWord">{{words.Word}}</strong>
<div class="wordListIcon">
<div class="whiteFaceIcon" ng-class="(words.IsPositive)? 'happyWhiteIcon': 'sadWhiteIcon' "></div>
</div>
</div>
<div class="col-md-2">
<span aria-hidden="true" class="glyphicon-remove glyphicon" ng-click="wordTrack.removeWord(words.Word)"></span>
</div>
</div>
<p class="noWordText" ng-show="(wordTrack.notUsedWordList.length > 0)">The following words have not yet been used</p>
<div class="wordListWellWrapper row" ng-repeat="words in wordTrack.notUsedWordList">
<div class="col-md-5 wordListWell form-control" style="background-color: gray;">
<strong class="wordListWord">{{words}}</strong>
</div>
<div class="col-md-2">
<span aria-hidden="true" class=" glyphicon-remove glyphicon" ng-click="wordTrack.removeWord(words)"></span>
</div>
</div>
</div>
</div>
which is using two arrays in my controller (wordList and notUsedWordList):
module WordsToTrackController {
export class Controller {
public static $inject = ["$scope", "CampaignFactory", "VideoFactory", "DashboardFactory", "WordsToTrackFactory"];
wordList: Array<IWordTrackItem>;
notUsedWordList: Array<string>;
constructor($scope: ng.IScope, campaignFactory, videoFactory, dashboardFactory, wordsToTrackFactory) {
this.campaignFactory = campaignFactory;
this.videoFactory = videoFactory;
this.dashboardFactory = dashboardFactory;
this.wordsToTrackFactory = wordsToTrackFactory;
this.wordList = [];
this.notUsedWordList = [];
this.hasData = false;
this.fetchInProgress = false;
$scope.$on("video-switch",() => {
this.setWordLists();
});
$scope.$on("detail-switch",() => {
this.showDetailedView = this.dashboardFactory.isDetailedView;
});
}}}
Inside my constructor, I am calling
$scope.$on("video-switch",() => {
this.setWordLists();
});
which executes setWordLists() which attempts to grab the data from one of my factories and set the values of the arrays (which it is doing correctly)
Controller:
setWordLists() {
this.fetchInProgress = true;
var campaignId = this.campaignFactory.currentId();
var videoId = this.videoFactory.currentId();
if (!campaignId || !videoId) {
return;
}
this.wordsToTrackFactory.doGetWordsToTrackModel(campaignId, videoId)
.then((response) => {
this.fetchInProgress = false;
this.wordList = (response) ? response.data.WordList : [];
this.notUsedWordList = (response) ? response.data.NotUsedWords : [];
});
}
Factory:
function doGetWordsToTrackModel(campaignId: number, videoId: number) {
return $http
.get(url, {
params: {
videoId: videoId,
campaignId: campaignId
}
});
}
Now, the problem is that even though the arrays are being set to the correct values, it is not being updated in my view (inside the ng-repeat).
I don't want to call $scope.$apply() for a quick fix either. Can anyone spot the source of the problem?
Edit:
$scope.$apply() doesn't help, so i'm thinking ng-repeat isn't binding correctly, but I can't see how I set the view up incorrectly.
Edit: ........
I'm a moron and put my ' ng-controller="Controller as controller" ' on the incorrect element.......
wrong code:
<div class="col-md-4" >
<h2 class="text-center" ng-controller="WordsToTrackController as wordTrack">Words to Track</h2>
corrected code:
<div class="col-md-4" ng-controller="WordsToTrackController as wordTrack">
<h2 class="text-center">Words to Track</h2>

How to skip $index in ng-repeat

Consider the following:
<div ng-repeat='quest in quests'>
<div ng-switch on="quest.ui.type">
<div ng-switch-when="ms-select-single" >
<div ms-select-single quest='quest'
quest-num='{{(true)?numInc():return}}'></div>
</div>
<div ng-switch-when="ms-select-multy">
<div ms-select-multy quest='quest'
quest-num='{{(true)?numInc():return}}'></div>
</div>
<div ng-switch-when="ms-date">
<div ms-date quest='quest'
quest-num='{{(true)?numInc():return}}'>{{questNo}}</div>
</div>
<div ng-switch-when="ms-text">
<div ms-text quest='quest'
quest-num='{{(true)?numInc():return}}'>{{questNo}}</div>
</div>
<div ng-switch-when="ms-textarea">
<div ms-textarea quest='quest'
quest-num='{{(true)?numInc():return}}'>{{questNo}}</div>
</div>
<div ng-switch-when="ms-number">
<div ms-number quest='quest'
quest-num='{{(true)?numInc():return}}'>{{questNo}}</div>
</div>
<div ng-switch-when="ms-html">
<div ms-html quest='quest'></div>
</div>
</div>
</div>
What should be my true statement in the quest-num='{{(true)?numInc():return}}'>?
What i want to achieve is an increment a model value conditionaly when the statement is true, if it's true all the time the program breaks, what should be my true statement here?
numInc returns a ++ of a num value in the model, initialized first at 0, and when it hits the function it increments, but because i have ng-switch it increments too many times, that's why i need the true/false statement, i think...
I'm not sure I understood your question but if you wanted something like this
Label Actual $index value
Question 1 0
1
Question 2 2
Question 3 3
etc...
Then we can use a directive. Here's a quick sketch
var app = angular.module('app', []);
app.controller('MainController', function($scope){
$scope.arr = [{name:'John', phone:'555-1276'},
{name:'Mary', phone:'800-BIG-MARY'},
{name:'Mike', phone:'555-4321', countMe:false},
{name:'Adam', phone:'555-5678'},
{name:'Julie', phone:'555-8765'},
{name:'Juliette', phone:'555-5678', countMe:false}]
});
app.directive('conditionalNumberDirective', function(){
var counter = 0;
return {
restrict: 'A',
link: function(scope, el, attr) {
// config what is item and what is coutMe via attrs here
if(scope.$index === 0) {
counter = 1;
}
scope.counter = counter;
if(angular.isDefined(scope.item) && angular.isDefined(scope.item.countMe) && !scope.item.countMe) {
scope.counter = null;
}else {
counter++
}
}
}
});
Html would look something like
<div ng-controller="MainController">
<input type="text" ng-model="search"/>
<div ng-repeat="item in arr | filter:search" conditional-number-directive>
Index:{{$index}} {{item}} - Label:{{counter}}
</div>
</div>
Instead of $index use a ng-model variable. You could try something like this also(ternary):
{{ true ? true : false }}
while assigning the value.

Resources