I have a function that is filtering data based upon clickable button (seen in console logs). When I put this array into my modal as a v-for 'loop', I break my button function. Why? Each time I do this, I get 'undefined' results. This idea worked fine for displaying table row data based on the skedDatas array.
Function getrowid within /src/pages/courses/ammo04.vue. Code is at github: https://github.com/EnergeticPixels/catalog
I would not call methods directly in the template of your component. Any time a rerender happens, the method reruns, which is going to cause problems and other side effects if you're not very careful. I suggest using a ref variable to hold the data. Being scoped to the entire component, you can use it in both your script and template code without needing to pass it around/return it anywhere.
First, updating the button to pass classId
as a parameter to the toggleModal function, showing that the use of data attributes is not needed with Vue:
<td><button @click.prevent="toggleModal(skedData.classId)">{{ skedData.contact }}</button></td>
const toggleModal = (classId) => {
getclickedrow(classId);
modalActive.value = !modalActive.value;
}
Passing it again as a parameter to getclickedrow
and using a ref to hold the result of the array filter (which I would change to Array.find if the expected result is always 1 object, which I think it is...):
const skedfiltered = ref(null);
const getclickedrow = (classId) => {
skedfiltered.value = skedDatas.find(offering => {
return offering.classId === classId
});
};
I saw this next code was commented out, but I noticed if made into a computed property it will automatically re-evaluate itself based on the above skedfiltered
ref, always giving you the desired Poc. This also looks like a better job for Array.find than Array.filter. Just be careful when skedfiltered
is initially null, finding or filtering won't work (hence the optional chaining to catch this)
// filter sitePoc array for matching clicked contactId
const filteredPoc = computed(() => sitePocs.find(poc => {
return poc.contactId === skedfiltered.value?.contactId
}))
computed needs to be imported, so change the line at the top:
import { ref, computed } from 'vue';
Finally, setting the rest of the template code to display all of the data evaluated above:
<ContactInfo v-if="filteredPoc" :filteredPoc="filteredPoc" class='contactInfo' @close="toggleModal" :modalActive="modalActive">
<h2 class="title has-text-centered is-size-3">{{ filteredPoc.pocTitle }}</h2>
<p class="">Please contact the following individual(s):</p>
<ul>
<li><span class="has-text-weight-bold">Name:</span> {{ filteredPoc.pocName }}</li>
<li><span class="has-text-weight-bold">Email:</span> {{ filteredPoc.pocEmail }}</li>
<li><span class="has-text-weight-bold">Commercial Phone 1:</span> {{ filteredPoc.pocPhone1 }}</li>
<li><span class="has-text-weight-bold">Commercial Phone 2:</span> {{ filteredPoc.pocPhone2 }}</li>
<li><span class="has-text-weight-bold">DSN:</span> {{ filteredPoc.pocdsnPhone }}</li>
</ul>
<div v-if="filteredPoc.altpocName">
<p class="">Or their alternate:</p>
<ul>
<li><span class="has-text-weight-bold">Name:</span> {{ filteredPoc.altpocName }}</li>
<li><span class="has-text-weight-bold">Email:</span> {{ filteredPoc.altpocEmail }}</li>
<li><span class="has-text-weight-bold">Commercial Phone 1:</span> {{ filteredPoc.altpocPhone1 }}</li>
<li><span class="has-text-weight-bold">Commercial Phone 2:</span> {{ filteredPoc.altpocPhone2 }}</li>
<li><span class="has-text-weight-bold">DSN:</span> {{ filteredPoc.altpocdsnPhone }}</li>
</ul>
</div>
</ContactInfo>
Added v-if="filteredPoc"
which is for error prevention. Even when the modal is not visible, all elements get rendered to the DOM, and if filteredPoc
is null (and it is initially), all these elements trying to use it will cause an error, so the v-if
will prevent that. The v-if
will evaluate to true by the time modalActive is toggled true, so it should all work out.