Background:
- I'm a Python/Vue developer; I've been using Vue since 2016.
- I have a client who runs a weight loss / meal planning business: clients pay her to prepare weekly single-page PDF menus that tell them (the clients) exactly what to eat for breakfast, lunch, and dinner of every day of the week. (image of an example menu)
- Each meal is shown as a list of ingredients.
- Right now she's preparing these menus in Excel, and she hired me to reproduce and extend the functionality of what she has in Excel, but in a Python/Vue app.
- The app I'm building for her has many "pages" ("top-level" components) to allow her to add/modify/delete objects like clients, ingredients, and recipes (image), but the most complicated part of the UI is the component in which she can define the meals for every meal of every day of the week (image). That component is named
WeeklyMenu.vue
. WeeklyMenu.vue
itself contains sevenDailyMenu.vue
children, one for each day of the week (Monday, Tuesday, etc.). (image)- Each
DailyMenu.vue
component itself contains fourMeal.vue
components, one for each of four meal types: Breakfast, Lunch, Dinner, and Snacks. (image) - Important: At the moment, the
DailyMenu.vue
andMeal.vue
components themselves contain their data rather than accessing it from the Vuex store.- For example, the list of ingredients for each meal is contained within the
Meal.vue
component as amealIngredients
variable within the component'sdata
attribute. (image) - Side-note: This means that there are lots of HTTP requests being sent to the back-end when the page loads as all of the meals are requesting their own data, rather than a single request being sent via a Vuex action (for example). This seems like it can't be best practice.
- For example, the list of ingredients for each meal is contained within the
The problem:
- The problem is that she is now asking me to add features in which a change to the data in one subcomponent should update the data in a different subcomponent.
- For example, she wants the app to work so that when she has the same recipe in several different Meals of the week, then a change to an ingredient in one of the meals will propagate to the other meals that have the same recipe. (image explanation)
My question:
What is the best practice for handling a situation like this? Should I move the ingredient data into the Vuex store or (in the same vein) the lowest-common-ancestor WeeklyMenu.vue
component? If so, how exactly should it work? Should there be a separate variable for each meal? Or should I have an object that contains data for all of the different meals? If I use a single object, do I need to worry that a watcher on that object in the Meal.vue
component would be triggering even when a change was made to a different meal's data?
If I store all the meal ingredients in separate variables, I would need to pass all of those to every meal (so every meal would need to receive every other meal's ingredients as separate props). So that doesn't seem like the right way to go.
If a user is making a particular change to a particular meal, how would I only have the other meals with the same name react?
Related links:
Simplified example of the situation I'm trying to handle:
- Without Vuex: https://codepen.io/NathanWailes/pen/zYBGjME
- Using Vuex: https://codepen.io/NathanWailes/pen/WNxWxWe
- With everything working (including the state being kept in Vuex) except the propagation: https://codepen.io/NathanWailes/pen/KKMYNVZ
I ended up getting it working in a simple example in CodePen, which I'm going to use as a guide when trying to get it working on the actual site.
The summary of my findings with this solution is, "Vue will actually update when the nested entries of a Vuex state object are updated; you don't need to worry about it not detecting those changes. So it's OK to just keep all the data in a single big Vuex store object when you have many duplicate sibling components that need to react to each other."
Here's the CodePen: https://codepen.io/NathanWailes/pen/NWRNgNz
Screenshot
Summary of what the CodePen example does
weeklyMenu
object, which has child objects to break up the data into the different days / meals.get
andset
functions so that it can both get changes from the store and also update the store.weeklyMenu
object, and it "just works".The code
HTML
JavaScript