Adam Silva
Adam Silva

Reputation: 1047

VueJS Show element on child component one at a time

So I have several components <server-header>. It has the following HTML:

<span @click="$parent.changeOrder(column, $event)">
    <slot></slot>
    <i v-show="sortActive" class="order-arrow" :class="sort"></i>
</span>

These components are inserted in another component <server-list>. These will be the headers, that when clicked, will order some lists. My objective is to only show one arrow icon at a time.

E.g.: If I click on the first header, the arrow appears on that one. If I click on the second header, the arrow from the first header hides and the one on the second header appears.

This would be simple to do with jQuery for example, but I'm kind of lost on how to do this with VueJS.

Upvotes: 1

Views: 1424

Answers (2)

Ohgodwhy
Ohgodwhy

Reputation: 50787

Don't call parent functions directly. That is an anti pattern. Instead use 2-way data binding with sync and this is much easier. Rough example below:

// server-list.vue
data() {
  return {
     selected: undefined
  }
}

<server-header v-for="(header, idx) in headers" :header="header" :selected.sync="selected" :idx="idx"></server-header

Then in the child, we drop @click="$parent.changeOrder(column, $event)" in favor of:

@click="$emit('update:selected', idx)"

Make sure server-header has this prop expected:

props: ['idx', 'header', 'selected']

Then make sure we compare the idx to our header index:

<i v-show="selected === index"

Upvotes: 1

alexfertel
alexfertel

Reputation: 936

I assume you're rendering the <server-header> components with a v-for directive, looping a server_headers property in your <server-list> component data property.

The way i go with this is adding a prop to the <server-header> component like selected, then I add a selected property to each of the server_headers objects. Then i render the icon (<i>) with v-show if the correspondent selected property is true.

Like this:

server-list component

Vue.component('server-list', {
    data: () => ({
        server_headers: [{key: value, selected: true}, {key:value, selected:false}]
    }),
    template: `
      <div> 
           <server-header v-for="header of server_headers" :v-key="somekey" :selected="header.selected"></server_header>
      </div>
`
}

Vue.component('server-header', {
     props: ['selected'],
     template: `
         <span @click="$parent.changeOrder(column, $event)">
             <slot></slot>
             <i v-show="selected" class="order-arrow" :class="sort"></i>
         </span>
     `
})

Then, if i click on the arrow I would unset all the selected properties, and set the one i clicked. I hope this helps!!!!

Upvotes: 0

Related Questions