What is the best way to store the data in the lowest common ancestor for effective communication among multiple identical components within a sibling network?

My Background:

  • I have expertise in Python and Vue development, with a history of using Vue dating back to 2016.
  • One of my clients operates a business focused on weight loss and meal planning: clients pay her for weekly single-page PDF menus that outline their daily breakfast, lunch, and dinner choices. (example menu)
    • Each meal is detailed with a list of ingredients.
  • Currently, she creates these menus using Excel, and I have been tasked with replicating and expanding this functionality into a Python/Vue application.
  • The application I am developing for her includes multiple "pages" or top-level components where she can manage clients, ingredients, recipes, as well as define meals for each day of the week through a complex UI component called WeeklyMenu.vue.
  • WeeklyMenu.vue consists of seven child components called DailyMenu.vue, one for each day of the week (Monday, Tuesday, etc.).
  • Each DailyMenu.vue component contains four Meal.vue components representing the meal types: Breakfast, Lunch, Dinner, and Snacks.
  • Note: Currently, the data within the DailyMenu.vue and Meal.vue components are self-contained rather than being accessed from a Vuex store.
    • For example, the ingredient lists for each meal are contained within the Meal.vue component's data attribute. This leads to numerous HTTP requests sent to retrieve individual meal data upon page load instead of fetching all data at once through a Vuex action.

The Issue:

  • The challenge arises as the client requires features wherein a change in one subcomponent should reflect in another subcomponent.
    • Specifically, she wants the app to synchronize changes made to common recipes across different meals of the week. For instance, modifying an ingredient in one meal should update other meals containing the same recipe.

Question:

What would be the best approach to address this scenario? Should I move ingredient data to the Vuex store or consider a hierarchical approach by storing it within the parent WeeklyMenu.vue component? How should this implementation work efficiently - with separate variables for each meal or a unified object encompassing all meal data?

If utilizing separate variables, passing every meal's ingredients as props to each meal seems inefficient. How can changes in one meal only affect similar meals?

Related Resources:

  • Communication between sibling components in VueJs 2.0
    • I am exploring the option of elevating ingredient data to the level of the WeeklyMenu.vue component following the "Lowest Common Ancestor" approach outlined here and here.

Example Scenario:

Answer №1

  1. A robust problem domain necessitates the utilization of Vuex, as relying on component data sharing via props is not scalable enough
  2. Store each Recipe as an object within a singular recipes object to avoid the need for watchers and enable Vue to re-render only relevant components upon changes
  3. Establish a "weekly menu" object within the store structure
  4. Utilize references (by name or unique ID) in the leaf nodes (Meals) of the weekly menu object to connect with recipes, allowing multiple instances of Meal.vue components to automatically update when using the same object from the store

Answer №2

After successfully implementing a simple example in CodePen, I plan to use it as a reference while working on integrating the actual site.

The key takeaway from this solution is that Vue will recognize and update changes within nested elements of a Vuex state object without any manual intervention. This means you can store all data in a single Vuex store object, especially when dealing with multiple identical sibling components that should respond to each other.

You can view the CodePen demo here: https://codepen.io/NathanWailes/pen/NWRNgNz

Screenshot

https://i.sstatic.net/R43zo.png

Overview of the CodePen Example

  • All menu data originates from a single weeklyMenu object within the Vuex store, divided into separate day and meal objects.
  • Each meal features computed properties with both get and set functions for retrieving and updating data from the store.
  • The DailyMenu and WeeklyMenu components retrieve their collective data through computed properties that iterate over the Vuex weeklyMenu object seamlessly.
  • To ensure consistency among same-named meals, a mutation in the Vuex store iterates through the meals and updates those sharing matching "Ingredient Name" values.

The code

HTML

<html>
  <body>
    <div id='weekly-menu'></div>
    <h3>Requirements:</h3>
    <ul>
      <li>Each row should have all the numbers in it summed and displayed ('total daily calories').</li>
      <li>The week as a whole should have all the numbers summed and displayed ('total weekly calories').</li>
      <li>If two or more input boxes have the same text, a change in one numerical input should propagate to the other same-named numerical inputs.</li>
      <li>Ideally the data (ingredient names and calories) should be stored in one place (the top-level component or a Vuex store) to make it more straightforward to populate it from the database with a single HTTP call (which is not simulated in this example).</li>
    </ul>
  </body>
</html>

JavaScript

// JavaScript code goes here
    

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

When you click, you will be directed to the specific details of the object

I have a recipe component that displays a list of recipes from my database and a recipe-detail component that should show the details of a selected recipe. What I aim to achieve is that when someone clicks on a recipe name, they are routed to the recipe-de ...

Problem arises with chai-http middleware when employing dynamic imports in chai 5.1.1 version

Currently, I am utilizing npm chai version 5.1.1 which has transitioned to supporting only imports and not requires. My use of dynamic imports has been successful so far. However, I have encountered an issue when incorporating the chai-http middleware with ...

Utilizing Node.js and Express alongside EJS, iterating through objects and displaying them in a table

Today I embarked on my journey to learn Node.js and I am currently attempting to iterate through an object and display it in a table format. Within my router file: var obj = JSON.parse(`[{ "Name": "ArrowTower", "Class" ...

Pop-up windows, the modern day digital version of fortune cookies

Expressing my requirement might be a bit challenging, but I will do my best. My goal is to create a web application using ASP.Net with C#. This project calls for functionality similar to the Windows popup: When a user clicks on the favorite button in IE- ...

Tips for correctly loading all elements on an HTML page before making CSS modifications

This question has been asked several times in the past. I am asking because when I used the on ready callback in jQuery, it did not change the placeholder text of my element "search_input". $( document ).ready(function() { $("#search_input").attr(' ...

Angular 2 - Graphic Representation Tool for Visualizing Workflows and Processes - Resource Center

Looking for a library that can meet specific requirements related to diagram creation and rendering. We have explored jsplumbtoolkit, mermaid, and gojs, but none of these fully satisfy our needs. For example, we need the ability to dynamically change con ...

Angular ng-repeat can sometimes lead to annoying flickering on the webpage

I have a code snippet that displays a list of thumbnails: <div class ="channel" ng-repeat ="channel in UIModel.channels" ng-class ="{evenchannel: ($index % 2) == 0, oddchannel: ($index % 2) == 1}"> <img class="channel-img" ng-src ="da ...

Rearrange Material UI styles in a separate file within a React project

Currently, I am developing an application utilizing material-ui, React, and Typescript. The conventional code for <Grid> looks like this: <Grid container direction="row" justifyContent="center" alignItems="center&q ...

Do closures truly behave like objects, or are they something else entirely? (It appears not)

Let me clarify right off the bat that I am not inquiring about how closures function, as I already have a grasp on that concept. What I am curious about is what data type should be assigned to closures. Essentially, a closure can be thought of as a record ...

Retrieve the native interface from the Puppeteer browser/page context

Can a native interface be obtained from the Browser or Page instance to verify if an object is an instanceof this interface? For example, in a testing scenario with jest (where CanvasRenderingContext2D is not available due to being a Node context rather t ...

After removing an item, Vue's computed property stops working

Utilizing Nuxt to showcase a table of contact data retrieved from an express API, I encounter an error message this.contacts.filter is not a function whenever I attempt to delete a contact. What could be the reason behind this issue? Why is it failing to ...

Exploring the use of barcodes with node.js

Having some issues with generating a barcode using a barcode module from NPMJS called npm i barcode. I am getting an error message res is not defined even after following the instructions. Can someone please guide me in the right direction? Here is my code ...

Discovering specific keywords within HTML tags and performing replacements using jQuery

I am searching for specific strings within my HTML code, and if I find them, I want to replace them with nothing. For example: HTML: <img src=`javascript:alert("hello ,world!")`> My goal is to locate keywords like javascript, alert, etc, within H ...

Preventing simultaneous AJAX requests with a single click

I am facing a challenge with handling multiple AJAX requests. Whenever a user clicks on a button, an AJAX request is triggered to enter a record into the database. However, if the user clicks on the button rapidly multiple times, it results in multiple sim ...

Send both file and model data using AngularJS with FormData

When uploading an image using the file input type along with other user data, my model includes the User class: public class User { public int Id { get; set; } public string Name { get; set; } public int Rollno { get; set; } public byte[] ...

Deactivate a chosen anchor button when clicked within a loop of elements

In my laravel project, I have a foreachloop that is rendering multiple buttons. I want to disable or remove only the button that is clicked, so I tried the following code: @foreach() <a onclick="remvebtn()" class="btn">My ...

I'm really struggling to get this angularJS ng-repeat to function properly

Something strange is happening with AngularJS. The first ng-repeat in the p tag works perfectly, but for some reason, the last div tag doesn't loop as expected: <p ng-repeat="item in supplierTeamObjects"> <a href="#" ng-click="se ...

Extract rotation values of X, Y, and Z from a Matrix4 in three.js

Is it possible to extract specific rotation values (X, Y, Z) in degrees (float) from the Matrix4 in three.js? Due to the lack of direct implementation in many of its functions, I am unsure how to achieve this. ...

Customize the Vuetify 2.0 sass variable $heading-font-family

I'm currently trying to customize the default variable $heading-font-family in Vuetify 2.0.0-beta.0, but I'm encountering issues with this particular override. Oddly enough, I have been successful in overriding other variables such as $body-font- ...

Enhance the standard input control in Vue.js by extending it to include features such as

Incorporating vue.js: Can you enhance a standard HTML input without the need for a wrapper element? I am interested in customizing a textarea like so: Vue.component('custom-textarea', { data () => { return { } }, template: &apo ...