How to add a dynamic class in knockoutjs? - javascript

Let's say i have,
<span class="cls1 cls2" data-bind="title: title" ></span>
I want to add another class via JSON object,
{ title: 'a', clas: 'cls3' }
This work's,
<span class="cls1 cls2" data-bind="attr:{title: title,'class': 'cls1 cls2'+clas}" ></span>
But the problem is that it will add two class attributes. I need the cls1 and cls2 class on beginning. But need cls3 class after some event.

You should use css binding instead of attr for this. Read more about it in the documentation: http://knockoutjs.com/documentation/css-binding.html.
You code will look something like this:
<span class="cls1 cls2" data-bind="text: title, css: myClass" ></span>
Here is working fiddle: http://jsfiddle.net/vyshniakov/gKaRF/

Using multiple classes:
<span
class="yourClass"
data-bind="css: { myClass: (true == true), theirClass: (!true == false), ourClass: true }"
>Thine Classes</span>

You can use the css binding to do this:
<span class="cls1 cls3" data-bind="css: clas"/>
This adds the value of your "clas" property to the current class collection of the element

Related

Angular: Check if element has a class and add a class to another element

How can I check with Angular if a DOM element has a class and then add a class to another element?
My Template:
<div class="d-table">
<ui-switch class="d-table-cell">
<span class="switch">
<small></small>
</span>
</ui-switch>
<span class="d-table-cell">
sign in
</span>
</div>
If the span with the class switch has also the class checked, then the color of the text between the span element with the class d-table-cell should be black, otherwise the color should be gray.
No problem with jQuery, but I want to do it the right Angular way :)
.gray {
color:gray;
}
.black {
color: black;
}
<div class="d-table">
<span class="switch" #switch>
<small></small>
</span>
<span class="d-table-cell" [ngClass]="switch.classList.contains('checked') ? 'gray' : 'black'">
sign in
</span>
</div>
We can create template reference variables and can directly access them in the template to get attributes, classes and etc. #switch is a template reference variable
stackblitz
The Angular way would be to avoid, if possible, direct, low-level DOM manipulation. Tie the checked class to some model, and tie the d-table-cell's class to the same model. Like that:
<div class="d-table">
<ui-switch class="d-table-cell" [class.checked]="someVariable">
<span class="switch">
<small></small>
</span>
</ui-switch>
<span class="d-table-cell" [class.active]="someVariable">
sign in
</span>
</div>
and in TS
someVariable: boolean;
Maybe tie someVariable to an ngModel of some input, or whatever logic should dictate whether the switch is checked or not.
step: create a template ref for the main element like this:
HTML:
in the corresponding component:
#ViewChild('switchSpan') switchSpanElement:ElementRef;
After this, you can check the classlist of the said element like this:
if(switchSpanElement:ElementRef.nativeElement.classList.contains('checked')) {
...
}
step: create a boolean variable in the component, that you can access in the template as well (==don't make it private).
isSwitchChecked = false;
and you can make it check whether the class was added when change detecion runs (from this answer, syntax here)
class <yourComponent> implements DoCheck
...
ngDoCheck() {
this.isSwitchChecked = witchSpanElement:ElementRef.nativeElement.classList.contains('checked');
}
you can then bind that boolean variable in the template to add a class to the said span:
<span class="d-table-cell" [ngClass]={'some-class':isSwitchChecked}>
sign in
</span>
and you can define a class in css:
.some-class{
background-color: gray;
}

Populate elements with class name using Javascript

I have some HTML which looks like this
<p>Latte: <span class="hot-drink"></span></p>
<p>Capuccino: <span class="hot-drink"></span></p>
<p>Coca Cola: <span class="cold-drink"></span></p>
<p>Water: <span class="cold-drink"></span></p>
<p>Iced tea: <span class="cold-drink"></span></p>
I would like to use javascript to populate all of the <span> elements with the class hot-drink applied to them with the variable hot-drink-status().
So far I have managed to do this to only one of the elements. The code I wrote looks like this:
var hot-drink = "Avaiable";
document.querySelectorAll('.hot-drink')[0].innerHTML = hot-drink;
I believe I need to change the [0] to something else. I have tried [i] but this does not work.
I know that querySelectorAll is working as it allows me to apply the script to any element. I am just unable to apply the script to all element.
The outcome I am looking for is the HTML to be rendered as below
<p>Latte: <span class="hot-drink">Available</span></p>
<p>Capuccino: <span class="hot-drink">Available</span></p>
<p>Coca Cola: <span class="cold-drink"></span></p>
<p>Water: <span class="cold-drink"></span></p>
<p>Iced tea: <span class="cold-drink"></span></p>
All elements with the class hot-drink are populated with the text "Available"
Try (do not use minus char in variable names - camel case instead)
var hotDrink = 'Available';
document.querySelectorAll('.hot-drink').forEach(el=> el.innerHTML= hotDrink)
<p>Latte: <span class="hot-drink"></span></p>
<p>Capuccino: <span class="hot-drink"></span></p>
<p>Coca Cola: <span class="cold-drink"></span></p>
<p>Water: <span class="cold-drink"></span></p>
<p>Iced tea: <span class="cold-drink"></span></p>

angular change class by id

I have collection in angular. the collection looks like:
$scope.collection = [{id:'a1', title:'title 1'}, {id:'a2', title:'title 2'}];
<span ng-repeat="c in collection" id="{{c.id}}">{{c.title}}</span>
it is then itterate using ngRepeat in a span tag. in other line i have buttons that have custom property, let say data-span-id, like so:
<button type="button" data-span-id="a1">
<button type="button" data-span-id="a2">
when that buttons clicked, i want to change the class of the span that have id equal to data-span-id property. in jQuery
$('#'+$(this).data('span-id')).addClass('someclass');
how to this in angular? PS: spans and buttons is scallable.
It's hard to answer without seeing more of your code, but something along these lines is how I'd do it....
<button ng-repeat="item in collection" ng-click="selected = item.id">{{ item.title }}</button>
<span ng-repeat="item in collection" ng-class="{ 'someClass': selected == item.id }">{{ item.title }}</span>
So clicking a button sets a variable in the scope to the id you want, and then your span checks for that variable to set a class.

conditionally apply ngClass in AngularJS

any way to make an expression for ngClass to be a conditional. For example, I have tried the following using javascript:
$scope.setEnabled = function(status){
$scope.filterEnabled = status;
if(status){
angular.element(document.querySelector( '#enabledFalse')).removeClass('active-btn');
angular.element(document.querySelector( '#enabledTrue')).addClass('active-btn');
} else {
angular.element(document.querySelector( '#enabledTrue')).removeClass('active-btn');
angular.element(document.querySelector( '#enabledFalse')).addClass('active-btn');
}
}
And view :
div class="buttons">
<a id="enabledFalse" href="" ng-click="setEnabled(0)" class="click-btn active-btn">No</a>
<a id="enabledTrue" href="" ng-click="setEnabled(1)" class="click-btn">Yes</a>
</div>
What's the best way to apply this using ngClass?
Here is what the conditional statement would look like:
<a href class="click-btn" ng-class="{ 'active-btn' : filterEnabled }" ng-click="setEnabled(0)">No</a>
<a href class="click-btn" ng-class="{ 'active-btn' : !filterEnabled }" ng-click="setEnabled(1)">Yes</a>
And the js would simply be:
$scope.setEnabled = function(status){
$scope.filterEnabled = status;
}
Edit:
As an alternative, here's the most simplified method I can think of:
<a href class="click-btn" ng-class="{ 'active-btn' : filterEnabled }" ng-click="filterEnabled = !filterEnabled">{{ filterEnabled ? 'Yes' : 'No' }}</a>
You won't need anything in the js file; the Yes/No text and active-btn class will toggle when you click this single button, because they depend solely on the value of filterEnabled.
This is assuming only having one button is acceptable.
Outside of my SO-tag comfort zone, here, but you can use a ternary expression, where each tag is setup as the negation of the other:
... id="enabledFalse" ng-class="( filterEnabled)? 'active-btn' : ''"
... id="enabledTrue" ng-class="(!filterEnabled)? 'active-btn' : ''"
Other classes to be applied unconditionally can be placed in a regular class attribute.
Also in each tag:
ng-click="filterEnabled=!filterEnabled"
if you want each to toggle, or call the function as you have it.

How to have multiple data-bind attributes on one element?

I need to have multiple data bindings on one element. For example, I want a href as well as a html data-binding on one a tag. I have tried this,
<a data-bind="html: name"
data-bind="attr: { href: url }"
data-bind="attr: { 'data-prop': xyz }">
</a>
But this doesn't work. It seems knockout only supports binding one data-bind property? How to bind both the href, the inner html, and a custom "data-prop" attribute on one element?
Like this:
<a data-bind="html: name, attr: { href: url }">
You use comma-separated bindings - the attribute is the same as passing an object:
{
html: name,
attr: { href: url }
}
Or, if you're asking about multiple attr bindings at once:
<a data-bind="html: name, attr: { href: url, 'data-prop': FullName }">
This is how I implemented the source attribute and click event using data-bind. You may find it useful.
<img data-bind="{click: function(data, event) {ESVendorWidget.loadFunction(data,event)},
attr: {src: $data.Photo.PhotoUrl }}"
alt="package pic" class="big" />
I simply use:
<input type="checkbox"
data-bind="click: callFunction(), checkedValue: 0, checked: Card.Days">
for a checkbox element.
you can use multiple properties using , like below
<a data-bind="attr: { href: url, id: id , class: classvalue}">
object like this
{ url: 'http://stackoverflow.com', id:'newid' , classvalue: 'classname' }
you can use like below
data-bind="text: method.method_title, attr: {'id': 'label_method_' +
method.method_code}"

Categories