Change the style of particular elements of an array inside ng-repeat in AngularJs - 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
}
}

Related

How to access nested elements in AngularJS

I have a list of items (divs) with a button. When I click on one of this buttons I can access the element using
$event.currentTarget
that returns some thing like
<div ng-click="myFunc()">
<i class="someclass"></i>
<span>bla bla</span>
</div>
how can I access and elements to modify attributes like class?
Don't. Use existing directives like ng-class or ng-if, etc in your html templates.
<div ng-click="clicked = true">
<span ng-class="{'someclass': clicked}">bla bla</span>
</div>
See stackblitz
Although you can get the html dom element and edit it you should only do this as a last option and other angularjs supported methods have failed or are not supported.
template
<div ng-click="myFunc($event)">
<i class="someclass"></i>
<span>bla bla</span>
</div>
controller
$scope.myFunc(event) {
var elem = angluar.element(event.currentTarget);
elem.children(".someclass").removeClass("someclass")
}

ng-if an element has a certain class

I was wondering if it is possible to have an ng-if be true if an element has a certain class.
Example:
<div class="edge" ng-repeat="item in items">
<div ui-view ng-if="(ng-repeat div has class of edge)"
Practically you can use hasClass method with angular element:
angular.element(myElement).hasClass('my-class');
So you can create a function and put the check in it and use that function in ng-if.
<div class="edge" ng-if="check()" ng-repeat="item in items">
However, remember that you cannot access the element in ng-if (vs you can pass the $event to ng-click and access $event.target) , need to create a directive to do it.

Angular if condition from value of ng-repeat

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>

How to show and hide items in dynamic rows in AngularJS?

I'm fairly new to AngularJS and I can't seem to find a way to do this appropriately. I created a custom directive to Apply a function a pass in the row Index. However, I can't seem to think of the way to show items in a row. What would be the best way to do this? I want to show specific and hide a target row via controller.
HTML:
<div class="row" data-index="{{$index}}">
<div>other information</div>
<div class="item hidden" ng-class="{hidden: hidden[{{$index}}]}">
Item
</div>
</div>
My Directive:
scope.$apply(function () {
scope.$parent.showItem(index);
});
Controller:
$scope.teamDrop = function(index) {
$scope.hidden[index] = false;
};
You can use the ng-show and ng-hide directives to hide and show elements.
You can also use the ng-if directive to remove elements from the dom.
For your example I'd change your ng-class to an ng-hide
<div class="row" data-index="{{$index}}">
<div>other information</div>
<div class="item hidden" ng-hide="hidden[$index]">
Item
</div>
</div>
You also don't need to use the {{}} syntax in the ng-class becausue it's already expecting an angular expression, that's for data binding.

Angularjs: custom grid component, dynamically add <br> elements

Ok, I have made a really simple grid component. I fetch a column count attribute and add a <br> tag after the end of a row. I do that within the link function.
Her is the directive: http://pastebin.com/U4ckuKJw
grid.html just looks like this: <div class="grid" data-ng-transclude=""></div>
In my first example I have 7 <div> tags inside the grid component and want to have 3 columns. So after every third <div> I want a <br> to be added.
It looks like this and is working:
<div data-grid="" data-cols="5">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
</div>
This one is not working: http://pastebin.com/wtcgM2Hv
I think it is because of the directive ng-repeat and that the content of the grid component isn't rendered at the time the link function ist executed.
Any thoughts on how to solve this problem or how to optimise the component?
An easier approach may be to solve the problem with standard angular directives and css. For instance, if you float your cells and clear: left on those cells that start a new row, you can use ng-repeat and ng-class to accomplish this.
I created an example at: http://jsbin.com/idukaz/1
The html looks like this. Note I'm using ng-class to apply the class that formats the cell that needs to start a new row depending on the result of calling the custom columnEnd function. columnBreak is a scope variable for the number of columns you want. $index is a variable generated by ng-repeat:
<div class="table">
<div class="label"
ng-class="{'new-row': startNewRow($index, columnBreak) }"
ng-repeat="item in items">{{ item.name }} ({{ $index + 1 }})</div>
</div>
In your controller:
app.controller('Controller', ['$scope', function (scope) {
// list of grid data
scope.items = [];
// controls the number of columns
scope.columnBreak = 5;
// calculates if current cell is start of new row
scope.startNewRow = function (index, count) {
return ((index) % count) === 0;
};
}]);
In your css if you float your cells and clear left, you'll get your columns to dynamically
reformat when you change the columnBreak value.
.label {
float: left;
}
.new-row {
clear: left;
}
Ok, now I found the solution:
use angular directive to change classes of ng-repeat elements
I mixed it with Marks idea and manipulate the css classes now.
Thanks

Resources