Reputation: 93
I have different groups of words on a single page, let's say nouns verbs and adjectives. The way to describe each group is with its 'part-of-speech'. This 'part-of-speech' is being printed inside a little box. So you have the 'part-of-speech' of the group, noun, in the little box, and I want to achieve that when I click on that box I hide verbs and adjectives. If I were to click on verb I would hide nouns and adjetives, and so on. Right now the 'part-of-speech' of each group is being passed in as a prop.
The problem is that I'd like to compare parts of speech that exist on the current page with the clicked part of speech, but I cannot manage to differentiate it.
In my template I've got:
<div class="part-of-speech">
<p class="pos">{{ pos }}</p>
</div>
and this { pos }
is coming from my props
props: {
pos: {
type: String,
required: false,
default: "na"
}
},
mounted() {
console.log(this.pos)
}
This gives me all the parts-of-speech that are being printed on the page (take into account that this is a child-component of something else and these groups of words are printing as many times as there are groups). So I though that adding a method to detect the clicked part-of-speech would help.
<div class="part-of-speech" @click="handleSelectedPos(pos)">
<p class="pos">{{ pos }}</p>
</div>
props: {
pos: {
type: String,
required: false,
default: "na"
}
},
methods: {
handleSelectedPos(pos) {
console.log(pos);
console.log(this.pos);
}
}
When I click on the current item, I get the current part-of-speech, and as you can see this.pos
in this context is no longer the list of parts-of-speech that are on the page but it has become the currently clicked part-of-speech. My idea was to make the comparison somehow between pos
and this.pos
, but they are now identical.
How to make the comparison to say: If there are parts-of-speech that are not equal to the one currently clicked, take some action (add a class or wtv) to hide the element.
Upvotes: 2
Views: 437
Reputation: 8329
If I understand well, what you would like to achieve, then some of the events shouldn't be handled by the subcomponents, but by the parent component.
Vue.component('partOfSpeech', {
props: ['pos', 'text'],
template: `<div :class="pos" @click='emitEvent'>{{text}}</div>`,
methods: {
emitEvent() {
this.$emit('emitpos', this.pos)
}
}
})
new Vue({
el: '#app',
data: {
words: [{
pos: 'noun',
text: 'noun1',
compare: false
},
{
pos: 'verb',
text: 'verb1',
compare: false
},
{
pos: 'adjective',
text: 'adjective1',
compare: false
},
{
pos: 'noun',
text: 'noun2',
compare: false
},
{
pos: 'verb',
text: 'verb2',
compare: false
},
{
pos: 'adjective',
text: 'adjective2',
compare: false
},
{
pos: 'verb',
text: 'verb3',
compare: false
},
{
pos: 'noun',
text: 'noun3',
compare: false
},
{
pos: 'adjective',
text: 'adjective1',
compare: false
},
]
},
methods: {
filterWords(val) {
this.words.forEach(e => {
if (e.pos === val) {
e.compare = true
} else {
e.compare = false
}
})
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<part-of-speech :key="i" v-for="(word, i) in words" :pos="word.pos" :text="word.text" v-on:emitpos="filterWords" :style="{ color: !word.compare ? 'black' : 'red'}" />
</div>
In the snippet above you can see that every
@click
) $emit()
an event and their prop back to the parentThe problem is that sibling elements do not know anything about each other: they’re not supposed to share any information with each other.
A component can share its own unique state information with sibling components either via their common parent (by emitting an event (with a data payload)) or by using some form of state management solution (event bus or Vuex store are the most common in Vue - the latter is for serious cases, the former is for occasions that require more than simple event emitting, but doesn’t require anything really complicated).
Custom events in Vue: https://v2.vuejs.org/v2/guide/components-custom-events.html
Event bus: https://alligator.io/vuejs/global-event-bus/
Vuex state management: https://vuex.vuejs.org/
Upvotes: 1