Using Vuex Getter as prop value of Quasar component - vue.js

I'm trying to set the label of a <q-btn-dropdown> with a value coming from a Vuex getter.
<q-btn-dropdown
color = "primary"
label = {{getMe}}
unelevated>
</q-btn-dropdown>
This prints: {{getMe}} as label of the component.
The getter inside a simple <h1> tag prints the expected value.

Related

Vue 2. How get child value throuth v-model binding

I'm using v-model in custom component, but when I try to get the data(value props) of the child component in the parent component, then I get the old value, although the data in the parent has changed. If I get the data of the child component through setTimeout, then I get the data I need. How do I synchronize the v-model #input event and the data I receive from the child element in the parent?
This is the logic: there are AppForm(parent) component and AppSelect(child) component. I'm binding v-model on AddSelect, and I follow the changes through watch() { v-model-data }. Then v-model data has changed I call AppForm.data() method, which iterates through the list of children and gets the value prop of AppSelect component, but this value is old.
Short example:
https://codesandbox.io/s/serene-wildflower-5seqx?file=/src/App.vue
You're trying to get the child component's prop inside a watcher watching the data property that the prop is bounded to. Of course, the watcher triggers first, then the data is passed onto the child component and the prop is updated. Its not a good design if you are relying on the order that Vue events and functions are fired, but if you must, you can use vm.$nextTick() function to get values after everything is synced.
watch: {
selectData(newV, oldV) {
alert("Select data from parent component: " + newV);
this.$refs.form.data();
this.$nextTick(() => {
alert("Show select data after 2sec");
this.$refs.form.data();
}, 2000);
},
},
Although, I'd suggest you shift the watcher inside the child component and access the data prop there.

Changing value of outer variable used in props after emitted listener from component disables v-model listener effects in Vue.js

Considering following HTML code:
<div id="app">
<comp :is_checked="is_checked" v-on:ch="function(x){is_checked_2=x}"></comp>
<p>{{ is_checked_2 }}</p>
</div>
<script src="app.js"></script>
and app.js:
var tm = `<div>
<input type="checkbox" v-model="is_checked"
v-on:change="$emit('ch',is_checked)"
>{{ is_checked }}
</div>`
Vue.component('comp', {
template: tm,
props: ["is_checked"]
})
new Vue({
el: "#app",
data: function() {
return {
is_checked: null,
is_checked_2: null
};
}
});
If we replace is_checked_2=x by console.log(x) in v-on:ch="function(x){...}, everything works correct and v-model is changing is_checked when input checkbox value changes.
Also if we don't send the value of variable by props and define it locally in component, everything works correct.
It seems that changing the parent Vue's object variable is
regenerating the whole HTML of component where the value of variable
is sent by props and the variable is reset there immediately after
firing the event inside template. It is causing that functions
triggered by events don't change component's variables.
Is it a bug in Vue.js?
To make it more clear, the behavior is following: changing whatever Vue parent value that is not bound and however related to the component (no props, no slots) results at resetting all values in the component that are bound by props. Following only occurs if we reactivelly write to parent/main HTML using modified parent variable, we can achieve that by placing {{ .... }} there. This seems to be the bug.
Example: Vue has variables a and b. We place {{ a }} to the main code. The value of variable b is sent by props to component and matched to variable c. With the time we are changing that value of variable c inside the component. In one moment we decide to change value of a and it results by "forgetting" current state of c and it is reset to initial state by invoked props.
To summarize: the bug itself gets stuck that props should be reactivelly invoked only if corresponding parent variable is changed and not if whatever parent variable changes and at the same time they modify HTML code.
This issue doesn't have nothing to do with event listeners neither events, because it is possible to replicate it without using them.
Conclusion:
{{ is_checked_2 }} or {{ '',is_checked_2 }} or {{ '',console.log(is_checked_2) }} after changing value of is_checked_2 is causing rerendering the whole top Vue component having is_checked as variable and it is resetting child component variable, because it has the same name. The solution is never using the same name for child and parent component variables bound by props. This is issue of Vue/props architecture how it was designed.
I don't think it's a bug.
You're most likely running into a race condition where your change event gets executed before or in place of the internally attached one (hence the seemingly nullified data binding).
Because v-model is essentially just a syntactic sugar for updating data on user input events. Quoting the docs:
v-model internally uses different properties and emits different events for different input elements:
text and textarea elements use value property and input event;
checkboxes and radiobuttons use checked property and change event;
select fields use value as a prop and change as an event.
You might also want to see "Customizing Component v-model".

v-model complains about props and data

Tinkering with Vue for the first time, I have a rather innocuous input like so:
<input type="number" name="quantity" v-model="quantity" />
This lives inside a component.
When quantity is set on the prop object, I get this error (when changing the value in the input):
Vue.component('my-product', {props: {quantity : {default: 1}}});
[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "quantity"
But when quantity is set on the data object as demonstrated on the Vue tutorial documentation, I get this error:
Vue.component('my-product', {data: {quantity : 1}});
[Vue warn]: The "data" option should be a function that returns a per-instance value in component definitions.
I'm at a loss. This field has no bearing on the parent views (vues?) so perhaps I am simply misunderstanding how to set this up.
Oh it's right there in the error text...
Vue.component('my-product', {
data: function(){
return {quantity : 1}
}
});

how to get the updated value when saving in vue

In my component I get some props from state like this:
computed: mapGetters({
id: 'downloadId',
pageLimit: 'pageLimit',
pageMaxSize: 'pageMaxSize',
cleaningInterval: 'cleaningInterval'
})
and I bind the property:
<input type="number" v-model.number="pageLimit" id="pageMaxSize" />
Save method:
methods: {
onSave () {
alert('Your data: ' + JSON.stringify(this.pageLimit))
}
}
When a value is entered into the input field and the save button is clicked, this.pageLimit remains the initial value
how do I get the updated value?
There is two issues with your code:
v-model should be used with data only and not with computed. a computed property value in Vue.js can not be changed unless the value or one of the values it depends on has changed.
You can not update the state directly. This is one of vuex rules. To update it you have to use a vuex mutation for that.
So the solution is:
Create a data property called tempPageLimit and bind it to the input using v-model.
In the store, Create a mutation that update the pageLimit with the value of the tempPageLimit and map it to your component using mapMutations.
Execute this mutation inside the onSave method.
look here if you want to read about vuex mutations.

When to use quotes, brackets or nothing when passing props in Vue?

I'm building a Vue template, and passing props into components. I find it somewhat confusing to decide when I need brackets, quotes or none of those, to pass a variable down into a component. I have seen these three notations:
<status-view v-bind:total=total></status-view>
<status-view v-bind:total="total"></status-view>
<status-view v-bind:total="{total}"></status-view>
What exactly is the difference between these types of notations?
Your first two examples are binding the <status-view> component's total prop to the value of total in the context of the current template's scope.
Your last example is binding the <status-view> component's total prop to the value of {total} in the context of the current template's scope.
In this case, {total} is the ECMAScript2015 object initializer shorthand for { total: total } (an object that has a key total with a value equal to the value of the total property).
To make it easier to reason about, let call the component <child>, the component's prop foo and the property we are binding bar.
With quotes:
<child v-bind:foo="bar"></child>
binds the value of the bar property in the current scope to the child's foo prop
anything within the quotes will be evaluated as a javascript expression. So v-bind:foo="bar + 1" (given bar equals 1) would bind the value 2 to the child's foo prop.
I would recommend always binding a property value to a child component's prop this way
Without quotes:
<child v-bind:foo=bar></child>
also binds the value of the bar property in the current scope to the child's foo prop
as Roy J pointed out, attribute quotes are optional in HTLM5. So this will be evaluated exactly the same as above. For consistency's sake, I would still use quotes.
As an object:
<child v-bind:foo="{bar}"></child>
binds an object { bar: bar } to the child's foo prop
for instace, if bar equaled 'test', the child's foo prop would be { bar: 'test' }
Here's the documentation for v-bind.