I'm trying to update the selected boolean to true from my lists items array of objects when the from_id property from the items array inside of the entry object matches with the item_id of the object in lists fromData array. The selected property updates but I got this error:
Error in callback for watcher "function () { return this._data.$$state }": "Error: [vuex] do not mutate vuex store state outside mutation handlers.
store.js
entry: {
items: [
{
from_id: 5,
to_id: 1,
quantity: 100,
},
{
from_id: 11,
to_id: 3,
quantity: 119,
},
{
from_id: 7,
to_id: 3,
quantity: 59,
},
]
}
lists: {
from: [
{
item: {...},
item_id: 5,
selected: false
},
{
item: {...},
item_id: 6,
selected: false,
},
{
item: {...},
item_id: 7,
selected: false,
}
]
}
const getters = {
entry: (state) => state.entry,
lists: (state) => state.lists,
};
This what I've tried
computed: {
...mapGetters('Conversion', ['entry', 'lists']),
from: function () {
return this.lists.from.filter((item) => !item.selected);
},
},
watch: {
from: {
deep: true,
handler: function (items) {
const _entries = this.entry.items;
_entries.map((entry) => {
items
.filter((item) => item.item_id === entry.item_from_id)
.map((item) => (item.selected = !item.selected));
});
},
},
},
The error means what it says. You're mutating the state outside the store. This should happen in mutation/action.
You need to have an action/mutation that modifies the state this way:
mutations: {
toggle(state, id) {
let item = state.items.find(item => item.id === id)
item.selected = !item.selected;
}
}
And dispatch/commit it outside the store:
this.$store.dispatch('toggle', someId)
Vuex is one-way data flow store. You will not able to mutate data directly with the getters, use action/mutation instead. https://vuex.vuejs.org/#what-is-a-state-management-pattern
In your store.js
const store = createStore({
...
mutations: {
patchEntry (state, payload) {
// Your logic here => return _entries
state.entry = Object.assign({}, state.entry, _entries)
}
}
})
In your watcher:
watch: {
from: {
deep: true,
handler: function (items) {
store.commit('patchEntry', items)
});
},
},
},
Ref: https://vuex.vuejs.org/guide/mutations.html#committing-mutations-in-components
Related
How do I update the boolean property from an array of objects using the watch of Vue and Vuex? I have from_id property from the items array. If the from_id is matches with the item_id from the lists array then update the selected boolean to true.
These are my objects:
store.js
entry: {
items: [
{
from_id: 5,
to_id: 1,
quantity: 100,
},
{
from_id: 11,
to_id: 3,
quantity: 119,
},
{
from_id: 7,
to_id: 3,
quantity: 59,
},
]
}
lists: {
from: [
{
item: {...},
item_id: 5,
selected: false
},
{
item: {...},
item_id: 6,
selected: false,
},
{
item: {...},
item_id: 7,
selected: false,
}
]
}
const getters = {
entry: (state) => state.entry,
lists: (state) => state.lists,
};
These what I've tried but it returns all the items and not updating the selected boolean to true
computed: {
...mapGetters('Conversion', ['entry', 'lists']),
},
watch: {
'lists.from': {
deep: true,
handler: function (items) {
const _itemsEntry = this.entry.items;
let result;
_itemsEntry.map((entry) => {
result = items.filter((item) =>
item.item_id === entry.from_id
? { ...item, selected: true }
: items
);
});
console.log(result);
},
},
},
I am trying to get data from server using vue and apexcharts, but even after I called data with axios, it gives me undefined..
What have I missed?
template
<apexchart
ref="chart1"
width="100%"
:options="chartOptions" :series="series">
</apexchart>
data from url
{
"pageviews": 1313,
"new_users": 1014
}
script
export default {
data: function () {
return {
series: [],
chartOptions: {
chart: {
type: 'donut',
},
colors: ['#01cd49', '#007568'],
labels: ['new', 're'],
}
},
created: function () {
this.getByVisitor()
},
methods: {
getByVisitor() {
const url = 'url';
axios
.get(url)
.then(response => {
this.$refs.chart1.updateSeries([{
name: 'Sales',
data: response.data
}])
})
.catch(error => (this.byVisitor = error.data));
console.log(`---------------this.$refs.chart1`, this.$refs.chart1);
},
}
See Updating Vue Chart Data
There's no need to directly call the updateSeries() method on the chart component since it is able to react to changes in series. All you have to do is update your series data property
export default {
data: () => ({
series: [], // 👈 start with an empty array here
byVisitor: null, // 👈 you seem to have missed this one for your error data
chartOptions: {
chart: {
type: 'donut',
},
colors: ['#01cd49', '#007568'],
labels: ['new', 're'],
}
}),
created: function() {
this.getByVisitor()
},
methods: {
async getByVisitor() {
const url = 'url';
try {
const { data } = await axios.get(url)
// now update "series"
this.series = [{
name: "Sales",
data
}]
} catch (error) {
this.byVisitor = error.data
}
},
}
}
I am trying to access nested property of store state data but it is undefined when I try to access. I have following data
const state = {
entity: {
initial: {valid: false},
general: {valid: false},
buildFiles: {valid: false},
license: {valid: false},
author: {valid: false},
}
};
const getters = {
ENTITY: (state: any): Submission => {
return state.entity; // Works fine
},
INITIAL: (state) => {
console.log(state.entity); // Prints observable with entity and properties
console.log(state.entity.initial); // Prints undefined
return state.entity.initial;
},
};
All I am trying to do is use getters from the component. Is there any way I can access property intitial?
I think you need return state as a function. And your getters needed some a little changes: Try some thing like this:
const state = () => ({
entity: {
initial: { valid: false },
general: { valid: false },
buildFiles: { valid: false },
license: { valid: false },
author: { valid: false },
},
})
const getters = {
ENTITY: (state) => (submission) => {
return state.entity // Works fine
},
INITIAL: (state) => {
console.log(state.entity) // Prints observable with entity and properties
console.log(state.entity.initial) // Prints undefined
return state.entity.initial
},
}
I have medications object as follow:
medications: [
{
'name': 'abc',
'id': naks23kn,
'resident': //this is resident id, resident is another object
.........
},
{.......},.....
]
I wanted to add another field residentName on this object list or is there any way so that I can display residentName in the v-data-table ?:
medications: [
{
'name': 'abc',
'id': naks23kn,
'resident': //this is resident id, resident is another object
'residentName': 'ad' //set this new field
.........
},
{.......},.....
]
I am using `v-data-table> as :
<v-data-table
:headers="headers"
:items="medications"
:items-per-page="20"
:search="search"
class="elevation-23"
>
Now I want to add an residentName field based on the resident field. For this I did the following:
export default {
data() {
return {
medications: [],
}
},
computed: {
...mapGetters([
'allMedications', //this is used to get all medication from medication store
'getResidentsById',
]),
},
created() {
this.get_resident_list(),
this.get_registered_medication_list();
},
methods: {
...mapActions([
'get_registered_medication_list', //this is used to call API and set state for medication
'get_resident_list', //this is used to callAPI and set state for resident
]),
getResidentName(id) {
const resident = this.getResidentsById(id)
return resident && resident.fullName
},
},
watch: {
allMedications: {
handler: function () {
const medicationArray = this.allMedications;
console.log("Created this");
this.medications = medicationArray.map(medication => ({
...medication,
residentName: this.getResidentName(medication.resident)
})
);
},
immediate: true
},
}
}
This is in resident.js getter module
getResidentsById: (state) => (id) => {
return state.residents.find(resident => resident.id === id)
}
This is setting residentName only when the component is created but if I reload/refresh page then residentName = undefined is set.
I have medications object as follow:
medications: [
{
'name': 'abc',
'id': naks23kn,
'resident': //this is resident id, resident is another object
.........
},
{.......},.....
]
I wanted to add another field residentName on this object list or is there any way so that I can display 'residentName' in the v-data-table ?:
medications: [
{
'name': 'abc',
'id': naks23kn,
'resident': //this is resident id, resident is another object
'residentName': 'ad' //set this new field
.........
},
{.......},.....
]
I am using `v-data-table> as :
<v-data-table
:headers="headers"
:items="medications"
:items-per-page="20"
:search="search"
class="elevation-23"
>
Now I want to add an residentName field based on the resident field. For this I did the following:
export default {
data() {
return {
medications: [],
}
},
computed: {
...mapGetters([
'allMedications', //this is used to get all medication from medication store
'getResidentsById',
]),
},
created() {
this.get_resident_list(),
this.get_registered_medication_list();
},
methods: {
...mapActions([
'get_registered_medication_list', //this is used to call API and set state for medication
'get_resident_list', //this is used to callAPI and set state for resident
]),
getResidentName(id) {
const resident = this.getResidentsById(id)
return resident && resident.fullName
},
},
watch: {
allMedications: {
handler: function () {
const medicationArray = this.allMedications;
console.log("Created this");
this.medications = medicationArray.map(medication => ({
...medication,
residentName: this.getResidentName(medication.resident)
})
);
},
immediate: true
},
}
}
In header
headers: [
{ text: 'Medication Name', value: 'name' },
{ text: 'Resident', value: 'residentName' },
]
This is in resident.js getter module
getResidentsById: (state) => (id) => {
return state.residents.find(resident => resident.id === id)
}
Edit: This is working, i.e I am getting residentName when the page is created but if I refresh the page then I get residentName=undefined
You can use map to add new prop to your each item in array
let medications = [{
name: 'abc',
id: 'naks23kn',
resident: 1
}]
medications.map(item => item.residentName = "Your Resident Name")
console.log(medications)
This should work
watch: {
allMedications: {
handler: function() {
const medicationArray = this.allMedications;
console.log("Created this");
this.medications = medicationArray.map(medication => medication.residentName = this.getResidentName(medication.resident)));
},
immediate: true
},
}