I have an input field with the value field being passed a string stored in Vuex.
The input fields changes are debounced and the new string synced to Vuex.
When bound like this :value="vuexState.myString, when typing, the cursor jumps to the end of the line.
When bound like this value={{vuexState.myString}}, the cursor stays where it is.
According to the guide: http://vuejs.org/guide/syntax.html#Arguments
These two should be the same, with the {{ }} style being internally converted to :bind. Could this be a bug?
My theory is that the cursor jumping occurs because the vuex state change re-renders the input and that the {{ }} style is interpolated only once while the binding syntax re-renders the input every change.
I am currently using value={{vuexState.myString}} but I'd like to know what is happening or if there is a better way to do this.
It's in the documentation about Interpolation and has been deprecated (see. Migration guit from 1.x)
Deprecated
This is the old way
<div class="btn btn-primary hint--top {{class}}"></div>
Solution
Use Javascript expression instead:
<div v-bind:class="'btn btn-success hint--top '+ class "></div>
Take a look at the console, it seems like it has been deprecated in favour of the colon syntax or v-bind:
vue.js:2237 [Vue warn]: foo="{{foo}}": Interpolation inside attributes has been deprecated. Use v-bind or the colon shorthand instead.
v-text:'something' === {{something}}
Related
In Vue 3 the following line of code produces an error:
<input v-model="modelValue[idx].name" v-for="(item, idx) in modelValue" :key="idx">
The error is the following:
error Unexpected mutation of "modelValue" prop vue/no-mutating-props
This makes sense, since modifying property values is considered an anti-pattern:
https://v2.vuejs.org/v2/guide/migration.html#Prop-Mutation-deprecated
Yet the following line of code compiles and runs happily:
<input v-model="item.name" v-for="(item, idx) in modelValue" :key="idx">
I still modify the very same object, the only difference is that I refer to it indirectly. Is this OK, or is this an anti pattern that the linter fails to detect?
I have found the answer in the documentation:
Warning
Note that objects and arrays in JavaScript are passed by reference, so if the prop is an array or object, mutating the object or array itself inside the child component will affect the parent state and Vue is unable to warn you against this. As a general rule, you should avoid mutating any prop, including objects and arrays as doing so ignores one-way data binding and may cause undesired results.
https://v3.vuejs.org/guide/component-props.html#one-way-data-flow
Can someone explain to me exactly what the input-value attribute does on the v-switch component?
I think it has something to due with using the component with vuex, when you cannot use v-model directly.
It seems to be working for me, but I don't understand it exactly.
You can see the attribute here: https://vuetifyjs.com/en/components/selection-controls#api
Where it is described as: "The v-model bound value".
(I originally found the attribute in an example somehere.)
input-value behaves like a default value attribute that you would expect in other components.
Normally v-model is syntax sugar for :value="value" :input="$emit('input', $event.target.value)", but we can change it.
from selectable.js:
model: {
prop: 'inputValue',
event: 'change'
},
So the above lines (see vue docs) make your v-model bind to input-value instead of value likely because some components i.e. checkbox (which v-switch uses) have value attribute reserved for something else.
So value attribute is then used to set the value which will be represented when the component is checked.
And in v-switch case v-model is syntax sugar for something like :input-value="value" #change="value = $event"
Codepen
Why this "value" can not be written as "pricevalue" or other, otherwise input will not convert non-numeric values
In the props element, you are defining the properties your component will attach to. You can call them whatever you want. You need to be clear about a couple of things...
You define the name here in camelCase, but when you call the component in the parent markup, use kebab-case.
methods only run when they are called. If you put your formatting on the downstream side (receiving a value and displaying it), everything will be reactive and all your values should display correctly. It will all just work whenever the source value changes. So do your formatting in a computed, like this...
js
computed: {
formattedPriceValue(){
return Number.parseFloat(this.priceValue).toFixed(2)
}
}
You can also just do it inline...
markup
<input type="number" :value="Number.parseFloat(priceValue).toFixed(2)">
The value you want to emit is probably the unformatted output of Number.parseFloat #change="$emit('price-changed', Number.parseFloat(event.target.value))"
Then, you will live longer if you do your number formatting with the Number functions provided.
Also, why don't you use the new template (multi-line) strings, delimited by a backtick `. They're much cleaner than the line continuation character you're using.
ps. I love seeing the chinese (?) comments in the code. I've copied and pasted them into my code. I hope there's no swearing. Unicode rocks.
In vue 1 it was possible to do this:
<app v-ref:test-app></app>
and then reference it like so:
vm.$refs.testApp;
however in vue 2 the syntax for the ref has changed to:
<app ref="test-app"></app>
but this no longer can be referenced by
vm.$refs.testApp
instead it only works if:
<app ref="testApp"></app>
which in standard DOM stuff isn't allowed. Is it a bug? can kebab case no longer be used?
Since the syntax has been changed from that of a namespaced element attribute (i.e., v-ref:foo-bar) to a normal key-value-pair attribute (i.e., ref="fooBar"), the implicit kebab-case-to-camel-case conversion is no longer applicable because the reference name is a plain string and is not constrained by having to conform to the requisite lowercase-kebab-case HTML syntax.
In other words, you can identify a ref with any string, so it wouldn't make sense for Vue to manipulate it. Have a look at this CodePen for an example in action of what I mean.
But, basically, a plain string ref value means you can define a reference like this:
<div id="app" ref="test ** app!"></div>
and reference it from Vue like this:
this.$refs['test ** app!']
In short, no, it's not a bug but no, automatic kebab-case conversion no longer takes place.
I need to use some handlebars block helpers inside of an element's attribute. How can I get
.some.class{:class => "{{if property}} otherClass {{/if}}"}
to parse properly? Here is the compiled output as is:
<div class='class otherClass property}} some {{/if}} {{if'></div>
I've tried escaping every non-word character, trying single quotes, and adjusting the spacing, but nothing seems to fix it. I'm hoping to find a more elegant solution than just using the :plain keyword.
I've found that you need to add some character before the {{}} for Haml to accept it. For example:
%div.some.class{:class => "a{{foo}}"}
Not idea, but suites my purposes.
Actually, the trick doesn't work for anything handlebars expression that is moderately complex.
In the end I resolved this by using string literals in haml. So in the example case shown in the question. The below haml is needed, remember to close your tag, which is the last line.
\ <div class='class {{if property}} otherClass {{/if}} some '>
-# Normal haml goes here and must not start at the same indent as the above literal
\ </div>
Move all the classes in to the class attribute instead of using both the class shorthand dot notation and a class attribute.
.col-md-12.card{ class: "{{toLowerCase level_name}}-master-card" }
becomes
%div{ class: "col-md-12 card {{toLowerCase level_name}}-master-card" }
HAML 4.0.7