Reputation: 5799
I face the following problem trying to migrate from Vue 1.0.27 to Vue 2.0.1.
EDIT added working JSFidle
I have built a very simple app that takes a list of tasks (from the model) and displays them in an un-ordered list, as well as the number of tasks that are not flagged as completed (i.e. remaining tasks). The code for the ViewModel and the Model is shown below:
/*************
* ViewModel *
* ***********/
var vm = new Vue({
el: '#my-app',
data: data
});
/*************
* Model *
* ***********/
var data = {
my_tasks: [
{body: "Go to the doctor", completed: false},
{body: "Go to the bank", completed: false},
{body: "Go to the zoo", completed: false}
],
};
In order to display the list of tasks I use a <task-list>
custom component. The component:
tasks
property via propsremaining
that calculates the number of the tasks that are not completedtoggleCompletedStatus
and inProgress
The code for the custom component is shown below
/*****************
* Component *
* ***************/
Vue.component('task-list', {
template: '#task-list-template',
props: ['tasks'],
computed: {
remaining: function () {
return this.tasks.filter(
this.inProgress
).length;
}
},
methods: {
/**
* Toggle the completed status of a task
* @param item
*/
toggleCompletedStatus: function (item) {
return item.completed = !item.completed;
},
/**
* Returns true when task is in progress (not completed)
* @param item
*/
inProgress: function (item) {
return !item.completed;
}
},
});
<template id="task-list-template">
<div>
<h3>My tasks list ( {{ remaining }} )</h3>
<ul>
<li v-for="task in tasks" @click="toggleCompletedStatus(task)">
{{ task.body }}
</li>
</ul>
</div>
</template>
Finally in my view I use v-bind
directive to bind the component's tasks property with the data.
/************
* View * <-- works fine with both Vue 1.X and 2.x
* **********/
div id="my-app">
<task-list :tasks="my_tasks"></task-list>
</div>
If I try to pass the task list inline, the computed property remaining
is NOT updated when the user clicks on a task. (i.e when the task.completed property changes)
/************
* View * <-- works in Vue 1.x, NOT working with Vue 2.x
* **********/
div id="my-app">
<task-list :tasks="[{body: "Go to the doctor", completed: false}, {body: "Go to the bank", completed: false}, {body: "Go to the dentist", completed: false}]"></task-list>
</div>
The same problem exists if I try to pass data from the server. The example below is using Laravel 5.3 in the backend:
/************
* View * <-- works in Vue 1.x, NOT working with Vue 2.x
* **********/
div id="my-app">
<task-list :tasks="{{$tasks}}"></task-list> <!-- {{$tasks}} are the json encoded data from the server -->
</div>
Any help appreciated
Upvotes: 2
Views: 947
Reputation: 1703
It's a normal behaviour, I'll let you check the migration guide about the props: http://vuejs.org/guide/migration.html#Prop-Mutation-deprecated4
Here your example updated to work with Vue 2.0:
/*****************
* Component *
* ***************/
Vue.component('task-list', {
template: '#task-list-template',
props: ['tasks-data'],
data: function () {
return { tasks: [] };
},
computed: {
remaining: function () {
return this.tasks.filter(
this.inProgress
).length;
}
},
created: function () {
this.tasks = this.tasksData; // Set default properties
},
methods: {
/**
* Toggle the completed status of a task
* @param item
*/
toggleCompletedStatus: function (item) {
return item.completed = !item.completed;
},
/**
* Returns true when task is in progress (not completed)
* @param item
*/
inProgress: function (item) {
return !item.completed;
}
}
});
/*************
* ViewModel *
* ***********/
new Vue({
el: '#my-app'
});
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<div id="my-app">
<task-list :tasks-data="[{body: 'Hello all', completed: false},{body: 'Goodbye all', completed: false}]"></task-list>
</div>
<!-- Template for custom component -->
<template id="task-list-template">
<div>
<h3>Remaining task {{ remaining }}</h3>
<ul>
<li v-for="task in tasks" @click="toggleCompletedStatus(task)">
{{ task.body }}
</li>
</ul>
</div>
</template>
As you can see, I set the tasks in data in the created hook so Vue can listen to the changes and update the template.
Upvotes: 2