JS Modified Ternary Operator? - javascript

I am aware of the JavaScript ternary operator condition? optionA : optionB and now I am seeing {{option: condition}} in Vue, and the behaviour seems to be that if condition holds the assignment is option, otherwise the assignment is empty. Is this 'binary' operator : something general for JS or particular to Vue?
The actual code:
<span :class="{ done: todo.done }">{{ todo.text }}</span>
where
.done { text-decoration: line-through; }
is a CSS and todo.done is a boolean.

It's not an operator but regular object literal syntax. Vue class attribute supports objects for conditional class lists, where boolean value determines whether class name from a key is added to a list or omitted.
This behaviour is similar to popular classnames package that serves the same purpose in React ecosystem.

If you wanted a binary operator, you should choose ||. This object syntax is not specific to vue but the usage is: What this code is saying is "Set the attribute done of the object bound to the class to todo.done, and vue will infer to add or not to add the class of the object parameter (in your case it is done).

Related

Add or remove a class based on a condition

I am adding / removing a class from an element’s classList based on a variable’s truthiness. However, I’m doing it in what appears to be an obtuse way:
if (myConditionIsMet) {
myEl.classList.add("myClass");
} else {
myEl.classList.remove("myClass");
}
Is there a way in which I could make this more sexy and dynamically call the add / remove chained function for example with a conditional operator such as:
myEl.classList.{myConditionIsMet ? add('myClass') : remove('myClass')};
The above is pseudocode, of course, and I would like as plain JS as possible.
There’s a toggle method on .classList which takes a second argument (force).
This boolean argument essentially takes a condition that adds the class if true, and removes the class if false.
myEl.classList.toggle("myClass", myConditionIsMet);
Your pseudocode js
myEl.classList.{myConditionIsMet ? add('myClass') : remove('myClass')};
can be translated to actual js
myEl.classList[myConditionIsMet ? 'add' : 'remove']('myClass');
which is not particularly readable, but does exactly what you described.
For readability, I would look at the toggle method.

Multiple class bindings in AlpineJS?

I'm trying to attach two :class bindings to a single element within an x-for loop. Usually this could be achieved by passing in a single object with multiple key:value pairs. In this instance however, one is a condition, the other is a property of the loop:
Condition:
:class="{'active': colours.includes(arrayItem.class)}"
Property:
:class="arrayItem.class"
Both of which work separately. I've tried adding them as separate attributes but only the first gets applied. I've also tried this (to no avail):
:class="{'active': colours.includes(arrayItem.class), arrayItem.class}"
I've searched through the docs but haven't found a solution.
Example:
https://jsfiddle.net/owjbu1ay/10/
You can use the array of classes when binding to the class attribute. The issue here is the object syntax {} here. You can use array of classes and use the ternary operator to conditionally render classes as shown below.
Now if the colours array includes the arrayItem.class it will apply the active class,
and the arrayItem.class will be the 2nd class applied without any conditions.
:class="[colours.includes(arrayItem.class) ? 'active' : '' , arrayItem.class]"

Vue equivalent of {{content?.body}} interpolation

In angular we could do something like {{content?.body}} and it will render the content body if it exist in your data.
This doesn't seem to work in Vue. Is there a way to achieve this or i have to check manually.
In Vue you can use v-if directive. For example;
<div v-if="content.body">
{{content.body}}
</div>
See for more at Vue official docs
This syntax does not exist in vue.js and it will probably never exists according to the creator of Vue.js (see this post)
However you could use get from lodash combined with computed property to simulate this behavior :
computed: {
nestedProperty() {
return get(this, 'here.is.my.nested.property')
}
}
But the easiest way is probably to just add v-if directive to your template to check that property exists
I’m guessing you’re looking for a similar approach to optional unwrap from swift or safe call operator from kotlin.
Neither JS or Vue.js support this.
Your safest bet is to use a v-if on the entire chain
<span v-if=“content && content.body”>
{{content.body}}
</span>

Error when using javascript ternary operator with knockout secure binding

When I use knockout-secure-binding with ko, and I try to use ternary operators inside data-bind, an error occurs.
Sample code:
<div data-bind="attr: { class: itemSelected() ? 'selected' : 'unselected' }"></div>​
KSB init:
var options = {
attribute: "data-bind", // default "data-sbind"
globals: window, // default {}
bindings: ko.bindingHandlers, // default ko.bindingHandlers
noVirtualElements: false // default true
};
ko.bindingProvider.instance = new ko.secureBindingsProvider(options);
Error:
Uncaught #<Object> knockout-secure-binding.js: 4
If I use the regular binder, without including the secure one, everything works as expected. Why is this happening? What can I do to keep using secure binding?
It's natural that it doesn't work. If you see the expressions section of the specs of sbind, , which is the language that you can use in data bindings when you use the secure bind binder, you'll see that the ternary operator isn't in the list.
You'll have to use a computed or pure computed that evaluates that expression, and bind the computed instead of the expression.
The computed could be like this:
self.selClass = ko.pureComputed(function() {
return self.itemSelected() ? 'selected' : 'unselected';
}, self);
NOTE: you can use a pure computed. This example shows the case of a view model created with a constructor that uses the self=this pattern. If you use other patter for your view model, like RMP, the computed will be slightly different
So, the binding woul be this one:
<div data-bind="attr: { class: selClass }"></div>​
which is a valid sbind expression.

multiple expression using ng-class to set and remove class

I saw others' solution but mine didn't work, probably there are snytax error because I'm applying multiple class.
ng-class="{'col-md-9 col-sm-8 col-xs-8':item.lp_image!='', item.lp_image='','col-md-12'}"
What you are defining in the ng-class attribute is a JavaScript object. You can define several rules, just like you define several properties of an object. Each key is a class, each value is a boolean or an expression that gives a boolean.
E.g.
{
'class1': false,
'class2': true,
'class3': 2 == 2,
'class4': 3.1415 > 0
}

Categories