I currently have two different working implementations of [ngClass] on an element;
[ngClass]="{ selected: element.isSelected, highlighted: element.isHighlighted}"
and
[ngClass]="element.customClasses"
Is it possible to combine both of these approaches in the template, or do I have to create a method in my component to return an array of classes based on the logic above?
Thanks!
I opted for using [class.*] to set the conditional classes, leaving [ngClass] to handle the binding;
<div
[ngClass]="element.customClasses"
[class.selected]="element.isSelected"
[class.highlighted]="element.isHighlighted"
></div>
You can directly set the customClasses to your template as
<span class="customClasses">something</span>
And also you can use [ngClass] which will append your classes based on the condition, so putting together
<span [ngClass]="{ selected: element.isSelected,
highlighted: element.isHighlighted}"
class="customClasses">something
</span>
Related
While migrating vue component to React, i am not able to understand that how can i apply those multiple classes in same div tag.
In Vue,
<ul>
<li v-for="m in Menus" #click="moveMenu(m)" class="primaryClass"
:class="{'ur-primay__selected':selectedMenu(m)}"> // selectedMenu() is a method
{{m.name}}
</li>
</ul>
My query is how can i apply this additional non-prop class attribute adding into the tag in React?
I have tried using template literal to add the classes but not able to do that.
classnames utility serves the same purpose in React and accepts an input that is similar to Vue class bindings and allows for a mix of strings, arrays and objects.
In Vue:
<li :class="['primaryClass', {'ur-primay__selected': selectedMenu(m)}]">
In React, an array can be flattened because it's possible to provide multiple arguments to the helper:
<li className={classnames('primaryClass', {'ur-primay__selected': selectedMenu(m)})}>
Using string template with backticks ``:
<div className={`${selectedMenu(m)?'ur-primay__selected':''}`}>
I want to check the condition in Angular.
I want to look at two numbers that would enter Div if these two numbers were equal.
How can I check this condition?
I tried the following method and it was wrong.
<div *ngIf="'{{item1.menuID==item2.menuID}}'">
{{item1.title}}
</div>
The code you have there would evaluate to a string given you're adding single quotes around the condition, also you don't need to interpolate to access an object inside an ngIf.
If you want to evaluate if item1.menuID and item2.menuID are equal you would do
<div *ngIf="item1.menuID == item2.menuID">
{{item1.title}}
</div>
You don't require to use interpolation within [anyAttributeEnclosingSquareBrackets] or any angular attribute like *ngIf, *ngFor or some attributes like formControlName
For example:
<child-component [childAttribute]="parentComponentVariable">
<div *ngFor="let x of arrayVariable">Array Variable is present in component</div>
<input type="text" formControlName="name">
You can directly compare like below code:
<div *ngIf="item1.menuID==item2.menuID">
{{item1.title}}
</div>
Assuming that, item1 and item2 are not private variables of component and are available or initialise expectedly
I'm new to Angular, just a question on the difference of Built-in Directives and property binding, below is some code I saw:
// ... just js expression, not relevant here
<div [ngClass]="'text-white' + ...">
Hello, World.
</div>
<div class="form-group m-2">
<label>Name:</label>
<input class="form-control" [value]=... />
</div>
so why we can't make ngClass a standard property binding just like [value] as:
<div [class]="'text-white' + ...">
why it has to be a directive?
Its possible to use [class] directly. It's even possible to combine with ngClass like in the following:
In app.component.ts
isActive = true;
componentClass = 'my-class';
In app.component.html
<div [class]="componentClass" [ngClass]="{ active: isActive }">hello</div>
If you inspect your html you will see this result:
<div _ngcontent-gej-c0="" class="my-class active">div</div>
But I wouldn't recommend it. When you will be constructing reusable components better let class attribute available for the end developer.
Literal values should be passed without brackets around the attribute.
ngclass="text-white"
If the value is variable you can pass it dynamically by wrapping the attribute in brackets:
Component.ts
myclass: string = 'text-white';
Component.html
[ngclass]="myclass"
You can also pass an object where each project is a CSS class name and the value true or false, true stating the class will be used false stating it will not.
[ngClass]="{'row': true, 'container': false}"
There is nothing stopping you building that dynamically too.
Component.ts
getClassses(): any {
return {'row': true, 'container': false}
}
Component.html
[ngClass]="getClasses()"
I started learning angular 5 3 days ago so I'm quite new at it. I also use angularJS and React to develop applications and I think I don't understand how angular 5 components fully work. If I create for example a custom button that has a custom text inside (I'm not saying this should be done this way but it's a simple example that shows my point) like this:
<app-button>
<app-text>
My Text
</app-text>
</app-button>
The rendered DOM results in:
<app-button>
<button>
<app-text>
<span>
My Text
</span>
</app-text>
</button>
</app-button>
which is unreadable, I wanted to know if there's a way to remove this wrapping elements and just place the components layout replacing the tags resulting in the following structure:
<button>
<span>
My Text
</span>
</button>
If there's no way of removing them what are your suggestions? thanks!
Angular components are directives with templates. According to this:
Directive configuration #Directive({ property1: value1, ... })
selector: '.cool-button:not(a)' Specifies a CSS selector that
identifies this directive within a template. Supported selectors
include element, [attribute], .class, and :not().
So component selectors can be also attribute selectors. For your example, instead of writing this:
parent.component.html:
<app-button>
<app-text>
My Text
</app-text>
</app-button>
write this:
parent.component.html:
<button app-button>
<span app-text>My Text</span>
</button>
where :
app-button.component.ts
...
selector: '[app-button]',
template: `<ng-content></ng-content>
...
app-text.component.ts
...
selector: '[app-text]',
template: `<ng-content></ng-content>`
...
this would be rendered as you expected:
Update after your comment about styling those buttons:
To style the buttons from inside the button component, and set class in parent component, use :host-context pseudo-class. It is not deprecated and works well
button.component.css
:host-context(.button-1) {
background: red;
}
:host-context(.button-2) {
background: blue;
}
app.component.html
<button app-button class="button-1">
<span app-text>My Text</span>
</button>
<button app-button class="button-2">
<span app-text>My Text</span>
</button>
Here is the DEMO
I had a similar issue. I'll provide my solution in case someone else has the same problem.
My component should be able to be used either within other components or as a route from <router-outlet></router-outlet>. When I used the selector as an attribute [my-component] things worked perfectly provided it was used within other components. But when created by <router-outlet></router-outlet> a <div> were created automatically.
To avoid that, we can simply use multiple selectors, and consider that the selectors can be combined.
Consider this: I want my component to use the attribute my-component and if it ever should be created by the <router-outlet></router-outlet> it should be wrapped in a <section></section>. To achieve this simply use:
#Component(
selector: 'section[my-component], my-component',
...
)
The result will be, if used inside another tag:
<whatevertag my-component>
... component content ...
</whatertag>
If used as a route:
<section my-component>
... component content ...
</section>
With the deprecation of bind-attr in favor of handlebar if statements for class name binding; how do I bind multiple class names to an element?
The documentation specifies the syntax for a single bound class name but not multiple:
http://guides.emberjs.com/v1.13.0/templates/binding-element-class-names/
<div class={{if isEnabled 'enabled' 'disabled'}}>
Warning!
</div>
Which results in (when isEnabled=true):
<div class="enabled"}}>
Warning!
</div>
But what if I need to bind other class names to this element? I've tried:
<div class={{if isEnabled 'enabled' 'disabled'}}{{if isNew 'new' 'old'}}>
Warning!
</div>
and (with and without the semicolon) ...
<div class={{if isEnabled 'enabled' 'disabled'; if isNew 'new' 'old'}}>
Warning!
</div>
The first is last-in wins and the second doesn't even compile.
Put quotes around the {{if}} helper:
<div class="{{if isEnabled 'enabled' 'disabled'}} {{if isNew 'new' 'old'}}">
</div>
You could also write a helper to do some of the work for you.
For reference, this is mentioned in the 1.11 release blog post.
Like many things in frameworks you can do this in multiple ways
1) You can have them both inline
<div class="{{if isTrue 'red' 'blue'}} {{if isAlsoTrue 'bold' 'underline'}}">
I have both classes
</div>
Some might argue that this on the brink of overwhelming your template with logic. I wouldn't fault you for this way, since it is only two classes, but as you expand your project you may want to consider option 2...
2) You can use use the classNameBindings of a component,
<script type="text/x-handlebars" id="components/my-cool-dealy">
<span>I love JSFiddle</span>
</script>
App.MyCoolDealyComponent = Ember.Component.extend({
classNameBindings: ['category', 'priority'],
category: function() {
//logic here
return "blue";
}.property(),
priority: function() {
//logic here
return "underline";
}.property()
});
Here is a JSFiddle of both ways