there
when I use Vue + Vuex in my project, I found an issue,
my code:
store:
const state = {
createInfo: {
id: 0,
// group_id: rootState.home.currentGroup,
content: '',
image_info: [],
video_info: [],
lat: '',
lng: '',
type: 1
},
list: [],
canLoad: true
}
function of mutations:
setPublishInfoImages(state, {key, value}) {
if (key === 'push') {
state.createInfo.image_info.push(value)
} else {
state.createInfo.image_info.splice(key, 1)
}
},
on page
first way:
let sourceTopic = Object.assign({}, {
image_info: [],
video_info: [],
content: '',
type: 1
}, JSON.parse(JSON.stringify(this.$store.getters['topic/signTopic'](topic))))
second way:
let sourceTopic = Object.assign({}, {
image_info: [],
video_info: [],
content: '',
type: 1
}, Object.assign({}, this.$store.getters['topic/signTopic'](topic))
I want deep copy a source Object which in state's list array from state use getter
const getters = {
/** get sign topic */
signTopic: (state) => (id) => {
return state.list.data.find((topic) => topic.id === id) || {}
}
}
yes, I got the Object from state,
but when I update the state (uploadimage, and push image-url into state),
first way, there is only one image-url in source images array forever,
second way, when I cannel editing source object, uploaded image-urls will be stored in source object
how can i resolve this issue?
Related
When I try to add an object to an array, it updates existing objects of the array and displays the error as: "Duplicate keys detected: 'test'. This may cause an update error". Can you please help me in resolving the issue.
Below is my code:
index.vue
methods: {
...mapActions({
saveItem: 'admin/saveItem'
}),
createItem() {
const saveItemFunc = this.saveItem
saveItemFunc({ "Test item", "category" })
},
}
actions.js
saveItem({ commit, dispatch, state }, payload) {
commit('addItemToBeSaved', payload)
}
mutations.js
addItemToBeSaved: (state, { name, type } ) => {
state.items.push(state.item)
state.items[state.count].name = name
state.items[state.count].type = type
state.count = state.count + 1
}
State.js
export default function() {
return {
items: [],
count: 0,
item: {
name: '',
type: ''
}
}
}
I get this error:
Uncaught Error: Module parse failed: Shorthand property assignments are valid only in destructuring patterns (74:14)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|
| dispatch('ADD_CHILDREN_TO_NODE', {
> doc = doc,
| })
| .finally(() => {
at eval (document-flow.module.js:1)
at Object../src/main/code/customers-self-data/vuex/modules/document-flow.module.js (_bundle.js?97212a2ac8be2d4b571f:8449)
at __webpack_require__ (_bundle.js?97212a2ac8be2d4b571f:20)
at eval (store.js:8)
at Module../src/main/code/customers-self-data/vuex/store.js (_bundle.js?97212a2ac8be2d4b571f:8473)
at __webpack_require__ (_bundle.js?97212a2ac8be2d4b571f:20)
at eval (index.js:3)
at Module../src/main/code/customers-self-data/index.js (_bundle.js?97212a2ac8be2d4b571f:8378)
at __webpack_require__ (_bundle.js?97212a2ac8be2d4b571f:20)
at eval (index.js:1)
This is my module:
import * as a from "../types/actions.types";
import * as g from "../types/getters.types";
import * as m from "../types/mutations.types";
import {
some imports
} from "#pn-js/core";
const documentFlow = {
namespaced: true,
state: {
documentFlowTree: null,
documentId: null,
childrens: null,
},
getters: {
[g.GET_DOCUMENT_FLOW_TREE](state) {
return state.documentFlowTree;
},
[g.GET_DOCUMENT_ID](state) {
return state.documentId;
},
[g.GET_CHILDRENS](state) {
return state.childrens;
},
},
mutations: {
[m.SET_DOCUMENT_FLOW_TREE](state, payload) {
state.documentFlowTree = payload;
},
[m.SET_DOCUMENT_ID](state, payload) {
state.documentId = payload.id;
},
[m.SET_CHILDRENS](state, payload) {
state.childrens = payload.childrens;
},
},
actions: {
[a.LOAD_DOCUMENT_FLOW_TREE]({ dispatch,commit, state }) {
var _documentTypeNamesMap = {
ORDER: order,
DELIVERY: delivery,
INVOICE: invoice,
};
let params = new ParamsBuilder(url)
.param(ParamsBuilder.UrlReplacements.ID, state.documentId)
.build();
let res = [];
return Http.get({ params }).then((response) => {
//Compongo il nodo root
let firstNodeText =
_documentTypeNamesMap.ORDER + ":\t" + state.documentId;
let doc = [];
if (response.result) {
Object.keys(response.result).forEach((key) => {
doc.push(response.result[key].sequentDocuments.filter((d) => {
return d.docType.category === "DELIVERY";
}));
});
}
dispatch('ADD_CHILDREN_TO_NODE', { ====> This generates the error
doc = doc,
})
.finally(() => {
if (response.result) {
res.push({
text: firstNodeText,
state: { expanded: true },
children: state.childrens,
});
} else {
res = [
{
text: firstNodeText,
state: { expanded: true },
children: [{ text: noDataFound }],
},
];
}
commit(m.SET_DOCUMENT_FLOW_TREE, res);
});
});
},
[a.UPDATE_DOCUMENT_ID]({ commit }, payload) {
commit(m.SET_DOCUMENT_ID, payload);
},
[a.ADD_CHILDREN_TO_NODE]({commit},payload) {
let doc = payload.doc;
let childrens = [];
let matRegNodeText = "";
let i = 0;
Object.keys(doc).forEach((key) =>{
let docId = doc[key][0].docNum;
let deliveryParams = new ParamsBuilder(url)
.param(ParamsBuilder.UrlReplacements.NUM, docId)
.build();
Http.get({
params: deliveryParams,
}).then((deliveryResponse) => {
if (deliveryResponse.result) {
matRegNodeText =
(doc[key][0].docType.category === "DELIVERY" ? goodsIssue : null) +
"\t\t\t" +
deliveryResponse.result.goodsReceiptNum +
"\t\t\t" +
deliveryResponse.result.actualMovDate;
}
let child = {
text: Strings.fsa.cdp.df.position + "\t" + response.result[i].docPos.posNum,
state: { expanded: true },
children: [{ text: matRegNodeText }],
};
childrens.push(child);
i++;
});
});
commit(m.SET_CHILDRENS,childrens);
}
},
};
export default documentFlow;
My question: is it possible to call an action from an action on the same module?
My problem is that before I didn't use the action to build the node (in the action loop my object doc to retrieve the data) but before being able to push the array childrens into property children of the object res, it was called asynchronous the commit, I thought about putting that piece of code inside a promise and then building the tree node but the result was the same.
Am building a simple Vue project to get to grips with simple store (vuex) and then using PouchDB. I am hitting an odd error and am struggling to see
where to go next
const PouchDB = require('pouchdb')
import EntryForm from '#/components/EntryForm.vue'
import DisplayText from '#/components/DisplayText.vue'
export default {
name: 'entryform',
components: {
EntryForm,
DisplayText
},
data() {
return {
db: [],
remote: [],
stepfwd: [],
stepback: [],
newMutation: true
}
},
created() {
//window.db or this.db does it matter ?
this.db = new PouchDB('icecream')
this.remote = 'http://localhost:5984/icecream'
this.db.sync(this.remote, { live: true, retry: true })
//any mutations are put into the stepfwd array and put into the db array
this.$store.subscribe(mutation => {
if (mutation.type !== CLEAR_STATE) {
this.stepfwd.push(mutation)
this.db.push(mutation)
}
if (this.newMutation) {
this.stepback = []
}
})
}
Any helpers much appreciated.
all the branch code can be found here for review
https://gitlab.adamprocter.co.uk/adamprocter/simplevuestore/tree/pouchdb
In Vuex I'm trying to pass a state's object (a string in this case), into another state's object, but it is returning undefined.
state: {
notifications: [
{ key: "success",
notification: "Awesome " + this.theName + "! Success.",
redirectPath: "/home"
},
{ key: "error",
notification: "Oh no " + this.theName + "... Error.",
redirectPath: "/error"
}
],
theName: 'Ricky Bobby' // this would normally come from a mutation method - see below
}
The example above the theName is hard-coded just for testing but its value is coming from a mutation method. I know it is coming in into the store's state, because I am able to console log it. But the string interpolation inside the notifications object is not working. How can I pass that incoming value into the notifications.notification value?
I don't know if this helps, but here is the mutation example:
mutations: {
loginSuccess(state, payload){
state.theName = payload.uName;
}
}
There're two issues with your code. Firstly, this doesn't work the way you're trying to make it to do. In your question this inside each notification doesn't refer to the state or any other part of your code. Its value is the global window object or undefined, depends on whether you are in strict mode:
const object = {
propName: this,
};
console.log(object.propName);
Secondly, you code is asynchronous, so theName would change from time to time, but you never actually redefine message strings in your notifications. And they won't be 'recalculated' by itself:
let surname = 'Whyte';
const object = {
fullName: 'Pepe ' + surname,
};
console.log(object.fullName);
setTimeout(() => {
surname = 'White';
console.log(object.fullName);
console.log('the value of \'surname\' variable is ' + surname + ' though.');
}, 2000);
What you can do in your case is to define notification as a function:
notification(name) { return "Awesome " + name + "! Success."}
Then write a getter for notifications and pass a name to the function.
Or as an alternative you can refer to the object itself inside the function. Like this:
let surname = 'Whyte';
const object = {
person: {
firstName: 'Pepe ',
fullName: () => {
return object.person.firstName + ' ' + surname;
},
}
};
console.log(object.person.fullName());
setTimeout(() => {
object.person.firstName = 'Keke';
console.log(object.person.fullName());
}, 1000);
UPD: I've made another example for you. It's hard to tell how exactly you are going to call this notifications, but here are two options you can access them the way you want (jsfiddle):
const store = new Vuex.Store({
state: {
theName: 'Ricky Bobby',
// accessing `theName` prop inside state (probably won't be possible in the real project or very inconvinient due to modularity)
successNotificationInState: () => `Awesome ${store.state.theName}! Success.`,
},
// accessing the same prop with getter
getters: {
successNotification: (state) => `Awesome ${state.theName}! Success.`,
},
mutations: {
loginSuccess(state, payload) {
state.theName = payload.uName;
},
},
actions: { // let's emulate a login
login({
commit
}) {
return new Promise(fullfil => {
setTimeout(function() {
console.log('logging in')
const response = {
uName: 'Keke',
email: 'keke#gmail.com',
}
fullfil(response);
commit('loginSuccess', response);
}, 2000);
});
},
},
});
const app = new Vue({
el: "#app",
store,
data: {
msgGetter: '',
msgState: '',
},
computed: {},
methods: {
login() {
this.$store.dispatch('login').then((response) => {
console.log(response);
console.log(this.$store);
this.msgGetter = this.$store.getters.successNotification;
this.msgState = this.$store.state.successNotificationInState();
});
},
},
mounted() {
this.login();
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.0.1/vuex.js"></script>
<script src="https://unpkg.com/vue"></script>
<div id="app">
<p>Message from state: {{msgState}}</p>
<p>Message from getter: {{msgGetter}}</p>
</div>
I am using vue-head in website because of I have to pass the name of the program to the html head, and the inf. it is coming from an API, so I make the request but every time I try to pass the name it send me error this the code:
export default {
data: () => ({
errors: [],
programs: [],
firstVideo: {},
vidProgram: {}
}),
},
created() {
//do something after creating vue instance
this.api = new ApiCanal({})
this.getProgram()
},
methods: {
getProgram() {
this.api.http.get(`videos/program/${this.programSlug}`)
.then(response => {
this.programs = response.data
this.firstVideo = response.data[0]
this.vidProgram = response.data[0]['program']
})
.catch(error => {
this.errors = error
});
}
},
head: {
//this is the inf. for the head
title: {
inner: this.programs.name,
separator: '-',
complement: this.programs.info
}
}
}
I will really appreciate if you can help me with this issue
If you want to use properties of your Vue object/component in the title there, you need to make it a function, as currently this refers to the object creating your Vue component (probably the global window object).
head: {
title: function() {
return {
inner: this.programs.name,
separator: '-',
complement: this.programs.info
};
}
}