JavaScript DRY:er way of conditionally applying classes? conditionally applying class,conditionally apply class angular,conditionally apply class

I'm going through an array to apply different classes based on a state that is set externally. This is how I do it now, but I feel like i'm repeating myself a lot. Is there a DRYer way to do it? The classnames could be something else if that helps.

var children2 = Array.from(wrapper.children);
var s = state.state;
children2.forEach((child, i) => {
    var classes = [];
    child.classList.remove('active', 'before', 'previous', 'next', 'after');
    if(i < s) { classes.push('before'); };
    if(i > s) { classes.push('after');  };
    if(i === s) { classes.push('active') }
    if(i === s - 1) { classes.push('previous') }
    if (i === s + 1) { classes.push('next') }
    child.classList.add(...classes)
})
Answer:1

The easiest solution is to use toggle:

toggle( String [, force] )

When only one argument is present: Toggle class value; i.e., if class exists then remove it and return false, if not, then add it and return true.

When a second argument is present: If the second argument evaluates to true, add specified class value, and if it evaluates to false, remove it.

For example like this:

let classes = child.classList;
classes.toggle('before', i < s);
classes.toggle('after', i > s);
classes.toggle('active', i === s);
classes.toggle('previous', i === s-1);
classes.toggle('next', i === s+1);

You could also create an object with the keys and conditions, then loop over it to toggle them individually:

const classes = {
  before: i < s,
  after: i > s,
  active: i === s,
  previous: i === s - 1,
  next: i === s + 1,
};
Object.entries(classes).forEach(([className, condition]) => child.classList.toggle(className, condition));

(Note that Object.entries is an ECMAScript 2017 feature.)

Answer:2

Currently there is one pattern that is extremely repetitive in your code: "if (some condition), add this class". You could probably instead do something like this:

var classes = [
  i < s && 'before',
  i > s && 'after',
  i === s && 'active',
  i === s - 1 && 'previous',
  i === s + 1 && 'next'
].filter(x => x)

The first part of that code, var classes = [...], creates an array that looks something like [false, false, 'active', false, false], by conditionally adding items. For example, suppose i is 3 and s is also 3. When JavaScript evaluates i === s && 'active', it sees that i (3) === s (3), so it moves on to the next value, which is 'active', and sticks that inside the array. When it evaluates i === s + 1 && 'next', it sees that i (3) is not the same as s + 1 (4), so it immediately takes false and adds it to the list.

Then, we use filter to get rid of those false items, so we get an array more like ['active']. Basically, filter takes a function and passes each in the array item one by one to it; when the function returns a truthy value, it keeps the item, and otherwise, it removes the item. The function we passed is an arrow function; it just returns the value that is passed to it. You could replace it with function(x) { return x } and it would be functionally the same.

(I sometimes use .filter(Boolean) instead of .filter(x => x). Boolean can be used as a function to convert a value into a boolean (according to the "truthy" link above) - if you've seen !!x syntax before, it does the same thing. I find .filter(Boolean) more syntactic: "keep items that are truthy (like a boolean)". But it's entirely unnecessary because filter itself automatically checks if your function's returned value is truthy. So if you use it is just a matter of taste!)

Another option is to just get rid of the unnecessary braces and semicolons, like this:

if (i < s) classes.push('before')
if (i > s) classes.push('after')
// ..and so on.

It's certainly a bit more verbose, but you might prefer it anyways!

Answer:3

<div class="row"> <div class="col-md-4"> <div class="form-group label-floating"> <label class="control-label">Act</label> <input ...

<div class="row"> <div class="col-md-4"> <div class="form-group label-floating"> <label class="control-label">Act</label> <input ...

  1. jquery dynamically add rows form
  2. dynamically add rows to form

I've 1000's of users and user data looks like the below. Some users have the devices as [{some data}] (array), some users have devices as {some data}, and some users have devices as empty []. I ...

I've 1000's of users and user data looks like the below. Some users have the devices as [{some data}] (array), some users have devices as {some data}, and some users have devices as empty []. I ...

I want to make a function that takes an array as an argument, creates a random number from 1 - 10, and runs until it creates a number that is not in the array, and returns it. Here is jsfiddle ...

I want to make a function that takes an array as an argument, creates a random number from 1 - 10, and runs until it creates a number that is not in the array, and returns it. Here is jsfiddle ...

i am trying to submit a form via Jquery when change event occurs in select field like this: $('select#slc_level').change(function(event){ event.preventDefault(); console.log('changed') $('form#...

i am trying to submit a form via Jquery when change event occurs in select field like this: $('select#slc_level').change(function(event){ event.preventDefault(); console.log('changed') $('form#...

  1. submit form jquery ajax
  2. submit form jquery post
  3. submit form jquery button click
  4. submit form jquery validation
  5. submit form jquery not working
  6. submit form jquery php
  7. submit form jquery preventdefault
  8. submit form jquery with parameters
  9. submit form jquery without ajax
  10. submit form jquery on click
  11. submit form jquery laravel
  12. submit form jquery without refreshing
  13. submit form jquery stack overflow
  14. submit form jquery ajax asp.net
  15. submit form jquery get response
  16. submit form jquery
  17. submit form jquery ajax php mysql
  18. submit form jquery mvc
  19. submit form jquery asp.net mvc
  20. submit form jquery ajax codeigniter