3

I'm new to Vue.js. I followed the tutorial here - https://coligo.io/dynamic-components-in-vuejs/ - on dynamic components, to give me a dynamic layout I liked, for listing products and allowing the user to switch to an edit view when they click on one of the products in the table. So, I have a 'list-products' component and an 'edit-product' component, and which one is displayed is dependent on the state of 'currentView' in the main Vue instance.

<div id="content">
  <keep-alive>
    <component :is="currentView"></component>
  </keep-alive>
</div>

The switching is all working fine when currentView is changed. What I haven't got figured out is how best to pass the product information to the edit component such that it ends up as data. I suppose the list and edit components are two sibling components of the main Vue instance, instantiated at the same time. What I need to do is when I click on a row in listing table, have the product object used for building that row made available to the edit component. I'm not sure how I do that (at least, in a proper Vue way). When the displayed component is switched (via the change in 'currentView'), is some event called for the newly (re)displayed component? If so, I could presumably call some function?

LATER: I have determined that the 'activated' hook is called when I switch to the edit-product component, which I imagine I should be able to use somehow. Now to figure that out.

1 Answer 1

1

You could use Vuex for that. Vuex is a Flux inspired state management library for Vue.

Your application basically has two different states: (1) no product selected (list-products component), and (2) any product selected (edit-product). When this is modeled with Vuex, the idea is to keep the currently selected product in a so-called store and let the components figure out their internal state depending on the store state. Here's an example:

Create a store to keep the application state:

const store = new Vuex.Store({
    state: {
        selectedProduct: null
    },
    getters: {
        selectedProduct: state => state.selectedProduct
    },
    mutations: {
        selectProduct: (state, data) => state.selectedProduct = data
    }
});

Handle product selection in your list-products component:

methods: {
    selectProduct(product) {
        this.$store.commit('selectProduct', product);
    }
}

Display the current product in edit-product:

Vue.component('edit-product', {
    store,
    template: '<div>{{selectedProduct.name}}</div>',
    computed: Vuex.mapGetters(['selectedProduct'])
});

And finally switch the components depending on the state:

new Vue({
    el: '#app',
    store,
    computed: Object.assign(Vuex.mapGetters(['selectedProduct']), {
        currentView() {
            return this.selectedProduct ? 'edit-product' : 'list-products'
        }
    })
});

Here's a basic working JSFiddle.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, that looks a good approach. At the moment I have it working, albeit in a rather unsatisfactory way, simply by setting a data property in the root instance (vm.currentProduct=product) in the list component, and then using that property for the data in the edit component. One quirk is that keep-alive gets in the way of automatic updating, so I have to do 'this.product=vm.currentProduct' in the 'activated' hook of the edit component, so every time I switch to it it updates.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.