marcus
marcus

Reputation: 730

Change Layout of Parent from Component in Vue.js

I'm trying to convert an UI element to a component, to reuse it. It's two buttons, to toggle the visibility of two DOM elements in parent app. The value is saved in local storage.

I reviewed several examples and the docu, and I was able to create a working example.

https://jsfiddle.net/d6xbts4h/2/

What I would like to get to is, to remove this.layout and toggleLayout() from the parent app and just drop in <toggle-view v-on:layout="toggleLayout" route="checklist"></toggle-view> and define that div#list-content and div#grid-content only be shown if respective component button is activated. Is that possible?

The reason why I want to get rid of additional methods in the parent app, is laziness. I want to deal with the logic in the component only.

I appreciate your time and input.

Vue.component('toggle-view', {
    props: ['route'],
    data: function () {
        return {
            // load value from local storage or set default value
            layout: Vue.ls.get(this.route + '__layout','list'), // list|grid
        }
    },
    template: `<div class="btn-group" role="group" aria-label="Basic example">
    <button id="list-toggle" v-on:click="setLayout('list', $event)" type="button" :class="[layout == 'list' ? 'active' : '' , 'btn', 'btn-secondary']"><i class="material-icons">view_list</i></button>
    <button id="grid-toggle" v-on:click="setLayout('grid', $event)" type="button" :class="[layout == 'grid' ? 'active' : '' , 'btn', 'btn-secondary']"><i class="material-icons">view_module</i></button>
    </div>`,

    mounted: function(){
        // init the layout and $emit it to parent
        this.setLayout(this.layout)
    },

    methods:{
        setLayout: function(layout,event){
            this.$emit('layout', layout);
            this.layout = layout;
            Vue.ls.set(this.route + '__layout',layout);
            console.log(layout);
        }
    },
});


var app = new Vue({
    el: '#app',
    data: {layout:null},
    methods:{
        toggleLayout: function(layout){
            this.layout = layout;
        }
    },
});

<div id="app">
        <toggle-view v-on:layout="toggleLayout" route="checklist"></toggle-view>
        <div v-if="layout === 'list'" id="list-content" class="list">
            Liste
        </div>
        <div v-if="layout === 'grid'" id="grid-content" class="grid">
            grid
        </div>
</div>

Upvotes: 0

Views: 918

Answers (1)

Patrick
Patrick

Reputation: 1620

Your child component should not be aware of the parent component. It's simply bad practice to "couple" the child component to the parent.

You should write the additional method in your parent component because this is the component which is affected by the users action.

Dispatching an event in your component (as you already do) is the correct way to handle this.

There was a possibility to do this in older Vue Versions, but it has been removed due to caveats. (https://012.vuejs.org/guide/components.html#Inheriting_Parent_Scope)

Upvotes: 1

Related Questions