Multiple class bindings in AlpineJS? - javascript

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]"

Related

Why doesn't React use the object reference as key?

When rendering a list of items, React uses the index of each item as a default key, if none is supplied.
return <div>
{this.props.shows.map(show => <ShowComp title = {show.title}/>)}
</div>;
But why doesn't React use the JS object reference of each item instead? Seems to me like a much safer option, as it would not cause re-rendering of any of the items if the list order changes (as opposed to the index approach).
I'm relatively new to React, so I'm sure there's an underlying reason.
In Angular, ngFor (which renders a list of elements, similar to mapping object to React elements), it also has a trackBy configuration option (which is the equivalent of key in React). However, if it's not supplied, it uses the object references as an identifier, which seems more natural.
The reason why it's not using the reference of the object by default is all React's developpers choice.
Keep in mind it doesn't have to be unique across all the items, it has to be unique across the siblings of each item.
As shown here : https://reactjs.org/docs/reconciliation.html#keys
You could definitely use a not so unique key that's only unique across siblings.
Also, is using the reference of the object faster than most small integer found in unique ids ?

What does this code using [].filter.call do?

Iā€™m learning javascript and trying to write code that sorts a list, removing elements if they meet certain criteria.
I found this snippet that seems promising but don't have a clue how it works so I can adapt it to my needs:
list = document.getElementById("raffles-list").children; // Get a list of all open raffles on page
list = [].filter.call(list, function(j) {
if (j.getAttribute("style") === "") {
return true;
} else {
return false;
}
});
Can you guys help me learn by explaining what this code block does?
It's getting all the children of the "raffles-list" element, then returning a filtered list of those that contain an empty "style" attribute.
The first line is pretty self-evident - it just retrieves the children from the element with id "raffles-list".
The second line is a little more complicated; it's taking advantage of two things: that [], which is an empty array, is really just an object with various methods/properties on it, and that the logic on the right hand side of the equals sign needs to be evaluated before "list" gets the new value.
Uses a blank array in order to call the "filter" method
Tells the filter to use list as the array to filter, and uses function(j) to do the filtering, where j is the item in the list being tested
If the item has a style attribute that is empty, i.e. has no style applied, it returns true.
Edit:
As per OP comment, [].filter is a prototype, so essentially an object which has various properties just like everything else. In this case filter is a method - see here. Normally you just specify an anonymous function/method that does the testing, however the author here has used the .call in order to specify an arbitrary object to do the testing on. It appears this is already built into the standard filter method, so I don't know why they did it this way.
Array like objects are some of javascript objects which are similar to arrays but with differences for example they don't implement array prototypes. If you want to achieve benefits of array over them (for example like question filter children of an element )you can do it this way:
Array.prototype.functionName.call(arrayLikeObject, [arg1, [arg2 ...]]);
Here in question array like is html element collection; and it takes items without any styling.
list is assigned a collection of elements that are children of the raffles-list element
list is then reassigned by filtering its elements as follows
an empty array is filtered by calling it with the parameter list and a callback function. The formal parameters for call are this (which is the list) and optionally further objects (in this case a callback function)
The callback function receives a formal parameter j and is called for each element
If the element's value for the style attribute is empty the element is retained in the array. Otherwise it is discarded.
At the end list should contain all elements that don't have a value for its style attribute

how to add multiple class names with different conditions using ng class in angular?

I need to add 2 class names in specific conditions to an element:
ng-class="(commentItem.comment | escapeHtml | direction)"
works for the first, getting text content of given html string using the "escapeHtml" filter and then getting direction of the text using the "direction" filter.
now I need to add another class to the same element this way:
ng-class="{'hidden': commentItem.isEditing}"
how to mix them both in a single ngClass directive?
Note
I think it's not possible to use the
{"exp1": condition1, "exp2": condition2}
because in the first condition, the filter returns the class name for me.
Take a look at this plnkr.
The documentation for ng-class regarding the argument states:
Expression to eval. The result of the evaluation can be a string
representing space delimited class names, an array, or a map of class
names to boolean values.
It does not have to be a literal string or map or array. You can have a function return an array of classes like this:
ng-class="getClasses()"
And use whatever you like to construct the array in your controller. If you need filters use the $filter service.
If you don't want to use a controller function to handle view details you can pass an array to ng-class and for each element write na expression that returns a class name or an empty string:
ng-class="[!!redbg ? 'redbg' : '', 'gr' + 'een']"

Is there a preferred approach to setting an item's class using jQuery

Before jQuery I would have used something like the following code to set a class on an element:
document.getElementById("MyElementID").className = 'MyClassName';
This has the intended behaviour of replacing anything that was there before my new class name MyClassName
In jQuery the equivalent seems to be:
$('#MyElementID').attr('class', 'MyClassName')
But, we also have the in-built class functions, addClass(), removeClass() and toggleClass(). So to achieve the same effect, I would say:
$('#MyElementID').removeClass().addClass('MyClassName');
Obviously, the first jQuery example is more concise and requires just one function call (to attr, instead of addClass() and removeClass())
Can we also work on the assumption that I can't use prop as its an earlier (and currently unchangeable) version that I'm working with.
So what would you say is the preferred approach? Does the second sample give me anything over and above the first?
Many thanks in advance.
The addClass(), removeClass() and has() methods of jQuery use the className property of the element. The big advantage they offer is that they allow you to add or remove a class without affecting the other class names set.
The attr() method uses something like this:
document.getElementById("MyElementID")[name] = value;
For cases that you only need one class name, the attribute method will be probably faster. I personally however find the addClass method more elegant and easier to adapt if you need to add more class names in the future.
I think you should check the performance of all these functions. personally i think prop method is fastest ( introduced in v1.6)
see here the performance jQuery().attr vs jQuery().data vs jQuery().prop
http://jsperf.com/jquery-data-vs-jqueryselection-data/8
The difference is in this guy:
<div class="a_class another_class a_third_class">
attr('class','no_other_classes_now') <-- will replace everything in the class attribute even if there are multiple space separated classes. It's probably the lightest-weight of JQ methods for doing this since it's just using DOM methods that already worked properly across browsers for over a decade now.
.removeClass('a_third_class') will remove a class, leaving other classes intact.
.addClass('a_fourth_class') will add a space-separated class without replacing other classes.
^^ These two would have to do more work for a simple class overwrite than attr since they need to do find/replace type operations.
Prop is for changing properties of DOM elements that don't have HTML representatives like the window object (not likely to be useful very often due to other convenience methods) or that would be confusing because different attribute strings can mean different things. Like simply having the attribute "checked" without an equal sign or value being equivalent to checked="checked" or checked="true" as far as the boolean (true/false only) JS property is concerned in certain flavors of HTML. With prop you'll get the javascript property and not necessarily whatever is considered to be between the quotes of the actual HTML element.
When you're not in that type of situation, I would stick with the attr method. The whole point of prop seems to be to take work from the old attr method so I'd be surprised if it was faster in most cases. More importantly it's common and easy to read.

Jquery returns a list using id selector

I'm having trouble with jquery and selectors using the following code:
<div id="test"></div>
console.log($('#test'));
This always returns a list like [<div id=ā€‹"test">ā€‹</div>ā€‹] instead of the single element.
This results on always having to write $('#test')[0] for every operations instead of only $('#test'). Any idea on why?
Regards
Jquery will not return the HtmlElement, it returns a jQuery object.
A jQuery object contains a collection
of Document Object Model (DOM)
elements that have been created from
an HTML string or selected from a
document. Since jQuery methods often
use CSS selectors to match elements
from a document, the set of elements
in a jQuery object is often called a
set of "matched elements" or "selected
elements"
The jQuery object itself behaves much
like an array; it has a length
property and the elements in the
object can be accessed by their
numeric indices [0] to [length-1].
Note that a jQuery object is not
actually a Javascript Array object, so
it does not have all the methods of a
true Array object such as join().
http://api.jquery.com/Types/#jQuery
This is an example of the Composite Design Pattern
The Composite Pattern describes a group of objects that can be treated in the same way a single instance of an object can. Implementing this pattern allows you to treat both individual objects and compositions in a uniform manner. In jQuery, when we're accessing or performing actions on a single DOM element or a group of DOM elements, we can treat both in a uniform manner. http://www.addyosmani.com/resources/essentialjsdesignpatterns/book/#designpatternsjquery
jQuery encapsulates any objects found for a number of reasons. For one, it ensures that no matter what, null will never be returned for example. Rather, the elements found are inserted into a list. The fact that even though you're searching for a single element, the mechanism always remains the same and therefore the results will be placed into an array of one element rather than the element itself.
In jQuery it is better to think of selectors as matching multiple items, and your solution would be best if you use the each syntax to iterate through the matches items...
$('#test').each(function() {
console.log($(this));
});
As ID is not unique, jQuery looks for every element with such ID. So it's always returns a list, because threre is no guarantee that the element is exactly one

Categories