Home > Mobile >  Add class to several elements in TypeScript
Add class to several elements in TypeScript

Time:08-14

I have switch that need's to add or remove class. In my .ts file I have:

export default class extends Controller {
  static targets = [
    "InformationOne",
    "InformationTwo",
    "InformationThree",
    "InformationFour",
    "InformationSwitchOne",
    "InformationSwitchTwo"
  ];

  private InformationOne: HTMLElement[];
  private InformationTwo: HTMLElement[];
  private InformationThree: HTMLElement[];
  private InformationFour: HTMLElement[];
  private InformationSwitchOne: HTMLInputElement;
  private InformationSwitchTwo: HTMLInputElement;

  switchInformation(): void {
    if (this.InformationSwitchOne.checked) {
        this.InformationOne.forEach((item) => { item.classList.remove("d-none"); });
        this.InformationTwo.forEach((item) => { item.classList.add("d-none"); });
        this.InformationThree.forEach((item) => { item.classList.add("d-none"); });
        this.InformationFour.forEach((item) => { item.classList.add("d-none"); });
    } else if (this.InformationSwitchTwo.checked) {
        this.InformationTwo.forEach((item) => { item.classList.remove("d-none"); });
        this.InformationOne.forEach((item) => { item.classList.add("d-none"); });
        this.InformationThree.forEach((item) => { item.classList.add("d-none"); });
        this.InformationFour.forEach((item) => { item.classList.add("d-none"); });
    }
  }
}

Now question is, how to make lines below more elegant? Is there a way to grab this three elements and perform on them classList.add rather then getting them one by one?

this.InformationTwo.forEach((item) => { item.classList.add("d-none"); });
this.InformationThree.forEach((item) => { item.classList.add("d-none"); });
this.InformationFour.forEach((item) => { item.classList.add("d-none"); })

CodePudding user response:

This can be simplified:

this.InformationTwo  .forEach((item) => { item.classList.add("d-none"); });
this.InformationThree.forEach((item) => { item.classList.add("d-none"); });
this.InformationFour .forEach((item) => { item.classList.add("d-none"); })

...to this:

const all = this.InformationTwo.concat( this.InformationThree ).concat( this.InformationFour );
for( const inp of all ) {
    inp.classList.toggle( 'd-none', /*force:*/ this.InformationSwitchOne.checked );
}

CodePudding user response:

As you describe in your last comment, you basically have a mapping of lists and switches and want to show the items for each switch, correct?

Then you can do something like this:

switchInformation(): void {
  // a mapping which items are shown for which switch
  const mapping = [
    // [HTMLInputElement, HTMLElement[]]
    [this.InformationSwitchOne, this.InformationOne],
    [this.InformationSwitchTwo, this.InformationTwo],
    [this.InformationSwitchThree, this.InformationThree],
    [this.InformationSwitchFour, this.InformationFour],
  ];

  for (const [{ checked }, items] of mapping) {
    for (const item of items) {
      // toggle "d-none" based on wether the switch is checked or not.
      item.classList.toggle("d-none", !checked);
    }
  }
}

And if the mapping doesn't change you can even move that out of the function.

  • Related