How do I bind multiple class names in Ember 1.13? - javascript

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

Related

why ngClass is not a standard property binding

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

Can I use vue.js v-if to check is the value exists in array

I have checkbox in form and I would like to use v-if directly to show/hide sections in accordance of selected checkbox values.
Is it possible or I should use watch: ?
It is possible. I would recommend adding a data model to the checkbox that toggles true or false. Then that will allow you to toggle the appearance of content using v-if.
Example:
<template>
<input type="checkbox" v-model="showContent" value="triggerString" />
<p v-if="showContent === 'triggerString'">Lorem ipsum</p>
</template>
<script>
export default {
data() {
return {
showContent: false
}
}
}
</script>
Generally speaking, we try not to use watch when we don't have to.
Update: Using the JSFiddle you included, this is how you would do it with just v-if
<template>
<input type="checkbox"
v-model="section"
name="section"
value="Epiphone"
id="epiphone">
<label for="epiphone">Epiphone</label>
<section v-if="section.includes('Epiphone')">
<h1>Epiphone</h1>
</section>
</template>
<script>
export default {
data() {
return {
section: []
}
}
}
</script>
Since there is two way binding occurring on the section array you created, there is no need for an additional div object since the only tracking that will occur will be in the section object.
The key thing to remember about v-if is that it can take actual JS expressions in it and not just data values. So you can extract out the logic from your watch method and simply plug it in there.
Hope this answers your question!

Angular2 [ngClass] - Combining direct binding with conditional classes

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>

Ember bind-attr not updating

I have a view with the following:
App.MyView = Ember.View.extend({
isSet: false,
layoutName: 'myview',
click: function() {
this.set('isSet', !this.get('isSet'));
}
};
And the template for it:
<i {{bind-attr class=":fa isSet:fa-check"}}></i> Toggle
The click event is working fine, and updates isSet (I can see that in ember inspector), but the bound class does not get added. Is there something wrong in my logic?
Use view.isSet instead of isSet in your template.
<i {{bind-attr class=":fa view.isSet:fa-check"}}></i> Toggle
Another possible solution, not to the OP's problem but to one with a similar title.
When using bind-attr to bind property changes and element class, it is important to include also static class mapping inside the bind-attr helper and not in a separate, static, class attribute.
This will not always work:
<div class="round" {{bind-attr class="highlighted:hl"}}>Inner text</div>
The correct way is:
<div {{bind-attr class=":round highlighted:hl"}}>Inner text</div>
If you are using above ember 1.11
then use the below tag
Reference :
http://www.hutchinson.io/bind-attr-is-dead/

Most Angular way to add class on click

I'm building an interface with a lot of toggles to control what data is being filtered in a different part of an App's search results. Here is a codepen of it: Here
Coming from a jQuery/Backbone background, what is the most Angular way of toggling the 'active' state of any/all of the filter items? Essentially, almost any <li> tag presented here is a toggle-able feature.
In jQuery, I would put a listener on the view and wait for any click events to bubble up and toggle an 'active' class on the event.target. I want to do it the best way with Angular.
(Also, this is my first Angular project.. I am probably doing all sorts of things the wrong way. Apologies in advance.)
Edit: To clarify the question, I have an App Interface with 20+ possible filter attributes to control a separate module on the page. Every time someone toggles one of these filter attributes, I want to add/remove an 'active' class. Do I put an 'ng-click="function(...)"' in the ng-repeat for each controller? Or is there an easier way to manage this module-wide behavior (a la event bubbling, like in Backbone/jQuery) ?
Thanks!
You can do something like this:
<section ng-init="active = 'areaFoo'">
<div ng-class="{active:active == 'areaFoo'}" ng-click="active = 'areaFoo'"></div>
<div ng-class="{active:active == 'areaBar'}" ng-click="active = 'areaBar'"></div>
</section>
It will populate $scope.active for you, and is very angular as it leverages existing directives, manages the state on scope, and does not leverage dom api's or events outside of directives. There is really no need to involve the controller here, as its display logic.
Learn more about ng-class here.
Multiple active elements
<section>
<div ng-class="{active:areaFoo}" ng-init="areaFoo = true">
<button ng-click="areaFoo = true">activate</button>
<button ng-click="areaFoo = false">de activate</button>
</div>
<div ng-class="{active:areaBar}" ng-init="areaBar = false">
<button ng-click="areaBar = true">activate</button>
<button ng-click="areaBar = false">de activate</button>
</div>
<div ng-class="{active:areaBar}" ng-init="areaBaz = false">
<button ng-click="areaBaz = true">activate</button>
<button ng-click="areaBaz = false">de activate</button>
</div>
</section>
you could also toggle with something like this ng-click="areaFoo = !areaFoo"
I was able to come up with a solution I'm ok with, for anyone curious you can see a demo Here.
Here are the relevant code snippets:
<li ng-repeat='category in data' ng-class='{active: category.isActive}' ng-click='toggleActive(category)' >
<span class='solr-facets-filter-title'>{{category.catTitle}}</span>
<span class='solr-facets-filter-count'>{{category.catResults}}</span>
</li>
An ng-click calls a method on the Controller, toggleActive(category). The current data model gets sent to the method. In the JS:
$scope.toggleActive = function(category){
category.isActive = !category.isActive;
}
The function returns the opposite of the isActive attribute back to the li in question: an ng-class adds the active class for a truthy state of isActive.
I'm not a huge fan of how I have to adjust the data model with flags for active/inactive states like this, but it ends up working out for the best in this case. I can push those isActive states back to the $scope so that other parts of the App can run queries based on that information.

Categories