`Cannot receive $emit event from child component in Vue Events`

I seem to be facing a simple issue that has me puzzled. I have a child component called "app-buttons" which contains an input field that I would like to monitor in order to filter a list based on the input value.

When I place the input field in the root component where the list resides, everything works perfectly fine. However, I wish to separate them and emit the search input value to the parent and then utilize it.

// This is the component where I want to listen for the search input

import Buttons from './app-buttons.js';
import Event from './vue-event.js';

export default Vue.component('post-item', {

template: `
<section class="posts flex" v-if="posts">
<app-buttons :posts="posts"></app-buttons>

<transition-group name="posts" tag="section" class="posts flex">
<article class="postitem" :class="{ 'danger': !post.published }" v-for="post in posts" :key="post.id">
<p v-if="post.published">Post is published</p>
<p v-else>Post is <em><strong>not</strong></em> published</p>
<h4>{{ post.title }}</h4>

<button type="submit" @click="post.published = !post.published">Change status</button>
</article>
</transition-group>
</section>
`,

data() {
return {};
},

components: {
Buttons,
},

props: {
posts: Array,
filterdList: [],
},

created() {
console.log('%c Post items', 'font-weight: bold;color:blue;', 'created');
},

computed: { },

methods: {
update() {
console.log('test');
}
}
});


// This is the component triggering the $event

import Event from './vue-event.js';

export default Vue.component('app-buttons', {
template: `
<div class="postswrapper flex flex--center flex--column">

<section :class="className" class="flex flex--center">
<button type="button" @click="showUnpublished">Unpublish</button>
<button type="button" @click="shufflePosts">Shuffle</button>
</section>

<section :class="className">
<input type="text" v-model="search" v-on:input="updateValue" placeholder="Search..." />
</section>

</div>
`,

data() {
return {
className: 'buttons',
search: '',
}
},

props: {
posts: Array,
},

created() {
console.log('%c Buttons', 'font-weight: bold;color:blue;', 'created');
},

methods: {
updateValue() {
this.$emit('searchquery', this.search);
},

showUnpublished() {
this.posts.forEach(item => {
item.published = true;
})
},
 
shufflePosts() {
this.$emit('postshuffled', 'Fisher-Yates to the rescue');
for (var i = this.posts.length - 1; i >= 0; i--) {
let random = Math.floor(Math.random() * i);
let temp = this.posts[i];

Vue.set(this.posts, i, this.posts[random]);
Vue.set(this.posts, random, temp);
}
},
}
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8>
<title>VuJS</title;

<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>

<div id="app">
<app-header :logo="logo" :name="name"></app-header>
<post-item :posts="posts" v-on:searchquery="update" v-on:sq="update" v-on:postshuffled="update"></post-item>
</div>

<script type="module">
import AppHeader from './components/app-header.js';
import PostItem from './components/post-item.js';

const app = new Vue({
el: '#app',
data: {
name: 'Vue App',
logo: {
class: 'vue-logo',
src: 'https://vuejs.org/images/logo.png',
},
components: {
AppHeader,
PostItem,
},
posts: [
{id: 1, title: 'Test', published: true},
{id: 2, title: 'New post', published: true},
{id: 3, title: 'Added', published: true},
{id: 4, title: 'Another post', published: true},
{id: 5, title: 'In the future', published: false},
{id: 6, title: 'Last post', published: true},
],
},

created() {
console.log('Created');
},

mounted() {
console.log('Mounted');
},

methods: {
update() {
console.log('updated');
}
},
});
</script>

</body>
</html>

Answer №1

You express:

I am working with a child component called "app-buttons", which contains an input field that I need to listen to in order to filter a list based on the input value.

Your current setup is as follows:

<div id="app">
    <app-header :logo="logo" :name="name"></app-header>
    <post-item :posts="posts" v-on:searchquery="update" v-on:sq="update" v-on:postshuffled="update"></post-item>
</div>

This implies that you are expecting post-item to emit a searchquery event, but it does not do so.

Within post-item, the code looks like this:

    <app-buttons :posts="posts"></app-buttons>

So you anticipate that app-buttons will emit an event and post-item will propagate it up automatically. However, Vue events do not work this way. If you desire this functionality, you must make sure that post-item handles the event explicitly:

    <app-buttons :posts="posts" v-on:searchquery="$emit('searchquery', $event)"></app-buttons>

Answer №2

After making changes to the markup, everything seems to be working well now. But is this the most efficient way to approach it? :) A big shoutout to Roy J for the assistance.

import Event from './vue-event.js';
import Buttons from './app-buttons.js';

export default Vue.component('post-item', {

template: `
<section class="posts flex" v-if="posts">
<app-buttons :posts="posts" v-on:searchquery="update($event)"></app-buttons>

<transition-group name="posts" tag="section" class="posts flex">
<article class="postitem" :class="{ 'danger': !post.published }" v-for="post in filteredItems" :key="post.id">
<p v-if="post.published">Post is published</p>
<p v-else>Post is <em><strong>not</strong></em> published</p>
<h4>{{ post.title }}</h4>

<button type="submit" @click="post.published = !post.published">Change status</button>
</article>
</transition-group>
</section>
`,

data() {
return {
search: '',
};
},

components: {
Buttons,
},

props: {
posts: Array,
},

created() {
console.log('%c Post items', 'font-weight: bold;color:blue;', 'created');
},

computed: {
filteredItems(search) {
return this.posts.filter(post => {
return post.title.toLowerCase().indexOf(this.search.toLowerCase()) > -1
});
}
},

methods: {
update(event) {
this.search = event;
}
}
});



// Child component
import Event from './vue-event.js';

export default Vue.component('app-buttons', {
template: `
<div class="postswrapper flex flex--center flex--column">

<section :class="className" class="flex flex--center">
<button type="button" @click="showUnpublished">Unpublish</button>
<button type="button" @click="shufflePosts">Shuffle</button>
</section>

<section :class="className">
<input type="text" v-model="search" v-on:input="updateValue" placeholder="Search..." />
</section>

</div>
`,

data() {
return {
className: 'buttons',
search: '',
}
},

props: {
posts: Array,
},

created() {
console.log('%c Buttons', 'font-weight: bold;color:blue;', 'created');
},

methods: {
updateValue() {
this.$emit('searchquery', this.search);
},

showUnpublished() {
this.posts.forEach(item => {
item.published = true;
})
},
 
shufflePosts() {
for (var i = this.posts.length - 1; i >= 0; i--) {
let random = Math.floor(Math.random() * i);
let temp = this.posts[i];

Vue.set(this.posts, i, this.posts[random]);
Vue.set(this.posts, random, temp);
}
},
}
});
Index same as before, just without alle the events on the components.

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

Issue with Shader UVs in ThreeJS occurs when a glTF model lacks textures

Currently, I am working on importing a glTF model that includes a UV set. My goal is to dynamically assign a texture to it in ThreeJS by injecting shader code into the existing using onBeforeCompile(). So far, everything functions properly. However, when ...

Calculation will not be updated if the radio button is selected programmatically

Apologies for the title, I struggled to find a better way to explain this problem. In my scenario, there are 3 radio buttons. The expected output should display the value of the selected radio button. However, the third radio button is unique as it contai ...

How to update data in AngularJS grid component using ng-bind directive

As a newcomer to AngularJS, I'm facing an issue that I need help with. Here's my problem: I have an ng-grid connected to a table. Inside the grid, there are values along with an ID (which is a foreign key from another table). Instead of display ...

Angular is not refreshing the DOM, but it is instead logging the data to the console

Can anyone explain why AngularJS is not updating the div, even though I can see the data in the console? What am I overlooking here? Here is a fiddle I created: function jsonp_example($scope, $http) { $scope.doRequest = function() { var url ...

Center the popover over the element

I am in the process of creating a resource map using SVGs. My goal is to display a popover in the center of the element when a user clicks on it. However, due to CSS rotation of the map, the traditional techniques such as the one mentioned here have not be ...

Enumerating items in a JSON dataset

I am facing an issue with my JSON data structure: var data = { "conv0": { "id":"d647ed7a5f254462af0a7dc05c75817e", "channelId":"emulator", "user": { "id":"2c1c7fa3", "name":"User1" }, "co ...

Combining two arrays without using concatenation, each from separate arrays but sharing one common variable

I'm struggling to combine two arrays in a specific manner and can't quite figure out the correct syntax to achieve this. primaryData = [1,2] secondaryData = [3,4] label = [label1, label2] Currently, I have this working data = $.map(la ...

"Enhance your table by adding a new row using user input in

I am just starting out with JavaScript and facing a challenge. I have created an HTML form to gather user input, with a submit button. My goal is to take the input values and add them as a new row in a table when the form is submitted. I have been strugg ...

tips for integrating external javascript in react applications

If you are working on an HTML page, you can include a JavaScript file using the following syntax: <script src="path"></script>. However, when it comes to retrieving variables from an external path in React, things get a bit more complex. For in ...

Vue warning: Issue encountered while executing setup function

[Vue warn]: Unhandled error occurred during the setup function <[...slug] onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< undefined > > During my development with Nuxt 3 (Vue 3), this error keeps popping up inexplicably. I suspect it occu ...

Utilizing JavaScript event handlers on dynamically appended elements after the document has finished loading

One issue I am facing is with a javasript function that needs to change the value of an element appended after the document has loaded. The problem arises when trying to intercept actions on a newly appended DIV, such as: <div class="new-div"></d ...

Quasar: Drawer now switches to Mini-mode automatically

Currently, I am using Quasar and I want the drawer to automatically switch to mini mode when users resize their browser window to make it smaller. At the moment, the drawer always remains open even when I narrow the browser width. Below is what I have tri ...

Storing external API requests in create-react-app's service worker for faster retrieval

I'm in the process of transforming a React web application into a PWA (Progressive Web App). I've made the necessary change in the index.js file - serviceWorker.register();. Everything is functioning properly as I can access the home page and as ...

What steps can be taken to convert this function into a more concise, dry function?

I'm attempting to customize a typewriter effect on my webpage, and while it successfully displays predefined data, I am struggling with converting it into a function that can receive values and then display those values. I have made attempts to modif ...

Is there a way to launch only a single popup window?

Recently, I came across this piece of Javascript code which is causing me some trouble: function call() { popup = window.open('http://www.google.co.in'); setTimeout(wait, 5000); } function caller() { setInterval(call, 1000); } func ...

Using a timer to make Ajax calls twice on a single webpage

Can multiple ajax calls be made simultaneously on the same page to different receiving div tags? I am struggling to find a solution to this issue. I have a total of 3 pages: a home page, and two PHP pages named status and alert which echo the results. Wi ...

Is there a way to access a JavaScript object using Perl?

Looking to manipulate a JavaScript Object file with 5.5mb of longitude latitude data? Consider opening it in Perl for applying a detail-reducing algorithm that will generate a new object file with reduced dataset. My approach involves using a for loop to s ...

Adding dynamic text to a <span> tag within a <p> element is causing a disruption in my layout

I'm encountering an issue with a Dialog box that displays a message to the user regarding file deletion. Here's how it looks: +-----------------------------------------------------------------------+ | Delete File? ...

Logging into Twitch API using asynchronous functions and VueJS

Hey there, I'm currently utilizing Nuxt to develop an application that integrates with Twitch. One of my main goals is to allow users to easily sign in using their Twitch credentials. I have already set up the necessary components within Twitch and o ...

Obtain a list of X characters from a nested array

When working with JavaScript, what is the most effective method for extracting all the X values from a multi-dimensional array and storing them in a new array? I am aiming to utilize either reduce or map if feasible. Is there a specific term used to descri ...