I'm new to Angular 2 and haven't worked front end before. So I'm not sure how to write a template structural directives. I need to translate this from ejs/angular 1 to Angular 2
for (var i = 0; i < n; i++) {
<% var classes = item.columns[i].fields.skin.indexOf("sign-in") > -1 ? "sign-in" : "" %>
<div class="dropdown menu-standout desktop <%= classes %>">
<a><%= item.columns[i].fields.title %></a>
</div>
}
My best guess was this, but I'm sure I can't have curly brackets twice inside ngFor. Any help?
<li *ngFor="let column of item.columns">
{{var classes = column.fields.skin.indexOf("sign-in") > -1 ? "sign-in":""}}
<div class="dropdown menu-standout desktop" {{ classes }}>
<a>{{column.fields.title}}</a>
</div>
</li>
You can not have binding assignment in template interpolation directive.
So, it should be like this
{{column.fields.skin.indexOf("sign-in") > -1 ? "sign-in":""}}
You can not declared variable inside interpolation directive
Remove the var classes = part from template otherwise it will template parse error.
you want to add a class dynamically, so try this :
<li *ngFor="let column of item.columns">
<div [class.active] = "isActive = 'column.fields.skin.indexOf("sign-in") > -1 ? "sign-in":"" ' " class="dropdown menu-standout desktop">
<a>{{column.fields.title}}</a>
</div>
</li>
it is not good practice to have js code in your view.
in your component
export class MyComponent {
isActive: boolean = false;
}
I fixed the syntax by writing an extra function
<li *ngFor="let column of item[0].fields.columns">
<div class="dropdown menu-standout desktop {{ checkIndex(column) }}" >
<a>{{column.fields.title}}</a>
</div>
</li>
export class PageDropdownComponent {
constructor() {}
checkIndex(classes:any) {
return classes.fields.skin.indexOf("sign-in") > -1 ? "sign-in" : "";
}
Thanks everyone else for the help, it was useful for understanding the syntax
What is wrong with my Angular code? I am getting the following error:
Cannot read property 'remove' of undefined at BrowserDomAdapter.removeClass
<ol>
<li *ngClass="{active: step==='step1'}" (click)="step='step1'">Step1</li>
<li *ngClass="{active: step==='step2'}" (click)="step='step2'">Step2</li>
<li *ngClass="{active: step==='step3'}" (click)="step='step3'">Step3</li>
</ol>
Angular version 2+ provides several ways to add classes conditionally:
type one
[class.my_class] = "step === 'step1'"
type two
[ngClass]="{'my_class': step === 'step1'}"
and multiple option:
[ngClass]="{'my_class': step === 'step1', 'my_class2' : step === 'step2' }"
type three
[ngClass]="{1 : 'my_class1', 2 : 'my_class2', 3 : 'my_class4'}[step]"
type four
[ngClass]="step == 'step1' ? 'my_class1' : 'my_class2'"
You can find these examples on the documentation page
[ngClass]=... instead of *ngClass.
* is only for the shorthand syntax for structural directives where you can for example use
<div *ngFor="let item of items">{{item}}</div>
instead of the longer equivalent version
<template ngFor let-item [ngForOf]="items">
<div>{{item}}</div>
</template>
See also https://angular.io/docs/ts/latest/api/common/index/NgClass-directive.html
<some-element [ngClass]="'first second'">...</some-element>
<some-element [ngClass]="['first', 'second']">...</some-element>
<some-element [ngClass]="{'first': true, 'second': true, 'third': false}">...</some-element>
<some-element [ngClass]="stringExp|arrayExp|objExp">...</some-element>
<some-element [ngClass]="{'class1 class2 class3' : true}">...</some-element>
See also https://angular.io/docs/ts/latest/guide/template-syntax.html
<!-- toggle the "special" class on/off with a property -->
<div [class.special]="isSpecial">The class binding is special</div>
<!-- binding to `class.special` trumps the class attribute -->
<div class="special"
[class.special]="!isSpecial">This one is not so special</div>
<!-- reset/override all class names with a binding -->
<div class="bad curly special"
[class]="badCurly">Bad curly</div>
Another solution would be using [class.active].
Example :
<ol class="breadcrumb">
<li [class.active]="step=='step1'" (click)="step='step1'">Step1</li>
</ol>
That's the normal structure for ngClass is:
[ngClass]="{'classname' : condition}"
So in your case, just use it like this...
<ol class="breadcrumb">
<li [ngClass]="{'active': step==='step1'}" (click)="step='step1'">Step1</li>
<li [ngClass]="{'active': step==='step2'}" (click)="step='step2'">Step2</li>
<li [ngClass]="{'active': step==='step3'}" (click)="step='step3'">Step3</li>
</ol>
with the following examples you can use 'IF ELSE'
<p class="{{condition ? 'checkedClass' : 'uncheckedClass'}}">
<p [ngClass]="condition ? 'checkedClass' : 'uncheckedClass'">
<p [ngClass]="[condition ? 'checkedClass' : 'uncheckedClass']">
You can use ngClass to apply the class name both conditionally and not in Angular
For Example
[ngClass]="'someClass'">
Conditional
[ngClass]="{'someClass': property1.isValid}">
Multiple Condition
[ngClass]="{'someClass': property1.isValid && property2.isValid}">
Method expression
[ngClass]="getSomeClass()"
This method will inside of your component
getSomeClass(){
const isValid=this.property1 && this.property2;
return {someClass1:isValid , someClass2:isValid};
}
Angular provides multiple ways to add classes conditionally:
First way
active is your class name
[class.active]="step === 'step1'"
Second way
active is your class name
[ngClass]="{'active': step=='step1'}"
Third way
by using ternary operator class1 and class2 is your class name
[ngClass]="(step=='step1')?'class1':'class2'"
You should use something ([ngClass] instead of *ngClass) like that:
<ol class="breadcrumb">
<li [ngClass]="{active: step==='step1'}" (click)="step='step1; '">Step1</li>
(...)
In Angular 7.X
The CSS classes are updated as follows, depending on the type of the expression evaluation:
string - the CSS classes listed in the string (space delimited) are added
Array - the CSS classes declared as Array elements are added
Object - keys are CSS classes that get added when the expression given in the value evaluates to a truthy value, otherwise they are removed.
<some-element [ngClass]="'first second'">...</some-element>
<some-element [ngClass]="['first', 'second']">...</some-element>
<some-element [ngClass]="{'first': true, 'second': true, 'third': false}">...</some-element>
<some-element [ngClass]="stringExp|arrayExp|objExp">...</some-element>
<some-element [ngClass]="{'class1 class2 class3' : true}">...</some-element>
Additionally, you can add with method function:
In HTML
<div [ngClass]="setClasses()">...</div>
In component.ts
// Set Dynamic Classes
setClasses() {
let classes = {
constantClass: true,
'conditional-class': this.item.id === 1
}
return classes;
}
to extend MostafaMashayekhi his answer for option two>
you can also chain multiple options with a ','
[ngClass]="{'my-class': step=='step1', 'my-class2':step=='step2' }"
Also *ngIf can be used in some of these situations usually combined with a *ngFor
class="mats p" *ngIf="mat=='painted'"
You can use [ngClass] or [class.classname], both will work the same.
[class.my-class]="step==='step1'"
OR
[ngClass]="{'my-class': step=='step1'}"
Both will work the same!
While I was creating a reactive form, I had to assign 2 types of class on the button. This is how I did it:
<button type="submit" class="btn" [ngClass]="(formGroup.valid)?'btn-info':''"
[disabled]="!formGroup.valid">Sign in</button>
When the form is valid, button has btn and btn-class (from bootstrap), otherwise just btn class.
We can make class dynamic by using following syntax. In Angular 2 plus, you can do this in various ways:
[ngClass]="{'active': arrayData.length && arrayData[0]?.booleanProperty}"
[ngClass]="{'active': step}"
[ngClass]="step== 'step1'?'active':''"
[ngClass]="step? 'active' : ''"
Let, YourCondition is your condition or a boolean property, then do like this
[class.yourClass]="YourCondition"
The directive operates in three different ways, depending on which of three types the expression evaluates to:
If the expression evaluates to a string, the string should be one or more space-delimited class names.
If the expression evaluates to an object, then for each key-value pair of the object with a truthy value the corresponding key is used as a class name.
If the expression evaluates to an array, each element of the array should either be a string as in type 1 or an object as in type 2. This means that you can mix strings and objects together in an array to give you more control over what CSS classes appear. See the code below for an example of this.
[class.class_one] = "step === 'step1'"
[ngClass]="{'class_one': step === 'step1'}"
For multiple options:
[ngClass]="{'class_one': step === 'step1', 'class_two' : step === 'step2' }"
[ngClass]="{1 : 'class_one', 2 : 'class_two', 3 : 'class_three'}[step]"
[ngClass]="step == 'step1' ? 'class_one' : 'class_two'"
ngClass syntax:
[ngClass]="{'classname' : conditionFlag}"
You can use like this:
<ol class="breadcrumb">
<li [ngClass]="{'active': step==='step1'}" (click)="step='step1'">Step1</li>
<li [ngClass]="{'active': step==='step2'}" (click)="step='step2'">Step2</li>
<li [ngClass]="{'active': step==='step3'}" (click)="step='step3'">Step3</li>
</ol>
This is what worked for me:
[ngClass]="{'active': dashboardComponent.selected_menu == 'profile'}"
For elseif statement (less comparison) use like that: (For example you compare three statement)
<div [ngClass]="step === 'step1' ? 'class1' : (step === 'step2' ? 'class2' : 'class3')"> {{step}} </div>
Not relevant with [ngClass] directive but I was also getting the same error as
Cannot read property 'remove' of undefined at...
and I thought to be the error in my [ngClass] condition but it turned out the property I was trying to access in the condition of [ngClass] was not initialized.
Like I had this in my typescript file
element: {type: string};
and In my [ngClass] I was using
[ngClass]="{'active', element.type === 'active'}"
and I was getting the error
Cannot read property 'type' of undefined at...
and the solution was to fix my property to
element: {type: string} = {type: 'active'};
Hope it helps somebody who is trying to match a condition of a property in [ngClass]
<div class="collapse in " [ngClass]="(active_tab=='assignservice' || active_tab=='manage')?'show':''" id="collapseExampleOrganization" aria-expanded="true" style="">
<ul> <li class="nav-item" [ngClass]="{'active': active_tab=='manage'}">
<a routerLink="/main/organization/manage" (click)="activemenu('manage')"> <i class="la la-building-o"></i>
<p>Manage</p></a></li>
<li class="nav-item" [ngClass]="{'active': active_tab=='assignservice'}"><a routerLink="/main/organization/assignservice" (click)="activemenu('assignservice')"><i class="la la-user"></i><p>Add organization</p></a></li>
</ul></div>
Code is good example of ngClass if else condition.
[ngClass]="(active_tab=='assignservice' || active_tab=='manage')?'show':''"
[ngClass]="{'active': active_tab=='assignservice'}"
Try Like this..
Define your class with ''
<ol class="breadcrumb">
<li *ngClass="{'active': step==='step1'}" (click)="step='step1; '">Step1</li>
<li *ngClass="{'active': step==='step2'}" (click)="step='step2'">Step2</li>
<li *ngClass="{'active': step==='step3'}" (click)="step='step3'">Step3</li>
</ol>
The example is a bit big, but triggering a class instead of typing inline is my first preferred approach.
this way you can add as many possibilities as you want to your element.
There may be a way for those who want to bind more than one [ngClass] to a single element.
<span class="inline-flex items-center font-medium" [ngClass]="addClass">{{ badge.text }}</span>
import { ChangeDetectionStrategy, Component, Input } from '#angular/core';
type Badge = {
size?: 'basic' | 'large';
shape?: 'basic' | 'rounded';
color?: 'gray' | 'red' | 'yellow' | 'green' | 'blue' | 'indigo' | 'purple' | 'pink';
dot?: boolean;
removeButton?: false;
text?: string;
}
#Component({
selector: 'bio-badge',
templateUrl: './badge.component.html',
styleUrls: ['./badge.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class BioBadgeComponent {
#Input() badge!: Badge;
get addClass() {
return {
'px-2.5 py-0.5 text-sx': this.badge.size === 'basic',
'px-3 py-0.5 text-sm': this.badge.size === 'large',
'rounded-full': this.badge.shape === 'basic',
'rounded': this.badge.shape === 'rounded',
'bg-gray-100 text-gray-800': this.badge.color === 'gray',
'bg-red-100 text-red-800': this.badge.color === 'red',
'bg-yellow-100 text-yellow-800': this.badge.color === 'yellow',
'bg-green-100 text-green-800': this.badge.color === 'green',
'bg-blue-100 text-blue-800': this.badge.color === 'blue',
'bg-indigo-100 text-indigo-800': this.badge.color === 'indigo',
'bg-purple-100 text-purple-800': this.badge.color === 'purple',
'bg-pink-100 text-pink-800': this.badge.color === 'pink',
}
}
}
If user want to display the class on basis of && and ||
then below one is work for me
[ngClass]="{'clasname_1': condition_1 && condition_2, 'classname_2': condition_1 && condition2, 'classname_3': condition}"
Example:
[ngClass]="{'approval-panel-mat-drawer-side-left': similar_toil_mode==='side' && showsTheSimilarToilsWithCloseIcon, 'approval-panel-mat-drawer-side-right': similar_toil_mode==='side' && !showsTheSimilarToilsWithCloseIcon, 'approval-panel-mat-drawer-over': similar_toil_mode==='over'}"
This question already has answers here:
if else statement in AngularJS templates
(10 answers)
Closed 8 years ago.
I need to use else if in angularjs template .What is the syntax ?
For example in c i would write the code like below:
if (data.sender=='system')
{data.receiver}
else if (data.sender=='mail')
{data.receiver}
else {data.sender}
My code:
{{data.sender == 'System' ? data.receiver : ' '}}
{{data.sender =='mail' ? data.receiver : data.sender }}
{{(data.sender === 'system' || data.sender === 'mail') ? data.receiver : data.sender}}
There are no if-else syntax in angular templates as you are looking for. Too much logic in the templates makes it difficult to maintain. Here are two possible solutions:
<span ng-show="data.sender == 'mail' || data.sender=='system'">{{data.receiver}}</span>
<span ng-show="data.sender != 'mail' && data.sender!='system'">{{data.sender}}</span>
You can also use ng-switch in a similar way:
<span ng-switch="data.sender">
<span ng-switch-when="mail">{{data.receiver}}</span>
<span ng-switch-when="system">{{data.receiver}}</span>
<span ng-switch-default>{{data.sender}}</span>
</span>
The later having the advantage that only one of the spans will exist in the document where ng-show/ng-hide all spans exist in the document they are just hidden using display:none.
Other options would be writing your own directive, or creating special filters.
Here it is, but you should really try to avoid having this kind of complicated logic inside of templates, as a rule of thumb.
{{ data.sender == 'system' ? data.receiver : data.sender == 'mail' ? data.receiver : data.sender }}
If you need an elseif in angular template you can use a ternary operator as in C/C++
{{ data.sender=='system'
< 4 ? data.receiver : data.sender=='mail' ? data.receiver : data.sender}}
angular.module('quetion_app', []);
angular.module('quetion_app').controller('quertion_controller', ['$scope',
function($scope) {
$scope.data = {
sender: 'some sender',
receiver: 'somebody'
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="quetion_app">
<div ng-controller="quertion_controller">
{{data}}
<br>
<br>
{{ data.sender=='system'
< 4 ? data.receiver : data.sender=='mail' ? data.receiver : data.sender}} </div>
</div>
Change data.sender in snippet to check the behavior
Hope it helps
This type of logic really belongs in the controller or service which is responsible for setting up data in your $scope. Placing it in your view brings a lot of logic in to the view unnecessarily and also causes that logic to be run as a watch which both expensive and unnecessary.
In the code that establishes data you could have:
data.displayedSender = (data.sender === 'system' || data.sender === 'mail') ? data.receiver : data.sender;
Then in your view you bind to the data.displayed sender:
<span>{{data.displayedSender}}</span>
I have to call a function on $last in ng-repeat, if I use,
div(ng-repeat="note in notes")
li: {{note}}
{{$last ? 'true' : 'false' }}
It prints false only on last li element, but for the same if I call a function instead of 'true', like below
div(ng-repeat="note in notes")
li: {{note}}
{{$last ? update() : 'false' }}
the function is called for each loop.
For your information, I had tried "&&" kind of solution given in this link
{{$last && update() || '' }}
also, but not working.
You are not doing anything obvious wrong so maybe error is somewhere else in your code. See the following:
app.controller('MyCtrl', function ($scope) {
$scope.notes = ['Note 1','Note 2'];
$scope.update = function () {
return 'i haz updated!1';
};
});
<div ng-controller="MyCtrl">
<ul ng-repeat="note in notes">
<li>
{{note}} - isLast:{{$last ? 'true' : 'false'}} - {{$last ? update() : '???'}}
</li>
</ul>
</div>
Plunker http://plnkr.co/edit/DwCpcC
Please check the demo
<ul>
<li data-ng-repeat="note in notes">
{{ note }}
{{ $last ? update():''}}
</li>
</ul>
So, I'm just getting started with angularjs and I'm already confused. I want to change the colour of a list element that corresponds to a hex code colour that is in an array. I've tried some stuff but I just can't get it.
Here's my code so far:
HTML
<div id="mainContentWrap" ng-app="newApp">
<div id="personContainer" ng-controller="personController">
<ul id="personList">
<li class="bigBox no_s" ng-style="personColour" ng-repeat="i in persons" ng-hover="changeColor()">< href="#/{{i.person_id}}">{{i.person_name}}</a></li>
</ul>
Javascript:
var app=angular.module('newApp',[]);
app.controller('personController',function($scope,$rootScope){
$rootScope.persons=[
{person_id:'0',person_name:'Jim',colour:"cc0000"},
{person_id:'4',person_name:'Bob',colour:"f57900"},
{person_id:'2',person_name:'James',colour:"4e9a06"},
{person_id:'9',person_name:'Paul',colour:"3465a4"},
{person_id:'3',person_name:'Simon',colour:"77507b"}
];
$scope.changeColor(){
$scope.personColour=$scope.persons.color// not sure what to do here???
}
});
There is no ng-hover directive. You'll want to use ng-mouseenter and ng-mouseleave.
Also, keep in mind that the syntax for ng-style is an object corresponding the CSS key-value pairs.
<li ng-repeat="i in persons" ng-style="personColour" ng-mouseenter="changeColor(i)"></li>
$scope.changeColor = function(person) {
$scope.personColour = {color: '#'+person.colour};
};
If you'd like for the color to change back to what it was before you hovered, you can create two functions, or pass a parameter to $scope.changeColour:
<li ng-repeat="i in persons" ng-style="personColour" ng-mouseenter="changeColor(i,true)" ng-mouseleave="changeColor(i,false)"></li>
$scope.changeColor = function(person, bool) {
if(bool === true) {
$scope.personColour = {color: '#'+person.colour};
} else if (bool === false) {
$scope.personColour = {color: 'white'}; //or, whatever the original color is
}
};
To take it a step further
You could create a directive for each person.
<person ng-repeat="i in persons"></person>
// your module, then...
.directive('person', [function() {
return {
restrict: 'E',
replace: true,
template: '<li class="bigBox no_s">{{i.person_name}}</li>',
link: function(scope, elm, attrs) {
elm
.on('mouseenter',function() {
elm.css('color','#'+i.colour);
})
.on('mouseleave',function() {
elm.css('color','white');
});
}
};
}]);
If you want to hack stay in the view:
<div ng-repeat="n in [1, 2, 3]" ng-style="{ 'background': (isHover ? '#ccc' : 'transparent') }" ng-mouseenter="isHover = true;" ng-mouseleave="isHover = false;">
<span>{{ n }}</span>
</div>
in the code bellow i add easy code to understand how to active style with condition. I hope that help you
<li ng-style="( (isOver == 'true') && (linkToActive == 'm1') ) ? { 'background-color': '#00bdcb' } : {'background-color': '#ededed'}"
ng-mouseenter="vm.changeColorMenu('m1','true')" ng-mouseleave="vm.changeColorMenu('m1','false')">
</li>
<li ng-style="( (isOver == 'true') && (linkToActive == 'm2') ) ? { 'background-color': '#00bdcb' } : {'background-color': '#ededed'}"
ng-mouseenter="vm.changeColorMenu('m2','true')" ng-mouseleave="vm.changeColorMenu('m2','false')">
</li>
</ul>
Javascript Code
function changeColorMenu(indexMenu,bool)
{
$scope.isOver = bool;
$scope.linkToActive = indexMenu;
}
If you check an example here you will see that ng-style directive waits for css style, not just value, so in your case it'll be:
$scope.person.colourStyle={'background-color':$scope.persons.color}
and in html it'll be:
<li class="bigBox no_s" ng-style="i.colourStyle" ng-repeat="i in persons" ng-hover="changeColor()">< href="#/{{i.person_id}}">{{i.person_name}}</a></li>
edit:
And You also need to set colour value to full hex for example: '#cc0000'.
In Angular, there is not ng-hover directive, so you should use ng-mouseenter & ng-mouseleave to simulate it.
<ul id="personList">
<li class="bigBox no_s" ng-style="personColour"
ng-repeat="i in persons" ng-mouseenter="changeColor($index)"
ng-mouseleave="recoverColor($index)">
{{i.person_name}}
</li>
</ul>
And you should use $index to get your element in persons Array
$scope.changeColor = function() {
$scope.personColour = { 'color': '#' + $scope.persons[$index].color };
// or 'background-color' whatever you what
}
$scope.recoverColor = function() {
$scope.personColour = {};
}
See Plunker Demo Here
Use ng-style to conditionally apply CSS styles - I've chosen to name this style 'personStyle'. Next, bind the ng-mouseover event to set the personStyle background-color to the person's colour attribute. Finally, bind the ng-mouseleave event to reset the personStyle when the mouse leaves the element. The changeColor() function is not needed for this solution to work.
<div id="personContainer" ng-controller="personController">
<ul id="personList">
<li class="bigBox no_s" ng-repeat="i in persons" ng-style="personStyle">
<a href="#/{{i.person_id}}" ng-mouseleave="personStyle={}"
ng-mouseover="personStyle={ 'background-color':'#' + i.colour}">
{{i.person_name}}</a>
</li>
</ul>
</div>