Vuex v-model with an array - vue.js

So I know to use v-model with vuex you use a computed property with a setter and getter, where the getter dispatches an action. How would this work when the property you want to bind with is an array? This is how the the code worked pre-Vuex so trying to convert it since newAds now is within Store.
<div v-for="ad in newAds" :key="ad.id">
<div v-for="key in ad" :key="key.id">
<input
type="text"
v-model="key.finalurl"
placeholder="www.books.com"
autofocus
>
</div>
</div>
Can I pass multiple parameters through a setter and then run that through to the mutation?

You can split v-model into the #input event handler and the :value property, and then handle multiple values, like this:
<input
type="text"
:value="key.finalurl"
#input="handleFinalURL"
placeholder="www.books.com"
autofocus
>
methods: {
handleFinalURL(value) {
// do stuff here like
callFunction(value, someOtherParam, extra)
}
}
It's less handy but it will solve your problem.

Related

How does one make arrow keys on number inputs lazy in Vue?

Vue supports lazy binding to models with the lazy modifier, e.g.
<input v-model.lazy="value" />
Now the model isn't updated until the input loses focus. However, if I change the type to Number and use the arrow keys to set the value, the model updates while the input has focus:
<input type="number" v-model.lazy="value" />
Is there an (easy) way to delay binding until after focus is lost?
v-model is synonymous for :value + #change. Assuming the arrows on input trigger a focus event, you can try replacing v-model with :value and #blur pair. Might not work if .lazy modifier already does this.
<input type="number" :value="value" #blur="value = $event.target.value" />
Another alternative is to "debounce" the change event with a set time so the value doesn't update while the user is changing the value.
Edit: debounce example using npm package
After installing and importing the debounce package, you need to create/assign the "debounced" version of the method (should define it in methods) to a method name under created (can be a different method name but should match what you put in #blur listener.
<input type="number" :value="value" #blur="updateValueOnBlur" />
created() {
this.updateValueOnBlur = debounce(this.updateValueOnBlur, 500);
},
methods: {
updateValueOnBlur(e) {
this.value = e.target.value;
},
}

What is the right way to use :value and v-model together in a <input>

this is my wrong code:
<input v-model="input.nameInput" type="text" :value="name" autocomplete="off" class="form-control">
<input v-model="input.posInput" type="text" :value="pos" autocomplete="off" class="form-control">
i can display the {{name}} and the {{pos}} outer of and its work. but if v-model and :value merged, error:
v-bind:value="name" conflicts with v-model on the same element because the latter already expands to a value binding internally
so what is the correct way? thanks
value is the same as v-model, v-model however updates on input where value does not.
There have been a few times I've used value over v-model but if you do this you would have to watch on input and change and update the value using a function instead.
do the following for this.
<input v-model="input.nameInput" type="text" autocomplete="off" class="form-control">
<input v-model="input.posInput" type="text" autocomplete="off" class="form-control">
Remove the value and keep the v-model.
You shouldn't use both v-bind and v-model on the same element. Consider the following code:
<label>
Input with v-bind
<input v-bind:value="message" />
</label>
<label>
Input with v-model
<input v-model="message" />
</label>
<p>{{ message }}</p>
The input with v-bind:value="message" (or it's shorthand, :value="message" will do the exact same), implements one-way binding. Any changes done to the "message" variable will be updated in this input, but changes done in the v-bind input will not change the message variable.
The input with v-model="message" has two-way binding. This means that changes to the input will reflect the message variable, but changes to the message variable will also reflect on the input. If you're building a form in vue, this type of binding is usually the way to go.
I made a JSFiddle where you can test both types of binding.
If your intention with both a v-bind and a v-model was to set a default value to your input field, you can set this value in the component's data.
data: {
message: 'My default value',
}
Or, if your fields are managed by a parent component (via props), you can set the initial value with default: "My default value".
props: {
message: {
type: String,
default: 'My default value',
},
}

Saving an entire form with vuex

I am just starting with Vue and Vuex and am wondering how to go about saving an entire form to an API. I have found this and it only seems like a good solution for a single field. Does this imply I would need to do a custom computed attribute with a getter and setter for each field in the form? I understand how data binding works well for local storage (which seems to be what most examples use) but updating a backend service with every keystroke seems like overkill.
What I would like to do is perform a single commit on a form when the user performs an action (like click a save button) and I feel like making a computed property or method for every field is not the right way to go.
Template:
<div v-show="isEditing" class="edit-view">
<form>
<div class="form-group">
<label>Title</label>
<input :value="item.title" type="text" class="form-control" #input="update" />
</div>
<div class="form-group">
<label>Description</label>
<input :value="item.description" type="text" class="form-control" #input="update" />
</div>
</form>
</div>
JS:
export default {
name: 'todo',
props: ['item'],
data() {
return {
isEditing: false
}
},
methods: {
showEdit() {
this.isEditing = true;
},
update() {
// Commit a change to vuex store
}
}
Keep the form data local to your form component. So define all form properties in data(). Apply v-model to all the input elements and your corresponding data properties. When user clicks submit, make a single commit with the form data.
This way, your form component will contain the edited values, and the vuex store will contain the submitted values.

vuejs - dynamic input 'types'

I would like to be able to dynamically change the type of an input field between text and password. I tried doing the following:
<input :type="dynamicInputType">
data() {
return {
dynamicInputType: 'password'
}
}
But apparently this doesn't work; vuejs displays the error: v-model does not support dynamic input types. Use v-if branches instead.
It's not clear to me how I can fix this with v-if.
This kind of thing is what's being suggested.
<input v-if="'text' === dynamicInputType" type="text">
<input v-else type="password">

Using $refs with Element UI's input component

Is it possible to use ref with el-input component from Element-UI? I am trying to use $refsto focus on the input when my Vue instance is mounted. Here is my code:
<div id="app">
<el-input type="text" ref="test" placeholder="enter text"></el-input>
</div>
And in my Vue instance:
new Vue({
el: "#app",
mounted(){
this.$refs.test.focus()
}
})
The focus method is not working at all, even if I move this.$refs.test.focus() into a method and try to trigger it through an event.
The $refs object stores Vue components and should be working fine. The problem is that you are attempting to invoke a focus method which doesn't exist in the component, but rather on an input somewhere inside the component's template.
So, to actually find the input you'd have to do something like this:
this.$refs.test.$el.getElementsByTagName('input')[0].focus();
Not the prettiest line of code ever made, right? So, instead of calling anything in your app's mounted method, if you want to autofocus on the input, just do this:
<el-input type="text" placeholder="enter text" autofocus></el-input>
This can be also solved your problem.
// Focus the component, but we have to wait
// so that it will be showing first.
this.$nextTick(() => {
this.$refs.inputText.focus();
});
Now you can use it like this
<div id="app">
<el-input type="text" ref="test" placeholder="enter text"></el-input>
</div>
this.$refs.test.focus();
https://element.eleme.io/#/en-US/component/input#input-methods