Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I access elements in v-for

I have a v-for loop iterating over an array called projects. I have another array called selectedProjects. When a project element is clicked, I'd like to add a class called selected to that specific element, as well as add the project.id property of that index to selectedProjects. Maybe I'm going about the whole problem wrong, is there a "vue" way to achieve this?

<!-- The template -->
<div v-for="project in projects" class="project" @click="">
    <p><i class="fa fa-folder"></i>{{project.name}}</p>
</div>

The component's data:

data: function(){
    return {
        projects: [...],
        selectedProjects: [],
    }
},
like image 402
Mav Avatar asked Oct 20 '18 10:10

Mav


People also ask

What does Key do in V-for?

The purpose of this key attribute is to give "a hint for Vue's virtual DOM algorithm to identify VNodes when diffing the new list of nodes against the old list" (from Vue. js Docs). Essentially, it helps Vue identify what's changed and what hasn't.

How do I get the index in V?

To get the v-for index in Vue. js, we can get it from the 2nd parameter. to render the items array with v-for . We get the index of each item from index .

How do I reference an element in Vue?

Refs are Vue. js instance properties that are used to register or indicate a reference to HTML elements or child elements in the template of your application. If a ref attribute is added to an HTML element in your Vue template, you'll then be able to reference that element or even a child element in your Vue instance.

How do you use V-model components?

Adding v-model to Custom Components To let our component support v-model two-way binding, the component needs to accept a value prop and emit an input event. To support v-model , the component accepts a value prop and emits an input event. With that, the custom component supports v-model two-way binding.


3 Answers

I would add a key selected on project objects.

The template will be like this

<div v-for="project in projects" class="project" :class="{selected: project.selected}" @click="select(project)">
    <p><i class="fa fa-folder"></i>{{project.name}}</p>
</div>

And add select event. If you need selectedProjects array for some reason, you can have a computed function rather than having two arrays in data.

methods: {
    select(project) {
        project.selected = true
    }
},
computed: {
    selectedProjects () {
        return this.projects.filter(project => project.selected)
    }
}
like image 68
Shu Yoshioka Avatar answered Oct 17 '22 19:10

Shu Yoshioka


You got the right idea going, just add a click handler and a $ref:

@click="onProjectClicked(project.id)" ref="`project${project.id}`"

And the methods implementation:

methods: {
  onProjectClicked(id) {
     this.selectedProjects.push(id)
     this.$refs[`project${id}`].$el.addClass('selected')
  }
}
like image 2
Brian Lee Avatar answered Oct 17 '22 20:10

Brian Lee


You can make use of Vue's dynamic class bindings to achieve this. Let's say that each of your projects has a property called isSelected (false by default). Then you can do the following ..

<div v-for="project in projects" class="project" :class="{selected: project.isSelected}" @click="handleClick(project)">
    <p><i class="fa fa-folder"></i>{{project.name}}</p>
</div>

Then in your script ..

  methods: {
    handleClick(project) {
      project.isSelected = !project.isSelected
      if (project.isSelected) {
        this.selectedProjects.push(project.id)
      } else {
        this.selectedProjects.splice(this.selectedProjects.indexOf(project.id), 1)
      }

    }
  }
like image 2
Husam Ibrahim Avatar answered Oct 17 '22 20:10

Husam Ibrahim