Understanding Vue.js: Effectively communicating updates between parent and child components using scoped slots

My goal is to develop a component with two slots, where the second slot repeats based on the number of items in the first slot. I have successfully implemented this using scoped slots. However, I noticed that when the data in the first slot is updated, the view in the second slot is not automatically refreshed unless an event like a button click triggers a method.

Is there a way to ensure that the second slot updates its view whenever the data changes in the first slot?

Here is an example of what I have:

Jsfiddle: https://jsfiddle.net/89vykm75/1/

new Vue({
el: '#app',
  components: {
  'repeat-for-each-item': {
      data: function() {
          return {
              items: []
          }
      },
    template: `<div>
          <slot name="item" v-for="item in items" :item="item"></slot>
          <button @click="addItem()">Add item</button>
          <slot name="repeat" v-for="item in items" :item="item"></slot>
      </div>
      `,
      methods: {
        addItem() {
          this.items.push({});
        }
      }
    }
  }
});
<div id="app">
  <repeat-for-each-item>
    <template slot="item" scope="props">
      <div>
        <input type="text" v-model="props.item.name">
      </div>
    </template>
    
    <template slot="repeat" scope="props">
      <div>
        <label>
            <span v-if="props.item.name">{{props.item.name}}:</span>
            <span v-else>No Name:</span>
        </label>
        <input type="text">
      </div>
    </template>
  </repeat-for-each-item>
</div>

Answer №1

After experimenting with different approaches, I discovered a solution that involves invoking a method on keyup.

To implement this solution, I attached an @keyup event listener to the input field in the following manner:

<input type="text" v-model="props.item.name" @keyup="props.onchange()">

Furthermore, I passed the onchange method to the slot within the component template like so:

<slot name="item" v-for="item in items" :item="item" :onchange="onchange"></slot>

Subsequently, I defined the onchange function to trigger a re-render as needed:

onchange:() => {
    // implementation to force updates
    this.$set(this.items, 0, this.items[0]);
}

If you would like to see the complete and operational code, you can visit the JsFiddle link provided here: https://jsfiddle.net/89vykm75/2/

I am curious if there is a more elegant solution available for this scenario.

Answer №2

Encountering an issue related to Vue's change detection caveats. The problem arises when adding a new property to an object after it has been added to the Vue data - Vue fails to detect the change. Here is a glimpse of the situation:

this.items.push({})

This snippet adds an object without any properties, and subsequently binds v-model to the non-existent name property of that object. As a result, Vue does not recognize the change and neglects updating other items linked to that property.

A working solution would involve:

this.items.push({name: null})

Implementing this adjustment will ensure proper functioning of your code. For a demonstration, refer to the revised JSFiddle.

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

Is there a way to transform an HTMLCollection into an array without depleting it of its elements?

I've been attempting to transform a collection of 4 divs in HTML into an array, but all my efforts seem to lead to the array becoming void. <div class="container"> <div class="shape" id="one"></div> <div class="sh ...

Creating a personalized notification box that is compatible with various screen sizes and web browsers on android devices with the help of

After successfully implementing a custom alert box to hide the header with JavaScript, I encountered an issue when trying to use it on different browsers and Android devices. The alert box appeared misplaced on the page and was too big for certain Android ...

Transforming into a serialized division

I am working on creating a custom WISYWIG editor that generates a div with specific inner elements. The goal is to design the div (along with its inner structure), serialize it, store it in a database as a string or JSON format, and later insert it into th ...

Tips for loading a webpage when a button is clicked with the help of jQuery AJAX and PHP:

Is it possible to dynamically load a page on button click, pass data to the new page using jQuery AJAX, and place the received value in an input field within the loaded page? Basically, the scenario is as follows: A button named "Something" triggers the l ...

Modify button behavior on click after the initial press

Struggling to make this work the way I want. I have a button that should execute Javascript function A when clicked, and in function A, I need to change the onclick attribute to function B. This way, on the second tap of the button, it will trigger functio ...

Utilizing AngularJS: Establishing a Universal Parent State in UI-Router for Modals and Shared Components

In my code using UI-Router and Bootstrap-ui modal, I have defined the state as shown below. reference var state = { name: 'modala', parent: 'home', onEnter: function($modal, $state) { modalInstance = $modal.open({ ...

What is the optimal arrangement for constructors or classes in JavaScript code?

Constructors, being objects that are stored as copies, appear to behave similarly to variables in terms of their placement within the code. Unlike functions, constructors cannot be placed "anywhere" and must instead be positioned above the area where they ...

How a Dynamic Icon Component in NextJS/React can disrupt Jest testing

Hello there! I'm a new member of this community, and usually I can find answers to my questions by searching. However, this time around, I need some help. My Current Setup I am using NextJS solely as a framework application without utilizing its API ...

Tips for preserving the jquery inputmask after updating the DOM

It's difficult to explain, but here is a snippet showcasing the issue. (function() { var PhoneNumber = function() { this.name = ko.observable(); this.phone = ko.observable(); }; $('[data-mask="phone"]').inputmask({ mask ...

Tips for executing getJSON requests one after the other

My goal is to showcase a weather forecast for a specific date on my website. Here are excerpts from the code I've used on a trial page that isn't functioning correctly: <script> function displayWeather(date){ $.getJSON(url + apiKey + "/" ...

Looking for a solution to fix the VueJS calculator that only works once?

My calculator project using VueJS, HTML and CSS is almost complete. However, I'm facing an issue where it only works once. For example, if I input 6x3, it correctly gives me 18. But if I then clear the result and try to input a new calculation like 3 ...

An issue was encountered with initializing digital envelope routines on a Vue.Js Project, error code 03000086

I'm encountering an issue with my Vue Project when I try to execute "npm run serve/build" syntax in the terminal. My npm node version is currently v18.12.0 (with npm 8.19.2) The error message being displayed is: opensslErrorStack: [ 'error:03 ...

Hovering over the Laravel Breeze dropdown will activate a dropdown feature

Recently, I've been working on a project with Laravel Breeze and have been utilizing some default components. The dropdown component used in the navigation bar caught my attention. By default, it requires a click for the menu to drop down below. Howev ...

What is the reason that the 'mouseenter' event only applies to the initial element in each round of iteration within a spacebar loop?

My goal is to create an off-canvas menu within a template component. I found inspiration from this helpful article. The setup I have is quite common: A container tab where I loop through an items collection An item component that contains the off-canvas ...

JavaScript event listener on the "change" event only triggers when changed manually [CodePen]

Check out this jsFiddle I created with all the data and information related to the issue. It should make it easier to understand what's happening: Take a look here: http://jsfiddle.net/lukinhasb/GuZq2/ $("#estado").val(unescape(resultadoCEP["uf"])); ...

Mastering the use of gl Scissor is essential for effectively implementing popups in your

I am attempting to implement a pop-up view on top of the current webGL view. My strategy is as follows: Whenever I need to display a popup, I create a scissorRect and begin rendering the popup scene onto it. I was hoping that the content of the previous s ...

Navigating through React Native with TypeScript can be made easier by using the proper method to pass parameters to the NavigationDialog function

How can I effectively pass the parameters to the NavigationDialog function for flexible usage? I attempted to pass the parameters in my code, but it seems like there might be an issue with the isVisible parameter. import React, { useState } from 'rea ...

Experiencing problems with npm and bower installations, along with deprecated modules while setting up angular-phonecat project

Trying to execute npm install in terminal while setting up angular-phonecat based on instructions from https://docs.angularjs.org/tutorial Encountering issues with deprecated modules and errors during the bower install phase. Seeking advice on how to upd ...

What is the best way to create a transparent sticky header that blends with the background while still maintaining visibility over images and text?

On my web page, the background features a radial gradient but the content extends beyond the viewport, causing the center of the gradient to not align with the center of the screen, producing the desired effect. However, I'm facing an issue with a sti ...

What could be causing me difficulty in integrating NProgress into my Next.js application?

Despite following all the necessary steps for implementing the nprogress package, I am facing an issue where the loading bar shows up when routes are changed but nprogress fails to function properly. I have attempted alternative ways such as linking the st ...