How can I put a condition inside a data binding in AngularJS? - angularjs

I would like to do the following:
<div>
<div ng-repeat="row in test.active">
<div>{{ row.id }}</div>
<div>
{{ if (row.testTypeId == 1) { test.exams.dataMap[row.examId].name; } }}
{{ if (row.testTypeId == 2) { test.topics.topicNameMap[row.topicId] } }}
</div>
</div>
</div>
However this is giving me an error with the { inside of the {{ }}. Is there another way I could make this work?

#jack.the.ripper is correct. Move the logic to a function in the $scope and call that instead.
$scope.name = function (row) {
if (row.testTypeId == 1) {
return test.exams.dataMap[row.examId].name;
} else {
return '';
}
}
In the HTML:
{{ name(row) }}

Ternary operators certainly work, plnkr.
{{ (row.testTypeId == 1) ? test.exams.dataMap[row.examId].name : '' }}
{{ (row.testTypeId == 2) ? test.topics.topicNameMap[row.topicId] : '' }}

You can use ng-show to do this:
<div>
<div ng-repeat="row in test.active">
<div>{{ row.id }}</div>
<div ng-show="row.testTypeId == 1">
{{test.exams.dataMap[row.examId].name }}
</div>
<div ng-show="row.testTypeId == 2">
{{ test.topics.topicNameMap[row.topicId] }}
</div>
</div>
</div>

Why does it need to be in the databinding itself? Couldn't you just use the ng-if directive?
<div ng-if="row.testTypeId == 1">stuff</div>
<div ng-if="row.testTypeId == 2">otherstuff</div>

Related

Anuglar js filter deep objects

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

Preprocess ng-repeat variables?

I am using ng-repeat to print the output in div. Elements in bCrumbs collection start with slash and space and I want to remove them from 1st loop iteration.
My Code:
<div ng-repeat="bCrumb in bCrumbs" id="{{bCrumb.name}}">{{ bCrumb.name }}</div>
the output from {{ bCrumb.name }}:
/ Test1
/ Test2
expected Output:
Test1
/Test2
You can use ng-repeat-start and ng-repeat-end
<div ng-repeat-start="bCrumb in bCrumbs" ng-if="$first>
{{ beautify(bCrumb.name) }}
</div>
<div ng-repeat-end ng-if="!$first">
{{ bCrumb.name }}
</div>
Besides, define a function called beautify in your controller:
$scope.beautify = function (name) {
return name.replace('/ ', '');
};
You can read the detailed documentation here
update
A better way to handle string beautify is creating a filter to handle it
app.filter('beautify', function () {
return function (data) {
return data.replace("/ ", "");
};
});
Then in your view template:
<div ng-repeat-start="bCrumb in bCrumbs" ng-if="$first>
{{ bCrumb.name | beautify }}
</div>
<div ng-repeat-end ng-if="!$first">
{{ bCrumb.name }}
</div>
I think you should change your controller (or whatever is producing bCrumbs) to strip the slashes before reaching view. This way it'll be more testable and (hopefully) clear. You could do something like this:
function strip(s) {
if(s.indexOf('/ ') === 0) {
return s.substring(2);
} else {
return s;
}
}
$scope.bCrumbs = originalBCrumbs.map(function(bc, idx) {
return idx === 0 ? strip(bc) : bc;
});

ng-if with multiple conditions inside ng-repeat not working as expected

I'm having trouble with something that is supposed to work unless I'm mistaken.
I've got a key:value object set up like this:
{
key1:"val1",
key2:"val2",
key3:"val3",
key4:null
}
In my view I have this:
<div class="col-md-4" ng-repeat="(key, value) in list" ng-if="key != 'key1' || value != null">
<ul>
<li>{{ key }} : {{ value }} </li>
</ul>
</div>
The problem:
If I only use key != 'key1' works,, the key and value of key1 is not displayed.
If I only use value != null works as well,, key4 is not displayed.
But when I combine the if statement with || (OR), the entire if statement is ignored.
Am I doing something wrong here?
I've posted an example over here: http://jsfiddle.net/caxoyud2/
Thanx in advance!
If you want both to disappear it should be '&&' instead of '||'. !(key == 'key1' || value == null), when negation is taken inside '||' becomes '&&'.
<div class="col-md-4" ng-repeat="(key, value) in list" ng-if="key != 'key1' && value != null">
<ul>
<li>{{ key }} : {{ value }} </li>
</ul>
</div>
OR
<div class="col-md-4" ng-repeat="(key, value) in list" ng-if="!(key == 'key1' || value == null)">
<ul>
<li>{{ key }} : {{ value }}</li>
</ul>
</div>
Please see demo below
Everything is fine just statement
(true || false) = true
var someModule = angular.module('myModule', []);
someModule.controller('someControler', function($scope) {
$scope.list = {
key1: "val1",
key2: "val2",
key3: "val3",
key4: null
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myModule">
<div ng-controller="someControler">
<div class="col-md-4" ng-repeat="(key, value) in list" ng-if="!(key != 'key1' && value != null)">
<ul>
<li>{{ key }} : {{ value }}</li>
</ul>
</div>
</div>
</div>

Set class of DIV in ng-repeat

I have next HTML code:
<div class="small-3 column cell"
ng-repeat="cell in line track by $index">
{{ cell }}
</div>
How can I add additional class for DIV element based on {{ cell }} value. For example, 'empty' for cell=0, and 'full' for cell != 0 ?
<div class="..." ng-repeat="cell in line" ng-class="{empty:(cell==0), full:(cell!=0)}">
...
</div>
which can be further reduced to
<div class="..." ng-repeat="cell in line" ng-class="(cell==0) ? 'empty' : 'full'">
...
</div>
You can use anything the angular expression supports. ng-class will be best for what you describe.
If the logic you require is more complicated than what you can do with ng-class you can always create a controller for this scenario.
<div class="small-3 column cell" ng-controller="MyCtrl"
ng-repeat="cell in line track by $index">
<div class="{{getClass()}}"></div>
</div>
function MyCtrl($scope) {
$scope.getClass = function() {
if($cell == whatever) return "whatever";
return "nothing";
}
}

List value in array with angularjs markup?

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

Resources