How can I access the count property inside the method when I use vuex? Please see my code below.
Code screenshot:
Error
[Vue warn]: Computed property "count" was assigned to but it has no setter.
You can access computed properties just like you access your data properties in a component. But since you are mapping the state in this case. You should not increment or alter its value directly inside the component. Instead, you should dispatch an action with the updated/incremented value and use mutation to mutate the value of the count property in the state object.
More detail https://vuex.vuejs.org/guide/mutations.html#commit-with-payload
The mapState you wrote is inside a computed block. By default computed values are read-only, but you can make them read/write by giving them a setter (ie a function to call when modifying the computed value):
computed: {
count: {
get() { return this.$store.state.count; },
set(newValue) {
// This will most likely throw a warning, as it is bad practise.
this.$store.state.count = newValue;
}
}
}
https://v2.vuejs.org/v2/guide/computed.html#Computed-Setter
Related
Following:
Passing data from Props to data in vue.js
I have:
https://codesandbox.io/s/u3mr8
which gives the following warning:
(the idea is to avoid mutating props). What side effects can happen in a straightforward copy object operation? I don't get it. The function just saves props into data.
Drag and drop fails with:
Do you really need a setter for a computed prop?
Looking at:
Computed property was assigned to but it has no setter - a toggle component
I've come up with:
https://codesandbox.io/s/39sgo
which is great, no warnings, no errors; it's just that the component no longer renders (fails to get data saved from prop).
Any ideas/suggestions/help/advice would be really, really awesome.
I think the error is thrown because it is not allowed to set within the getter the value from which the computed property is generated. It is a logical loop to modify the initial value while getting the computed results. Instead you can just return the prop value on initial call to getter (if the local value is not yet set).
get() {
if (!this.itemSectionPropsLocal["itemSectionCategory"]) {
return Object.assign({}, this.itemSectionProps)[
"itemSectionCategory"
];
}
return this.itemSectionPropsLocal["itemSectionCategory"];
},
set(value) {
this.itemSectionPropsLocal = value;
},
Also, in setter, you should assign the received value not the prop. If you want to update the local values if the prop value changes after mount you should use a watcher.
watch: {
itemSectionProps: {
deep: true,
handler(val){
this.getPropsLocal = Object.assign({}, val["itemSectionCategory"])
}
}
}
I have a getter called viewItems in my Vuex store, returning an array.
I can access it from my Cypress test with:
Cypress.Commands.add("getStore", () => {
return cy.window().its("app.$store");
});
cy.getStore().its("getters.viewItems.length").should("equal", 13);
It works, but I get an error on the console when running Cypress:
[Vue warn]: Property or method "nodeType" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties
Is there a better way to access getters, or is it something else?
I'm trying to create a computed property that I want to be reevaluated whenever any value in a deeply nested object changes. I understand that myObj.[] can be used to reevaluate computed properties whenever any object in an array changes, but I want this to be recursive.
eg I have
// should recalculate whenever myObj.x.y.z changes, or when myObj.a.b.c changes
computed('myObj', function() {
// ...
})
I don't know in advance exactly how the object is structured, and it may be arbitrarily deep.
Neither computed('myObj.[]', ...) nor computed('myObj.#each', ...) seem to work for this.
Any ideas how to do this?
In Ember it is possible to define computed properties at runtime
import { defineProperty, computed } from '#ember/object';
// define a computed property
defineProperty(myObj, 'nameOfComputed', computed('firstName', 'lastName', function() {
return this.firstName+' '+this.lastName;
}));
So taking that a step further, you could dynamically create whatever computed property key string you want at runtime (this could be in component's init() or something):
// define a computed property
let object = {
foo: 'foo',
bar: 'bar'
}
this.set('myObj', object);
let keys = Object.keys(object).map((key) => {
return `myObj.${key}`
});
defineProperty(this, 'someComputed', computed.apply(this, [...keys, function() {
// do something here
}]));
It's up to you to figure out how to properly recursively traverse your objects for all the dependent keys without creating cycles or accessing prototype keys you don't want...or to consider whether or not this is even that good of an idea. Alternatively, you could try to handle the setting of these properties in such a way that retriggers a computation (which would be more in line with DDAU). I can only speculate from what you've provided what works but it's certainly possible to do what you want. See this twiddle in action
could you try anyone computed/obeserver like below..
But try to prefer the computed.
import { observer } from '#ember/object';
import EmberObject, { computed } from '#ember/object';
partOfNameChanged1: observer('myObj','myObj.[]','myObj.#each', function() {
return 'myObj is changed by obeserver';
})
partOfNameChanged2: computed ('myObj','myObj.[]','myObj.#each', function() {
return 'myObj is changed by computed';
})
then in your handlebar/template file
{{log 'partOfNameChanged1 is occured' partOfNameChanged1}}
{{log 'partOfNameChanged2 is occured' partOfNameChanged2}}
Then you have to associate/assign this partOfNameChanged1 / partOfNameChanged2 to some where in the handlebar or to any other variable in your .js file.
As long as you have not assigned this computed/observer property partOfNameChanged1 /partOfNameChanged2 to somewhere, then you will not get it's value.
I'm trying to bind the text in a b-dropdown element to a value in the store. I tried binding to a computed property since the value in the store can change and the b-dropdown's text should change dynamically to reflect this change. I want to store the value in the store rather than as a data object because the value has to persist outside of the component where the b-dropdown exists.
Here's the b-dropdown element:
<b-dropdown v-bind:text="selectedSearchType" variant="outline-secondary">
...
</b-dropdown>
And the computed property
computed: {
selectedSearchType: function() {
return store.getters.getSelectedSearchType
}
},
The getter
getSelectedSearchType: state => {
return state.selectedSearchType
}
The state
state: {
selectedSearchType: "Item",
.....
}
I'm getting the following error:
[Vue warn]: Invalid prop: type check failed for prop "text". Expected String, got Function.
Instead if I do
<b-dropdown v-bind:text="selectedSearchType()" variant="outline-secondary">
I get
[Vue warn]: Error in render: "TypeError: Cannot read property 'selectedSearchType' of undefined"
How do I fix this to make the b-dropdown's text bind to the selectedSearchType ins the store?
Your best bet on binding to the store is to create a computed getter/setter and then use v-model in your input. That would look something like the following, you will have to adjust a little depending on your values.
This also assumes that b-dropdown is going to emit an input when the value changes.
<b-dropdown v-model="selectedSearchType" variant="outline-secondary">
computed: {
selectedSearchType: {
get() {
return //value from store
},
set(val) {
// set the value in the store
}
}
}
Is it even possible?
I know I can do it like this:
computed: {
...mapGetters({
xyz: 'xyz'
}),
but I was wondering if I can do it using inherited mapGetters, i.e. in created hook:
created () {
this.$options.computed = Object.assign(this.$options.computed, {...this.dependencies.mapGetters(this.stores)});
console.log(this.$options.computed); // returns mapped getters
},
Console output returns mapped getters, but it doesn't seem to work, in Vue DevTools those Vuex bindings are undefined.
No. You can't. There's no way around.
Also,
The $options is read only.