admin管理员组文章数量:1278883
I'm working on an application using vuejs with vuex which uses projects, with each project having one or more jobs.
I can add, delete and update the jobs. The adding and deleting is working perfect, but the updating is not.
The state in the vuex dev tools:
My HTML:
<div class="job-pact row" v-for="(job, index) in project.jobs">
<div class="col-md-6">
<div class="form-group" :class="{'has-error' : errors.has('jobs.' + index + '.function')}">
<input type="text" name="jobs[function][]" class="form-control" v-model="job.function" @change="updateJobValue(index, 'function', $event.target.value)"/>
</div>
</div>
<div class="col-md-4">
<div class="form-group" :class="{'has-error' : errors.has('jobs.' + index + '.profiles')}">
<input type="number" name="jobs[profiles][]" class="form-control" v-model="job.profiles" @change="updateJobValue(index, 'profiles', $event.target.value)"/>
</div>
</div>
<div class="col-md-2">
<button v-if="index == 0" class="btn btn-success btn-sm" @click="addJob"><i class="fa fa-plus"></i></button>
<button v-if="index > 0" class="btn btn-danger btn-sm" @click="deleteJob(index);"><i class="fa fa-minus"></i></button>
</div>
</div>
As you can see, I have a v-for
that is showing all my jobs. When editing a value inside my jobs, I use the @change
event to update my value. And, at the bottom, I have two buttons to add and remove a job row.
My stores are divided into modules. The main store looks like this:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const state = {};
const getters = {};
const mutations = {};
const actions = {};
//Separate Module States
import jobCreator from './modules/job-creator/store';
export default new Vuex.Store({
modules: {
jobCreator: jobCreator
},
state,
actions,
mutations,
getters
});
The module store for this specific problem:
import store from './../../store'
const state = {
project: {
title: null,
description: null,
jobs: []
},
defaultJob: {
function: '',
title: '',
description: '',
profiles: 1,
location_id: '',
category_id: '',
budget: '',
},
};
const getters = {}
const mutations = {
addJob(state, job) {
state.project.jobs.push(job);
},
deleteJob(state, index) {
state.project.jobs.splice(index, 1);
},
updateJobValue(state, params) {
Object.assign(state.project.jobs[params.jobIndex], {
[params.field]: params.value
});
}
};
const actions = {
addJob: function (context) {
contextmit('addJob', state.defaultJob);
},
deleteJob: function (context, index) {
contextmit('deleteJob', index);
},
updateJobValue: function (context, params) {
contextmit('updateJobValue', params);
},
};
const module = {
state,
getters,
mutations,
actions
};
export default module;
The project state is mapped to a puted property of my vue instance:
puted: {
...mapState({
project: state => state.jobCreator.project,
}),
}
The problem is the following: In the image of the application, you can see that I entered "vin" in one of the fields, but all of the fields are updating.
So, all of the function
fields of all the jobs have been updated to my last entry, instead of only the one I want.
What am I doing wrong?
PS:
I also tried the following in my mutation function:
updateJobValue(state, params) {
var job = state.project.jobs[params.jobIndex];
job[params.field] = params.value;
Vue.set(state.project.jobs, params.jobIndex, job);
}
But it's giving me the same result.
UPDATE: As requested, I created a jsFiddle to show my problem
I'm working on an application using vuejs with vuex which uses projects, with each project having one or more jobs.
I can add, delete and update the jobs. The adding and deleting is working perfect, but the updating is not.
The state in the vuex dev tools:
My HTML:
<div class="job-pact row" v-for="(job, index) in project.jobs">
<div class="col-md-6">
<div class="form-group" :class="{'has-error' : errors.has('jobs.' + index + '.function')}">
<input type="text" name="jobs[function][]" class="form-control" v-model="job.function" @change="updateJobValue(index, 'function', $event.target.value)"/>
</div>
</div>
<div class="col-md-4">
<div class="form-group" :class="{'has-error' : errors.has('jobs.' + index + '.profiles')}">
<input type="number" name="jobs[profiles][]" class="form-control" v-model="job.profiles" @change="updateJobValue(index, 'profiles', $event.target.value)"/>
</div>
</div>
<div class="col-md-2">
<button v-if="index == 0" class="btn btn-success btn-sm" @click="addJob"><i class="fa fa-plus"></i></button>
<button v-if="index > 0" class="btn btn-danger btn-sm" @click="deleteJob(index);"><i class="fa fa-minus"></i></button>
</div>
</div>
As you can see, I have a v-for
that is showing all my jobs. When editing a value inside my jobs, I use the @change
event to update my value. And, at the bottom, I have two buttons to add and remove a job row.
My stores are divided into modules. The main store looks like this:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const state = {};
const getters = {};
const mutations = {};
const actions = {};
//Separate Module States
import jobCreator from './modules/job-creator/store';
export default new Vuex.Store({
modules: {
jobCreator: jobCreator
},
state,
actions,
mutations,
getters
});
The module store for this specific problem:
import store from './../../store'
const state = {
project: {
title: null,
description: null,
jobs: []
},
defaultJob: {
function: '',
title: '',
description: '',
profiles: 1,
location_id: '',
category_id: '',
budget: '',
},
};
const getters = {}
const mutations = {
addJob(state, job) {
state.project.jobs.push(job);
},
deleteJob(state, index) {
state.project.jobs.splice(index, 1);
},
updateJobValue(state, params) {
Object.assign(state.project.jobs[params.jobIndex], {
[params.field]: params.value
});
}
};
const actions = {
addJob: function (context) {
context.mit('addJob', state.defaultJob);
},
deleteJob: function (context, index) {
context.mit('deleteJob', index);
},
updateJobValue: function (context, params) {
context.mit('updateJobValue', params);
},
};
const module = {
state,
getters,
mutations,
actions
};
export default module;
The project state is mapped to a puted property of my vue instance:
puted: {
...mapState({
project: state => state.jobCreator.project,
}),
}
The problem is the following: In the image of the application, you can see that I entered "vin" in one of the fields, but all of the fields are updating.
So, all of the function
fields of all the jobs have been updated to my last entry, instead of only the one I want.
What am I doing wrong?
PS:
I also tried the following in my mutation function:
updateJobValue(state, params) {
var job = state.project.jobs[params.jobIndex];
job[params.field] = params.value;
Vue.set(state.project.jobs, params.jobIndex, job);
}
But it's giving me the same result.
UPDATE: As requested, I created a jsFiddle to show my problem
Share Improve this question edited Jul 3, 2017 at 14:42 thanksd 55.7k23 gold badges165 silver badges154 bronze badges asked Jul 1, 2017 at 6:40 vincentvincent 1,3234 gold badges16 silver badges31 bronze badges 2- Could you possibly turn this into a jsfiddle? Since it is a rather long question it will be much easier for people to help you out that way. – Stephan-v Commented Jul 1, 2017 at 10:19
- I added a jsfiddle explaining my problem – vincent Commented Jul 3, 2017 at 7:34
2 Answers
Reset to default 11 +25The issue is in your addJob
action:
addJob: function (context) {
context.mit('addJob', state.defaultJob);
},
You are referencing the state.defaultJob
object each time you add a new job. That means each item in the state.project.jobs
array is referencing the same object.
You should create a copy of the object when passing it to the addJob
mutation:
addJob: function (context) {
context.mit('addJob', Object.assign({}, state.defaultJob));
},
Or, just pass in a new object with the default properties each time:
addJob: function (context) {
context.mit('addJob', {
function: '',
title: '',
description: '',
profiles: 1,
location_id: '',
category_id: '',
budget: '',
});
},
Here's a working fiddle.
Here's a post explaining how variables are passed in Javascript: Javascript by reference vs. by value
I would give the following advice:
Use v-bind:value="job.function
instead of v-model="job.function"
because you want only a one way binding. This your code more predictable.
Add a v-key="job"
to your v-for="(job, index) in project.jobs"
element just to be sure that the rendering works correctly.
The first two lines should be enought, the object is still reactive.
var job = state.project.jobs[params.jobIndex];
job[params.field] = params.value;
Vue.set(state.project.jobs, params.jobIndex, job);
PS: In my fiddle the @change
did only fire when i hit enter or left the input.
本文标签: javascriptUpdating an item in an array updates them allStack Overflow
版权声明:本文标题:javascript - Updating an item in an array updates them all - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741303163a2371214.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论