Modifying tag classes dynamically with JavaScript

I am working on creating a list of projects where the user can select one as the default project for future use in other processes.

The issue I am facing is that each project in the list has a unique id and by default, they all have the RegularIcon class attached to them. This is how it is structured:

<span :id="project.id" class="RegularIcon" @click="changeIcon(project.id, projectKey)"></span>

In this code snippet, projectKey represents the index of the current project in the list.

Here is the function I have implemented:

changeIcon: function(projectId, projectIndex) {

  let ClassName = document.getElementById(projectId).className;

  if (ClassName == 'RegularIcon') { 

    var x = document.getElementsByClassName("SolidIcon");
    var i;

    if (x.length != 0) {
      for (i=0; i < this.ProjectsList.length; i++) {
        if (i != projectIndex) { 
          x[i].className = 'RegularIcon'; 
        } else {
          x[i].className = 'SolidIcon'; 
        }
      }
    } else {
      document.getElementById(projectId).className = 'SolidIcon'; 
    }

  } else { 
    document.getElementById(projectId).className = 'RegularIcon'; 
  }

},

My intention was for the user to be able to click on an icon to toggle between filled and unfilled states, with the selected project becoming solid and filled while others return to their regular state.

However, upon testing the functionality, I encountered an error message :

Uncaught TypeError: Cannot set property 'classList' of undefined

Answer №1

Instead of directly manipulating the DOM, you have the option to utilize Vue's class binding feature to assign a specific class based on certain conditions:

<span :class="{ CLASS1: CONDITION1, CLASS2: CONDITION2, ... }">

In your scenario, this binding would look like:

<span :class="{ RegularIcon: CONDITION, SolidIcon: !CONDITION }">

Here, the value of CONDITION is determined by user selection (such as the selected index). For instance, when the icon's index does not match the selected index, the RegularIcon class will be active; conversely, if they do match, the SolidIcon class will be active.

<div v-for="(project, i) in projects">
  <span :class="{ RegularIcon: i !== selectedIndex, SolidIcon: i === selectedIndex }"
        @click="selectedIndex = i"></span>
</div>

new Vue({
  el: '#app',
  data: () => ({
    selectedIndex: -1,
    projects: [
      {id: 1},
      {id: 2},
      {id: 3},
    ]
  }),
})
<script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="0f797a6a4f3d213a213e38">[email protected]</a>"></script>

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.4.2/css/all.css" integrity="sha384-/rXc/GQVaYpyDdyxK+ecHPVYJSN9bmVFBvjA/9eOB+pb3F2w2N6fc5qB9Ew5yIns" crossorigin="anonymous">

<div id="app">
  <div v-for="(project, i) in projects" :key="project.id">
    <span class="fa-ghost"
          :class="{far: i !== selectedIndex, fas: i === selectedIndex}"
          @click="selectedIndex = i"></span>
  </div>
</div>

Answer №2

Consider utilizing the following:

document.getElementById(taskId).classList.add("newClass");
document.getElementById(taskId).classList.remove("oldClass");

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Async/Await moves on to the next function without waiting for the previous function to finish executing

I am developing a web application that requires querying my database multiple times. Each query depends on the data retrieved from the previous one, so I need to ensure each call completes before moving on to the next. I have attempted using async/await fo ...

Using React.PureComponent, the list component efficiently renders each item with optimized performance

We've developed a reusable list component in ReactJS. To address performance concerns, we decided to incorporate the shouldComponentUpdate method to dictate when our list component should re-render. public shouldComponentUpdate(nextProps: TreeItemInt ...

Creating template variable based on $state in AngularJS

Here is what I currently have: <span>{{ $root.page_header || "default" }}</span> However, I want it to default to default unless the current $state is a specific value. For example, if my states are: home, settings, & profile, then I wan ...

What is the best way to display div elements based on a selected option?

Here is the code for a select list that contains the number of guests for a room: <select name="txtHotelGuestNO" id="txtHotelGuestNO" class="hotels" onchange="show_room_choose()"> <?php for($i=1;$i<=100;$i++) echo "<option value=$i>$ ...

Emphasize the Jqgrid row when clicked on, but do not check the multiselect checkbox

Is there a method in jQgrid to highlight a row when clicked without selecting the multiselect checkbox? I attempted using Multiboxonly = true as suggested by Oleg on Your assistance would be greatly appreciated, as this issue is currently hindering progr ...

A comprehensive guide on properly obtaining user details in React with Redux and OIDC

Although I've dabbled in OIDC before, I wouldn't consider myself an expert. Currently, I'm trying to integrate OIDC into a react app using oidc-client-js and redux-oidc libraries, following the redux-oidc-example as a guide. Encountering th ...

Looking for an alternative to document.querySelectorAll?

My issue involves using querySelectorAll('a') to select all buttons, but I only want to target two specific buttons labeled 'Know More'. How can I achieve this? Below is the code snippet in question: const buttons = document.query ...

When an array object is modified in Vue, it will automatically trigger the get method to validate any

One of the challenges I am facing is related to a button component that has a specific structure: <template> <button class="o-chip border-radius" :class="{ 'background-color-blue': theValue.isSelected, ...

Using prevState in setState is not allowed by TypeScript

Currently, I am tackling the complexities of learning TypeScipt and have hit a roadblock where TS is preventing me from progressing further. To give some context, I have defined my interfaces as follows: export interface Test { id: number; date: Date; ...

Static parameter in Vue router

In my Vue Router, I need to pass specific information through the URL. For example: http://localhost/center/SHOPID/products http://localhost/center/SHOPID/categories http://localhost/center/SHOPID/... The SHOPID value will remain constant throughout th ...

Tips for creating a drawing grid with a table

I am currently working on a project where I need to create a canvas-like table with around 10,000 cells. The goal is to allow users to draw on this canvas by moving their mouse over it while holding down specific keys (e.g. ctrl for blue, shift for red). ...

The standard TextField functionality was disrupted by the update to MUI v5

After typing a comment in the TextField and trying to click Done, nothing happens because the TextField still has focus. The first click removes the focus, while a second click is needed to complete the action. <TextField id={'generalCom ...

How can we utilize a loop to continuously sum up numbers until we reach a multiple of another number, let's say when the total is divisible by 4?

I am trying to create a function in JavaScript that will detect when a given number is not a multiple of 4. If the number is not a multiple of 4, I want to add numbers incrementally until it reaches the closest multiple of 4. Here’s what I have so far: ...

Customizing the layout of specific pages in NextJSIncorporating

In my Next.js project, I'm trying to set up a header and footer on every page except for the Login page. I initially created a layout.tsx file in the app directory to apply the layout to all pages, which worked fine. However, when I placed another lay ...

Retrieving a specific attribute pair from a JSON object

Currently, I am trying to retrieve the temperature data and display it on my webpage. Since these are objects with no specific order, I am struggling to understand how to access them without using an index. { "response": { "version": "0.1", "termsofServic ...

What strategies can I use to reduce duplication in my HTML and JavaScript code?

Struggling with messy HTML and JS code? If you're using Bootstrap-3 and jQuery-1.11.0, dealing with dropdowns might be tricky. Especially when it comes to switching icons based on the dropdown state and ensuring only one dropdown is open at a time. Is ...

What is the reason for the initial DOM operation taking significantly longer than subsequent ones?

Why is the first operation much more despite the subsequent manipulation of the DOM being practically identical in time when both are written with the realization in JS and jQuery? Link to Javascript source // ES5 // Sending a message function sendMessa ...

Typescript struggling to load the hefty json file

Currently, I am attempting to load a JSON file within my program. Here's the code snippet that I have used: seed.d.ts: declare module "*.json" { const value: any; export default value; } dataset.ts: import * as data from "./my.json" ...

An error has occurred: Expected a string as the element type in React when attempting to update the state

I encountered an issue while trying to update the state after fetching data. Error: Element type is invalid - expected a string (for built-in components) or a class/function (for composite components), but received: undefined. This could be due to forgett ...

The value of type 'X' cannot be assigned to type 'Y' or 'undefined'

In my code, there is a component that requires a prop with an enum value: export enum AType { some = "SOME", word = "WORD", } const MyComponent = (arg: AType) => {} When I try calling this component like so: <MyComponent ar ...