vuejs - dynamic input 'types' - vue.js

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">

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;
},
}

vue computed placeholder changes multiple select-boxes

Vue version 2.6.10
I'll try writing in the code that gives the relevant information to prevent this from being huge
this is part of my component that has to do with select boxes
<div class="input-field">
<input
:id="name"
v-model="searchFilter"
type="text"
tabindex="-1"
:class="{ searchbar: true, 'validation-error': validateError }"
autocomplete="off"
spellcheck="false"
:disabled="disabled || loading"
:readonly="single"
:placeholder="placeholder"
#click="openList"
/>
<input-icon :loading="loading"></input-icon>
</div>
this is the computed part which does the placeholder part
computed: {
placeholder() {
if (this.single) {
const selected = this.singleList.filter(item => item.selected === true).shift();
return selected === undefined ? `Select ${_.startCase(this.name)}` : selected.name;
}
},
},
The issue is, that lets say I've got 3 instances of this component running?
once I choose one of them? the rest change their UI (aka placeholder value)
This is strictly a ui problem since I can tell that the value stays the same but I can't seem to find a way to access that value in order to show it.
I hope this is enough information to go on
Will provide additional code if needed.
Thanks in advance.

Vuex v-model with an array

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.

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',
},
}

v-bind object's properties in radio buttons can't render correctly

The radio buttons' behavior is not as I expected when I am being lazy to use v-bind to dynamically bind the properties of the options to the template.
I am trying to dynamically render the options by an javascript object. However, it behaves differently when I am binding the properties differently. Even after checking the output HTML, I am not sure why the problem exists.
This is the Vue instance for backend data.
const app = new Vue({
el: '#app',
data: {
inputs: {
radioDynamic: '',
radioDynamicOptions: [
{
id: 'Light',
label: 'Blue',
value: 'Light',
},
{
id: 'Dark',
label: 'Red',
value: 'Dark',
},
],
},
},
template: `
<div>
<h4>Radios Dynamic Options</h4>
<!-- case 1: It works fine when I bind properties individually>
<template v-for="(option, index) in inputs.radioDynamicOptions">
<input v-model="inputs.radioDynamic" type="radio" :value="option.value" :id="option.value">
<label :for="option.value">{{ option.label }}</label>
<br v-if="index < inputs.radioDynamicOptions.length">
</template>
-->
<!-- case 2: the options are rendered as a single radio button which is not able to function correctly when I bind the object directly with v-bind="object".
<template v-for="(option, index) in inputs.radioDynamicOptions">
<input v-model="inputs.radioDynamic" type="radio" v-bind="option">
<label :for="option.value">{{ option.label }}</label>
<br v-if="index < inputs.radioDynamicOptions.length">
</template>
-->
<p><strong>Radios:</strong>{{ inputs.radioDynamic }}</p>
</div>
`,
})
<case 1 HTML output>
<h4>Radios Dynamic Options</h4>
<input type="radio" id="Light" value="Light">
<label for="Light">Blue</label>
<br>
<input type="radio" id="Dark" value="Dark">
<label for="Dark">Red</label>
<br>
<p><strong>Radios:</strong>Dark</p>
<case 2 HTML output>
<h4>Radios Dynamic Options</h4>
<input type="radio" id="Light" label="Blue" value="Light">
<label for="Light">Blue</label>
<br>
<input type="radio" id="Dark" label="Red" value="Dark">
<label for="Dark">Red</label>
<br>
<p><strong>Radios:</strong></p>
I expect the case 2 method, which is using v-bind="object", should generate the same result like v-bind:id="object.id" v-bind:value="object.value"
But it turns out that I can't select the radio button individually and the selected value isn't pushed into the array.
This is my very first question here. Please forgive if my expression or format isn't good or qualified enough. Thanks and have a great day~
not sure what you're trying to achieve here, but i would recommend going over the functionality of v-bind and v-model. v-bind enables passing dynamic data to html attributes. v-on allows listening to DOM events, and v-model results in whats called - two way data binding, which is basically a combination of both v-bind and v-on. with that said, using both v-model and v-bind on the same element feel's a bit odd.
you might achieve what you desire in the 2nd case following way:
<template v-for="(option, index) in inputs.radioDynamicOptions">
<input v-model="inputs.radioDynamic" type="radio" v-bind:value="option.id">
<label :for="option.value">{{ option.label }}</label>
<br v-if="index < inputs.radioDynamicOptions.length">
</template>
UPDATE:
i believe that the issue your'e experiencing is a result of one main difference between object (which you can learn more about here) and primitive types.
long story short, in JavaScript primitive types like the strings you pass in case 1 are being passed by value and so behave as expected. while passing object's to v-bind you actually pass a pointer to that object and so when you click a radio button, you manipulate the same place in memory in charge of both radio buttons, which results with the unexpected behavior you experience.
Why do you expect that v-bind="options" will work on <input/>? This form is used for custom components only.
From documentation:
Components In-Depth → Props → Passing the Properties of an Object
If you want to pass all the properties of an object as props, you can use v-bind without an argument (v-bind instead of v-bind:prop-name). For example, given a post object:
post: {
id: 1,
title: 'My Journey with Vue'
}
The following template:
<blog-post v-bind="post"></blog-post>
Will be equivalent to:
<blog-post
v-bind:id="post.id"
v-bind:title="post.title">
</blog-post>
If you want to bind dynamic/javascript values to an usual element, you should use :value="option.value" :id="option.id" as shown in your first example.