ng-if an element has a certain class - angularjs

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.

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")
}

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
}
}

AngularJs directive bind events in link function with ng-repeat

I want to create a directive which includes a ng-repeat and I need to bind an event to a contained tag inside the ng-repeat like the "test-class"
<div>
<div ng-repeat="row in ctrl.items">
<div>
<p ng-bind="row.Text"></p>
<a class="test-class"></a>
</div>
</div>
</div>
but my problem seems to be that in the link function the "element" property seems to contain only the ng-repeat and so I can't find the "test-class" within the element because its not there in the link function, that makes sense.
But how can I then access the dom and bind some custom events to the "a" in my example.
The only solution I had is to create two directives one with the ng-repeat and the other with the content inside the ng-repeat. Do I miss something or is this the only possible solution for my problem?
Directive with name "DirectiveContent":
<div>
<p ng-bind="row.Text"></p>
<a class="test-class"></a>
</div>
Then the new complete Directive:
<div>
<div ng-repeat="row in ctrl.items">
<directive-content></directive-content>
</div>
</div>

angularjs binding to an attribute

I am trying to load directive inside another directive dynamically, so I am trying to use ng-repeat for the below, where {{item.directiveName}} is the inner directive name.
<card ng-repeat="item in items" {{item.directiveName}} title="{{item.title}}">
The problem is that the {{item.directiveName}} is not evaluated, it stays as it is. I think because it is not a value of an attribute, it is an attribute.
Is there any way for this expression to be evaluated or this is not supported by angularjs?
This should do it, depending on the card directive.
<div ng-repeat="item in items">
<card {{item.directiveName}} title="{{item.title}}"> </card>
</div>
try to assign it to an attribute
<card ng-repeat="item in items" data="{{item.directiveName}}" title="{{item.title}}">
<card ng-repeat="item in items" myAttr="{{item.directiveName}}" title="{{item.title}}">

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.

Resources