In VUE, switching colors upon clicking is undone once the cursor moves away from the element

I need help with changing the color of a div when it is clicked.

Here's how the div is structured:

<li v-for="monomer in monomers">
    <div :style="monomerButton" @mouseover="hover = true" @mouseleave="hover = false" 
    @click="selectMonomer($event)" class="monomer-button">
        <p class="monomer-symbol">foot;{{monomer.symbol}}</p>
    </div>
</li>

This function is triggered on click event:

selectMonomer(event) {
    // If the p element gets clicked, get the div that contains the p element
    let element = event.target.nodeName === "P" ? event.target.parentElement : event.target
    element.style.backgroundColor = "rgba(44, 224, 203, 0.5)"
}

The color changes upon click but reverts back to original when mouse leaves the div. How can I make the color stay changed?

Edit:

monomerButton: {
    backgroundColor: getNodeColor(this.monomers[0].polymerType, this.monomers[0].naturalAnalog)
}

The background color depends on the type of monomer used.

Second edit: The component (let's call it A) is nested within another component (B). Component B structure:

<component B>
<ul>
  <li v-for="monomer type in monomer types">
    <component A :monomers="monomers of that type"></component A>
  </li>
<ul>
</component B>

For each monomer type (e.g., Glycine + analogs), a separate component A is created. Component A generates square div boxes with text for each analog. Thus,

getNodeColor(this.monomers[0].polymerType, this.monomers[0].naturalAnalog)
only takes the first element since all divs within one instance of component A should have the same color.

Answer №1

Thanks to the help of @Shoejep, I was able to come up with a solution.

// component A
mounted() {
        this.monomers.forEach(monomer => {
            monomer.selected = false
        })
    }

In the mounted hook, I assigned a 'selected' attribute to each monomer. Initially, they are all set to not selected.

// component A
<div :style="monomerButton(monomer)" @mouseover="hover = true" @mouseleave="hover = false" @click="selectMonomer(monomer)" class="monomer-button">
    <p class="monomer-symbol"&rt;{{monomer.symbol}}&rt;
</div>

I updated the :style attribute to utilize the return value of getMonomerStyle() function, as follows:

// component A
getMonomerStyle(monomer) {
    return {
         backgroundColor: monomer.selected ? "rgba(131, 222, 226, 0.8)" : getNodeColor(this.monomers[0].polymerType, this.monomers[0].naturalAnalog),
         borde:r this.monomers[0].monomerType === "Terminal" ? "2px dashed" : "1px solid"
        }
    }

Upon clicking on a mononer, that specific monomer is emitted to the parent component. This allows all other instances of component A to be aware of which monomer is currently selected.

Then it simply involves setting the selected attribute to true for the clicked monomer and setting it to false for the previously selected monomer.

if (this.previousSelected) {
    this.previousSelected.selected = false
    }
    monomer.selected = true
    this.previousSelected = monomer

Answer №2

Here is a suggestion for your code structure:

Add a selected property to each monomer. Then, when determining the style of the div, base it on whether that monomer is selected or not.

This approach can streamline some of the existing code. For instance, clicking on the p element will bubble up to the div and mark the corresponding monomer as selected.

Vue.config.devtools = false;
Vue.config.productionTip = false;

new Vue({
  el: "#app",
  data: {
    monomers: [{
        polymerType: "Test",
        naturalAnalog: "Test",
        symbol: "Test",
        selected: false
      },
      {
        polymerType: "Hello",
        naturalAnalog: "Hello",
        symbol: "Hello",
        selected: false
      },
      {
        polymerType: "World",
        naturalAnalog: "World",
        symbol: "World",
        selected: false
      }
    ],
    hover: true
  },
  methods: {
    getNodeColor: function(polymerType, naturalAnalog) {
      return "lightblue";
    },
    selectMonomer: function(monomer) {
      monomer.selected = !monomer.selected;
    },
    monomerButton: function(monomer) {
      return `backgroundColor: ${monomer.selected ? "pink" : this.getNodeColor(monomer.polymerType, monomer.naturalAnalog)}`;
    }
  }
});
ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

li div {
  padding: 8px;
}

li {
  margin-bottom: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <ul>
    <li v-for="monomer in monomers">
      <div :style="monomerButton(monomer)" @mouseover="hover = true" @mouseleave="hover = false" @click="selectMonomer(monomer)" class="monomer-button">
        <p class="monomer-symbol">{{monomer.symbol}}</p>
      </div>
    </li>
  </ul>
</div>

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

Guide to inheriting and overriding text styles

I am looking for a way to customize the style of all h6 elements within reactjs/material-ui, without using themes. I have attempted the code below, among other methods: const useStyles = makeStyles({ someClass: { h6: { fontSize: &qu ...

Disable the functionality of the next and previous buttons for the Bootstrap carousel when clicking on the outer

Here is the code for the carousel: The next/prev button functions under its respective div, how can I stop it? When I click on the div below the carousel, the carousel continues to move as usual. Below the carousel div, there is another one with a tabbi ...

Converting (Geo)JSON data into an array of objects

I am new to JavaScript and facing some difficulties in converting GeoJSON to a JavaScript Object Array. Using JSON.parse, I successfully parse the JSON generated on the server into a JSON Object. The addGeoJson method from Google returns [object (Array)] ...

initiating a communication to a specific path with provided parameters

I am attempting to submit a request to the Laravel named route users.update with the parameter user: const saveUser = () => { router.put(route("users.update", user.value.id), user.value); submitted.value = true; createUserDialog.va ...

Creating a stylish look for a selection of multiple menu options

option:active { color: red; } option:focus { color: green; background: green; } option:checked { color: yellow; background: yellow; } <select multiple> <option>One</option> <option>Two</option> <option&g ...

Creating Full-Page Background in CSS: Tips for Stretching Element Backgrounds to the Full Page Width

Just starting out with CSS and running into some issues. I'm attempting to create a solid colored top bar similar to the black bar at the bottom of this page. However, instead of the color extending from the borders of the page, it's creating a b ...

Difficulty of aligning div elements side by side in a container

It seems like I'm trying to achieve something similar to the following diagram. The two div elements are contained in a larger container with the class name "contentmain." --------|------- | | | | | | |updates|tweet | | ...

Guide on sending an array of objects to Material Vue Autocomplete

Context Currently, I am dealing with a situation where I am passing an array of objects to a material autocomplete feature. The documentation for this can be found here. However, upon selecting an item from the list for the first time, it throws an error ...

Creating a responsive loading button using Bootstrap 5

I'm struggling to create a button that displays a loading message. In my HTML file, I have: <div class="btn-area"> <button id="connectMetamaskBtn" class="btn sp-btn" type="button" ...

Retrieving AJAX Response and Assigning it to a JavaScript Variable

I've dedicated countless hours searching for assistance on how to implement an AJAX call in Javascript to communicate with a PHP script. My goal is to add a value to a table, retrieve the ID of the newly inserted row, and use that ID in a form submis ...

Is it possible to integrate a backbone model with Angular?

Below is an example of a Backbone post model: var Post = Backbone.AssociatedModel.extend({ urlRoot: ApiService.resolveRESTUrl('posts'), defaults: { age : 0, fname : "", lname : "", manager : null }, ...

Using JavaScript to launch a new window for a specific folder

When opening a popup window with a specific URL, I typically use the following code: $("#OpenFolder").click(function () { var url = "https://stackoverflow.com"; windowObjectReference = window.open(url, "ModulesList", " ...

Retrieve Object3D in three.js based on a custom property value

In my coding project, I have been creating instances of LineSegments in the following manner: const geometry = new THREE.BufferGeometry(); geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3)); const edges = new THREE.EdgesGe ...

Issues with Alignment of Items in Vuetify Data Table Columns

Upon reviewing the code provided, it appears that while the column headers and pagination display correctly (2 pages with 5 records each), all the data is showing in the first column in a jumbled manner. <!DOCTYPE html> <html> <head> ...

What is the best way to link a socket.id with an element in an array?

I am currently working on creating a chat-room where the names of connected users are shown in an 'Online Users' section. The following code snippet adds each user's name to an array and displays the contents of that array. However, if a u ...

JavaScript: Harnessing the power of scripts to handle dynamically loaded data via AJAX

I am currently working on a webpage where I need to display various events using AJAX and PHP. One requirement is that when a user clicks on the "view event" link at the bottom of each event, a modal window should pop up. To achieve this functionality, I h ...

Issue with Error in Expanding Label in Material-Ui using React

I have managed to increase the size of the Label in the TextField component of my React application. However, I am encountering an issue where it overlaps some text on its right when it shrinks. https://i.sstatic.net/BikHJ.png Here is the link for refere ...

Utilize a select box to toggle between enabling and disabling options

Could someone please help me with enabling and disabling a text field based on a select box option? I'm not sure if I have written the code correctly below. If there are any errors, please correct me. <body> <table width="500" border="1"> ...

Optimize your website by reducing the size of CSS, JavaScript, and HTML files through NUXT's

I'm currently working on a project in NUXT utilizing yarn for managing packages. My objective is to compress (and potentially merge) js, css, and html files to enhance load time efficiency. I came across "https://www.npmjs.com/package/nuxt-compress" ...

What is the proper way to utilize the "Long" type when declaring a schema in MongoDB?

Forgive my ignorance, but I am trying to achieve something like this: var mongoose = require('mongoose'); var Long = require("long"); var UserSchema = new mongoose.Schema({ id: Long(), name: String, completed: Long(), ...