I have a series of components that go several levels deep. Each component has its own piece of data that it loads over AJAX and uses to render each instance of child components. The days parent template for example:
<template>
<accordion :one-at-atime="true" type="info">
<panel :is-open="index === 0" type="primary" :header="'Day ' + day.day" v-for="(day, index) in days" :key="day.id">
<br/>
<div class="panel panel-success">
<div class="panel-heading">
<h3 class="panel-title">Cycles</h3>
</div>
<div class="panel-body">
<cycles
:day="day"
>
</cycles>
</div>
</div>
</panel>
</accordion>
</template>
The cycles child template for example:
<template>
<accordion :one-at-atime="true" type="info">
<panel :is-open="index === 0" type="primary" :header="'Week ' + cycle.week + ': ' + cycle.name" v-for="(cycle, index) in cycles" :key="cycle.id">
<form v-on:submit.prevent="update">
....misc input fields here...
<button type="button" class="btn btn-warning" v-if="cycle.id" v-on:click="destroy">Delete</button>
</form>
</panel>
</accordion>
</template>
<script>
export default {
props: [
'day'
],
data() {
return {
cycles: []
}
},
beforeMount: function () {
var self = this;
if (this.cycles.length === 0) {
axios.get('/plans/days/' + this.day.id + '/cycles')
.then(function (response) {
self.cycles = response.data;
})
.catch(function (error) {
console.log(error);
});
}
},
methods: {
destroy: function (event) {
var self = this;
axios.delete('/plans/cycles/' + event.target.elements.id.value)
.then(function (response) {
self.cycles.filter(function (model) {
return model.id !== response.data.model.id;
});
})
.catch(function (error) {
console.log(error);
});
}
}
}
</script>
Each cycles component then renders another component in a v-for loop, which renders another type of component, and so on and so forth. What is created is a tree like structure of components.
When I need to send a generic request to the server that then updates the data in the component it is called from, I don't want to have to duplicate that request method in every component. I'd rather just have one instance of the method on the root Vue instance.
For example, this would be preferred:
const app = new Vue({
el: '#app',
store,
created: function () {
this.$on('destroy', function (event, type, model, model_id, parent_id) {
this.destroy(event, type, model, model_id, parent_id);
})
},
methods: {
destroy: function (event, type, model, model_id, parent_id) {
var self = this;
axios.delete('/plans/' + type + '/' + model_id)
.then(function (response) {
model = model.filter(function (model) {
return model.id !== response.data.model.id;
});
this.$emit('modified-' + type + '-' + parent_id, model);
})
.catch(function (error) {
console.log(error);
});
}
}
});
Then in the cycles.vue delete button call this on click:
<button type="button" class="btn btn-warning" v-if="cycle.id" v-on:click="$root.$emit('destroy', event, 'cycles', cycles, cycle.id, day.id)">Delete</button>
And add this to cycles.vue events:
created: function () {
this.$on('modified-cycles-' + this.day.id, function (cycles) {
this.cycles = cycles;
})
},
However, that doesn't work because the child element never gets the emitted 'modified-' + type + '-' + parent_id event from root.
I also tried this.$children.$emit('modified-' + type + '-' + parent_id, model); but that didn't work either.
What's the Vue 2.5.16 way to do this? And is there a better design pattern than I am currently using?
thisin the payload of theemit? - Roy J