I have this action in my store:
updateTicketCustomer ({commit, state}, selectedCustomer) {
axios.patch('/tickets/' + state.currentTicket.id, {
customer_id: selectedCustomer.id
})
.then((response) => {
commit('UPDATE_TICKET_CUSTOMER', selectedCustomer)
});
}
If I wanted to assign null to customer_id, what is the right way to do it? Given that in template I assign null to selectedCustomer, how do I build the conditional to assign null or selectedCustomer.id?
Something like
if (selectedCustomer !== null) {
customer_id: selectedCustomer.id
} else {
customer_id: null
}
You could use the conditional operator:
updateTicketCustomer ({commit, state}, selectedCustomer) {
axios.patch('/tickets/' + state.currentTicket.id, {
customer_id: selectedCustomer !== null ? selectedCustomer.id : null
})
.then((response) => {
commit('UPDATE_TICKET_CUSTOMER', selectedCustomer)
});
}
The syntax is, basically:
<condition> ? <returned if true> : <returned if false>
Related
I have this watcher, where I am changing value of the activeTable - this value is stored inside Pinia store:
const { tables, freeTables, usedTables, activeTable, selectedTable } = storeToRefs(useTableStore())
watch([tables, urlPath], (newValue, oldValue) =>
{
if(urlPath.value[0] === 'tables' && Number.isInteger(+urlPath.value[1]))
{
let tableIndex = tables.value.findIndex(table =>
+table.id === +urlPath.value[1]
)
if(tableIndex > -1)
{
let table = tables.value[tableIndex]
if(+table.userID === +userData.id || +table.waiterID === +userData.id)
{
mineButton.click();
}
else
{
document.getElementById('other-tables').click()
}
activeTable.value = table
}
}
})
In another component I am watching activeTable
const {showTableOrder, activeTable, selectedTable} = storeToRefs(useTableStore())
watch(
() => activeTable.value,
async (newValue, oldValue) => {
console.log(newValue);
console.log(oldValue);
},
{ deep: true }
)
If you refresh the page, the first watcher is working as expected, and activeTable is set properly, but the second watcher is never activated. What am I doing wrong here?
I have following store defined:
state: () => ({
infoPackCreationData: null,
infoPackCreationTab: null,
}),
getters: {
infoPackImage(state: any) {
return state.infoPackCreationTab && state.infoPackCreationTab.infopackContents
? state.infoPackCreationTab.infopackContents.filter((item: any) => item.type === "IMAGE")
: [];
}
},
mutations: {
setImageData(state:any, infopackImageData: any) {
state.infoPackCreationTab.infopackContents.filter((item: any) => {if(item.type === "IMAGE")
item = infopackImageData
console.log(item , 'this is items');
return item})
}
},
actions: {
setImageData(context: any, payload: any) {
context.commit('setImageData', payload)
}
}
and in my component I am using the computed to get the imageList:
computed: {
...mapGetters("creationStore", ["infoPackImage"]),
imageList: {
get() {
return this.infoPackImage ?? [];
},
set(value) {
this.$store.dispatch('creationStore/setImageData', value);
}
}
},
The problem is I want to edit a value of the imageList by index using draggable libarary,
but imageList does not act reactive and it just move the image and not showing the other image in the previous index:
async imageChange(e) {
this.loading = true
let newIndex = e.moved.newIndex;
let prevOrder = this.imageList[newIndex - 1]?.order ?? 0
let nextOrder = this.imageList[newIndex + 1]?.order ?? 0
const changeImageOrder = new InfopackImageService();
try {
return await changeImageOrder.putImageApi(this.$route.params.infopackId,
this.$route.params.tabId,
e.moved.element.id, {
title: e.moved.element.title,
infopackAssetRef: e.moved.element.infopackAssetRef,
order: nextOrder,
previousOrder: prevOrder,
}).then((res) => {
let image = {}
let infopackAsset = e.moved.element.infopackAsset
image = {...res, infopackAsset};
Vue.set(this.imageList, newIndex , image)
this.loading = false
return this.imageList
});
} catch (e) {
console.log(e, 'this is put error for tab change')
}
},
Array.prototype.filter doesn't modify an array in-place, it returns a new array. So this mutation isn't ever changing any state:
mutations: {
setImageData(state:any, infopackImageData: any) {
state.infoPackCreationTab.infopackContents.filter((item: any) => {if(item.type === "IMAGE")
item = infopackImageData
console.log(item , 'this is items');
return item})
}
},
So, if you intend to change state.infoPackCreationTab.infopackContents, you'll need to assign the result of filter():
mutations: {
setImageData(state:any, infopackImageData: any) {
state.infoPackCreationTab.infopackContents = state.infoPackCreationTab.infopackContents.filter(...)
However, since state.infoPackCreationTab did not have an infopackContents property during initialization, it will not be reactive unless you use Vue.set() or just replace the whole infoPackCreationTab object with a new one (see: Vuex on reactive mutations):
mutations: {
setImageData(state:any, infopackImageData: any) {
state.infoPackCreationTab = {
...state.infoPackCreationTab,
infopackContents: state.infoPackCreationTab.infopackContents.filter(...)
};
I try to create a delete method in vue-tags-input in Vue Js. I am not sure how to get the index. from this tag. Usually in my delete method I use the index .
<vue-tags-input
v-model="tagName"
class="tags-input w-100 mt-0"
#before-deleting-tag="deleteCustomerName"
/>
deleteCustomerName: function () {
const id = this.editedItemId;
const id_c = 33; //right now I am not sure how to get id_c
// const deleted_user_name = this.customer_names[index].name;
this.boxOne = "";
this.$bvModal
.msgBoxConfirm("Are you sure that you want to delete this ?", {
okVariant: "danger",
okTitle: "Delete",
cancelTitle: "Cancel",
centered: true
})
.then(confirm => {
if (confirm) {
deleteApi("/customers/" + id + "/" + id_c).then(() => {
this.$nextTick(() => {
// this.$emit('deleted',deleted_user_name)
// this.customer_names.splice(index, 1); //usualy I do this, but now it doesn't now how index is
console.log('User deleted!');
});
});
}
})
.catch(error => {
console.log(error);
});
},
Here is describing http://www.vue-tags-input.com/#/api/events . before-deleting-tag return index,tag,deleteTag[func] so you need to set param in deleteCustomerName parameters scope .
deleteCustomerName: function (params) {
console.log(params.index)
....
}
A little background
Well, I was trying to use upsert command, however I keep getting errors, and I had no idea what went wrong, I already input the object that I want upsert (that is NewIssue) which is a value based on other call.
What it does
Error :(
{
"name": "SequelizeDatabaseError",
"parent": {
"fatal": false,
"errno": 1064,
"sqlState": "42000",
"code": "ER_PARSE_ERROR",
"sql": "INSERT INTO `ms_issue` VALUES () ON DUPLICATE KEY UPDATE ;"
},
"original": {
"fatal": false,
"errno": 1064,
"sqlState": "42000",
"code": "ER_PARSE_ERROR",
"sql": "INSERT INTO `ms_issue` VALUES () ON DUPLICATE KEY UPDATE ;"
},
"sql": "INSERT INTO `ms_issue` VALUES () ON DUPLICATE KEY UPDATE ;"
}
My code
Data Schema:
const Issue = sequelize.define('ms_issue', {
id_Issue: {
type: Sequelize.NUMBER,
primaryKey: true
},
id_IssueTag: {
type: Sequelize.NUMBER,
},
datetime_Issued: {
type: Sequelize.NOW
},
subject_Issue: {
type: Sequelize.STRING
},
desc_Issue: {
type: Sequelize.STRING
},
status_Issue: {
type: Sequelize.STRING
}
}, { timestamps: false, freezeTableName: true });
app.put('/issues/:id', (req, res) => {
const id_Staff = req.body.id_Staff
if (typeof id_Staff !== 'undefined' && typeof id_Staff === 'number') {
const id_Issue = parseInt(req.params.id)
if (typeof id_Issue !== 'undefined' && typeof id_Issue === 'number') {
Issue.findByPk(id_Issue)
.then(issue => {
if (issue) {
const newIssue = {
subject_Issue: req.body.subject || undefined,
desc_Issue: req.body.description || undefined,
id_IssueTag: req.body.tag || undefined
}
for (const obj in newIssue) {
if (typeof newIssue[obj] !== 'undefined') {
issue[obj] = newIssue[obj]
}
}
const NewIssue = issue
return NewIssue
} else res.status(404).send("Issue not found")
})
.then(NewIssue => {
return Issue.upsert(NewIssue)
.then(bool => {
if (bool === true) {
res.status(200).send("Issue has been updated")
res.status(200).send(NewIssue)
}
})
.catch(err => {
res.status(500).send(err)
})
})
.catch(err => {
console.log(err)
res.status(500).send("Cannot connect to database")
})
} else {
res.status(400).send("Invalid parameters: require 'id_Issue'")
}
} else {
res.status(401).send("Unauthorized access")
}
})
What I wanted
Able to insert/update on request in MariaDB. And explanation :)
The generated SQL is invalid - there are no values:
"sql": "INSERT INTO `ms_issue` VALUES () ON DUPLICATE KEY UPDATE ;"
The SQL should be valid if you specify, roughly as below:
...
Issue.upsert({
id_Issue: id_Issue,
subject_Issue: NewIssue.subject_Issue,
id_IssueTag : NewIssue.id_IssueTag,
...
I'm having the following initial structure of vuex state (in VueJS project):
state: {
level1prop: null
}
And then I'm changing it dynamically and I'm mutating it into the following structure:
state: {
level1prop: {
level2prop: {
level3prop: {
"customKey1": { /* this is some object 1 */ },
"customKey2": { /* this is some object 2 */ },
...
}
}
}
}
I will be then adding "customKeyN": { /* this is some object N */ } under the level3prop and what it's important for me is on every change to trigger a watcher, which is watching for a changes into the level1prop from the state.
Initially, in my mutation I was doing this update on the following way:
if (!state.hasOwnProperty("level1prop"))
state["level1prop"] = {};
else if (state["level1prop"] === null || state["level1prop"] === undefined)
state["level1prop"] = {};
if (!state["level1prop"].hasOwnProperty("level2prop"))
state["level1prop"]["level2prop"] = {};
else if (state["level1prop"]["level2prop"] === null || state["level1prop"]["level2prop"] === undefined)
state["level1prop"]["level2prop"] = {};
if (!state["level1prop"]["level2prop"].hasOwnProperty("level3prop"))
state["level1prop"]["level2prop"]["level3prop"] = {};
else if (state["level1prop"]["level2prop"]["level3prop"] === null || state["level1prop"]["level2prop"]["level3prop"] === undefined)
state["level1prop"]["level2prop"]["level3prop"] = {};
let payloadObj = { "customKey1": { /* this is some object 1 */ } };
state["level1prop"]["level2prop"]["level3prop"] = payloadObj;
And this is creating the structure on the way I want, but the watcher of changes is not triggered. Following the advises from here i refactor my code to a few different ways, but none of them is triggering the changes. Here is an example for latest option which I tried:
if (!state.hasOwnProperty("level1prop"))
state = Object.assign(state, { "level1prop" : {} });
else if (state["level1prop"] === null || state["level1prop"] === undefined)
state = Object.assign(state, { "level1prop" : {} });
if (!state["level1prop"].hasOwnProperty("level2prop"))
state["level1prop"] = Object.assign(state["level1prop"], { "level2prop" : {} });
else if (state["level1prop"]["level2prop"] === null || state["level1prop"]["level2prop"] === undefined)
state["level1prop"] = Object.assign(state["level1prop"], { "level2prop" : {} });
if (!state["level1prop"]["level2prop"].hasOwnProperty("level3prop"))
state["level1prop"]["level2prop"] = Object.assign(state["level1prop"]["level2prop"], { "level3prop" : {} });
else if (state["level1prop"]["level2prop"]["level3prop"] === null || state["level1prop"]["level2prop"]["level3prop"] === undefined)
state["level1prop"]["level2prop"] = Object.assign(state["level1prop"]["level2prop"], { "level3prop" : {} });
let payloadObj = { "customKey 1": { /* this is some object 1 */ } };
state["level1prop"]["level2prop"]["level3prop"] = Object.assign(state["level1prop"]["level2prop"]["level3prop"], payloadObj);
Again, this is creating the structure which I need, but watcher is still not triggered. A few other options that I tried, but were not triggering the change were:
...
state["level1prop"]["level2prop"]["level3prop"] = Object.assign({}, state["level1prop"]["level2prop"]["level3prop"], payloadObj);
...
and
...
Object.assign(state["level1prop"]["level2prop"]["level3prop"], payloadObj);
...
Is there any way to be able to trigger the watcher for a changes, in such a complex object state with so many nested levels?
As explained in the docs Object Change Detection Caveats section, you should better use the specifically designed Vue setter Vue.set to later add sub-levels to your state.
Then make sure your watcher specifies the deep option, so that it is correctly triggered when your sub-levels change.
const store = new Vuex.Store({
state: {
level1prop: null,
},
});
const state = store.state;
if (!state["level1prop"])
Vue.set(state, "level1prop", {})
if (!state["level1prop"]["level2prop"])
Vue.set(state["level1prop"], "level2prop", {})
if (!state["level1prop"]["level2prop"]["level3prop"])
Vue.set(state["level1prop"]["level2prop"], "level3prop", {})
let payloadObj = {
"customKey1": {
hello: "world",
},
};
state["level1prop"]["level2prop"]["level3prop"] = payloadObj;
setTimeout(() => {
// Change an already existing key.
state["level1prop"]["level2prop"]["level3prop"].customKey1.hello = "too";
}, 1000);
setTimeout(() => {
// To add or remove keys, make sure to use again Vue.set or Vue.delete.
state["level1prop"]["level2prop"]["level3prop"].customKey1.hello = "too";
Vue.set(state["level1prop"]["level2prop"], "level3propSibling", {
hi: "again",
});
}, 2000);
new Vue({
store: store,
watch: {
"$store.state": {
// Make sure you specify the `deep` option
deep: true,
handler() {
console.log(store.state);
},
},
},
});
<script src="https://unpkg.com/vue#2"></script>
<script src="https://unpkg.com/vuex#3"></script>