Angular if condition from value of ng-repeat - angularjs

I'm rendering data in a table using Angular and ng-repeat. What I would like to do is add an if condition to say if the value contained in ng-repeat is a certain word, set the background colour of that row to red. I think it might look something like this, but I'm not sure how to do this in Angular.
if( {{field.value}} == THING){
var backgroundColour = red;
}
I was thinking of using ng-filter, although I dont wan't to actually filter the data, just set a variable based on a value.
Any ideas?

You could add an ng-class in the html to achieve this.
<div ng-repeat"field in fields" ng-class="{'with-background': field.value == THING}">
{{field.value}}
</div>
And then add with-background to css
.with-background {
background-color: red;
}
If THING is a variable pointing to some other value, you don't have to use quotes and if it's meant to be a string, use it as 'THING'
Here's the official documentation of ngClass: https://docs.angularjs.org/api/ng/directive/ngClass

You cann also use ng-style for this
<div ng-style="field.value == THING?{'background-color':'red'}:{}">
Hello Plunker!
</div>
plunker

You could do something like this below:
<div ng-repeat="field in collections"
ng-if="field.value && field.value =='THING'">
{{backgroundcolor}}
</div>
Or you could you use ng-class directive
<div id="wrap" ng-class="{true: 'yourClassName'}[field.value]">

You can use ng-class directive
<tr ng-class="{'color-red': item.value > 0}" ng-repeat="item in vm.items">
<td>{{ item.value }}>/td>
</tr>

Related

ng-click - hide all other div that isn't this $index within ng-repeat

What i'm trying to do is similiar to an accordion.
Simple put
i have an ng-repeat with an <a> tag that once clicked show another div called "Printpanel" nested inside it within ng-show.
If the user cick to another <a> tag, i want to hide all other div showed before, and open only to that one related.
I am using $index to trigger the specific div.
Here what i have done:
<div ng-repeat="product in $ctrl.Products">
<a href="#" ng-click="showDetails = $index;>CONFIGURE</a>
<div class="Printpanel ng-hide" ng-show="showDetails == $index" ng-hide="showDetails != $index">
</div>
it seems that ng-hide is not recognized... Anybody have an idea?
You don't need to use ngShow + ngHide: one is enough.
<div class="Printpanel ng-hide" ng-show="showDetails == $index">
You can use ng-if also:
<div class="Printpanel" ng-if="showDetails == $index">
EDIT:
due to scope inheritance problem, you are not able to set showDetails variable. use $parent for that.
working example:
<div ng-repeat="product in $ctrl.Products">
CONFIGURE
<div class="Printpanel" ng-if="$parent.showDetails == $index"> </div>
</div>
seems you have missed closing double quotes here ng-click="showDetails = $index;
Also either of one you need to use ng-show/ng-hide/ng-if = expression

Change the style of particular elements of an array inside ng-repeat in AngularJs

E.g
I have an array of text like $scope.array = [{text:'abc'}, {text:'pqr'}, {text:'xyz'}];
Now along with ng-repeat I want to change the colour of the text of any particular element of the array. how to achieve it?
IMO, we've multiple options to achieve that.
If you want to change single property then you can use ng-style but let say if you want to manipulate multiple properties then its preferable to use ng-class.
ng-style
The ngStyle directive allows you to set CSS style on an HTML element conditionally.
<div ng-repeat="contact in jsonContacts">
<span ng-style="{'color':($first ?'red':'blue')}">{{data.row}}</span>
</div>
ng-class
The ngClass directive allows you to dynamically set CSS classes on an HTML element by databinding an expression that represents all classes to be added.
<div ng-repeat="i in array" ng-class="{'green': $last, 'blue': $first}">
{{i.text}}
</div>
FYI,
The ngRepeat directive instantiates a template once per item from a collection. Each template instance gets its own scope, where the given loop variable is set to the current collection item, and $index is set to the item index or key.
$first boolean true if the repeated element is first in the iterator.
$middle boolean true if the repeated element is between the first and last in the iterator.
$last boolean true if the repeated element is last in the iterator.
Official documentations
ngRepeat
ngClass
ngStyle
Hope this helps you :)
var app = angular.module('app', []);
app.controller('homeCtrl', function($scope) {
$scope.array = [{text:'abc'}, {text:'pqr'}, {text:'xyz'}];
});
.green
{
color: green;
}
.blue
{
color: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="homeCtrl">
<h3>ng-style used</h3>
<div ng-repeat="i in array" ng-style="{'color':($first ?'red':'blue')}">{{i.text}}</div>
<br/>
<h3>ng-class used</h3>
<div ng-repeat="i in array" ng-class="{'green': $last, 'blue': $first}">{{i.text}}</div>
</div>
</div>
</div>
You can achieve this by using directives such as ngClass or ngStyle, to apply classes or style changes conditionally to certain HTML elements.
Let's assume you're listing your $scope.array elements:
<ul>
<li ng-repeat="element in array">{{element.text}}</li>
</ul>
You could add a class called .red (that would change the text color to red) to an element if text === 'pqr', but changing the above example to:
<ul>
<li ng-repeat="element in array" ng-class="{'red': element.text === 'pqr'}">{{element.text}}</li>
</ul>
Similarly you can also use the directive ng-style to apply a style directly, avoiding new classes.
Since you're using an ngRepeat, you can also its iterator $index to apply classes/styles on more advanced cases such as first/last element, element index is odd/even, etc...
For more examples and clarifications, please check the official documentation for both directives:
https://docs.angularjs.org/api/ng/directive/ngClass
https://docs.angularjs.org/api/ng/directive/ngStyle
You can use ng-class or ng-style, even including an auxiliar function in your controller to calculate that style.
<div ng-repeat="item in array" ng-class="calculateClass(item)" ng-style="calculateStyle(item)">
<!-- more stuff -->
</div>
EDIT
For your case it could be useful depending on what logic you want to apply to do something like
$scope.calculateStyle = function(item){
var color;
// Some logic to define color
return {
'color': color
}
}

Angular: a part of view does not update

I have a directive template with the following code
<div class="colorpicker">
<div>Chosen color</div>
<div class="color_swatch" style="background-color: {{ngModel}}"> </div>
<div class="clearfix"></div>
<div>Standard colors</div>
<div class="color_squares">
<div ng-repeat="color in colorList">{{color.trim() == ngModel.trim()}} //does not update
<div class="color_swatch" style="background-color: {{ color }};"></div>
</div>
</div>
<div class="clearfix"></div>
In the directive, I update the ngmodel using the below code to the color that was clicked - the div next to "chosen color" is updated with the selected color.
But, the expression "{{color.trim() == ngModel.trim()}}" always amounts to false.
{{color.trim() == ngModel.trim()}}
I have debugged the code and the values are exactly the same.
What I am missing?
This is probably because your variable is precisely named 'ngModel' see that article for more explanation : http://zcourts.com/2013/05/31/angularjs-if-you-dont-have-a-dot-youre-doing-it-wrong/
To resume this article : never use raw fields use always a dot. So in your scope change
$scope.ngModel
By
$scope.data.ngModel
And in your html change ngModel by data.ngModel.
When using dot you may have some undefined error, this is because you have to initialize the object :
$scope.data={};
Of course you can jsut rename your variable, but you may still have a problem with others directives.
I solved this by removing curly braces around color and using ng-style
<div class="color_swatch" id="colorpicker_selected_color" ng-style="{'background-color': selectedColor}" > </div>

repeating a template with ng-repeat

I have a template here that I want to repeat based on my $scope.dataset.
How do I get ng-repeat to repeat this template for each name?
HTML I have my template as follows
<table>
<tr ng-repeat = "data in dataset">
<td>{{data.name}}</td>
<td>
<div class="progressbar {{data.color}}" ng-style="{width:{{data.width}} + '%'}"
value = "{{data.value}}">
<span id="barValue">{{data.value}}</span>
</div>
</td>
</tr>
</table>
and as you can see, I'm trying to repeat this template inside the table.
dataset is as follows
$scope.dataset=[
{'name':'name1', 'value':34, 'width':34, 'color':'colorRed'},
{'name':'name2', 'value':50, 'width':50, 'color':'colorBlue'},
{'name':'name3', 'value':47, 'width':47, 'color':'colorRed'},
{'name':'name4', 'value':82, 'width':82, 'color':'colorBlue'},
{'name':'name5', 'value':72, 'width':72, 'color':'colorOrange'},
{'name':'name6', 'value':17, 'width':17, 'color':'colorGreen'},
{'name':'name7', 'value':20, 'width':20, 'color':'colorRed'},
]
When I try to use this, nothing pops up.
All I want is for the data to appear for each .name that comes up.
So first question is what am I doing wrong?
Second, is it possible to do all this in a custom directive?
You must be getting $parse error in your console as you are using
{{}} in ng-style
You shouldn't use {{}} interpolation directive inside ng-style directive.
color should be applied as style instead of adding class, you could be applied from ng-style directive.
HTML
<div class="progressbar" ng-style="{width:data.width + '%', color: data.color}"
value = "{{data.value}}">
<span id="barValue">{{data.value}}</span>
</div>

Different class for the last element in ng-repeat

I am creating a list using ng-repeat something like this
<div ng-repeat="file in files">
{{file.name}}
</div>
But for the last element alone I would like to have a class (<div class="last">test</div>) included to it. how can i achieve this using ng-repeat?
You can use $last variable within ng-repeat directive. Take a look at doc.
You can do it like this:
<div ng-repeat="file in files" ng-class="computeCssClass($last)">
{{file.name}}
</div>
Where computeCssClass is function of controller which takes sole argument and returns 'last' or null.
Or
<div ng-repeat="file in files" ng-class="{'last':$last}">
{{file.name}}
</div>
It's easier and cleaner to do it with CSS.
HTML:
<div ng-repeat="file in files" class="file">
{{ file.name }}
</div>
CSS:
.file:last-of-type {
color: #800;
}
The :last-of-type selector is currently supported by 98% of browsers
To elaborate on Paul's answer, this is the controller logic that coincides with the template code.
// HTML
<div class="row" ng-repeat="thing in things">
<div class="well" ng-class="isLast($last)">
<p>Data-driven {{thing.name}}</p>
</div>
</div>
// CSS
.last { /* Desired Styles */}
// Controller
$scope.isLast = function(check) {
var cssClass = check ? 'last' : null;
return cssClass;
};
Its also worth noting that you really should avoid this solution if possible. By nature CSS can handle this, making a JS-based solution is unnecessary and non-performant. Unfortunately if you need to support IE8> this solution won't work for you (see MDN support docs).
CSS-Only Solution
// Using the above example syntax
.row:last-of-type { /* Desired Style */ }
<div ng-repeat="file in files" ng-class="!$last ? 'class-for-last' : 'other'">
{{file.name}}
</div>
That works for me! Good luck!
You could use limitTo filter with -1 for find the last element
Example :
<div ng-repeat="friend in friends | limitTo: -1">
{{friend.name}}
</div>
The answer given by Fabian Perez worked for me, with a little change
Edited html is here:
<div ng-repeat="file in files" ng-class="!$last ? 'other' : 'class-for-last'">
{{file.name}}
</div>

Resources