Selecting text in a textField with Vuetify - vue.js

I'm trying to dynamically set the value of a text field in Vuetify, focus it and selecting its text (in order for the user to be able to quickly reset the field if necessary). The error I get is "select is not a function". This works for normal text inputs, but does not with Vuetify text fields.
<template>
<vContainer>
<vTextField
ref="input"
v-model="input"
/>
<vBtn
#click="test"
>
Select
</vBtn>
</vContainer>
</template>
<script>
export default {
data: () => ({
input: null,
}),
methods: {
test() {
this.input = 'test value';
this.$refs.input.focus();
// this.$refs.input.select(); -> TypeError: this.$refs.input.select is not a function
},
},
};
</script>

An easy trick to select text in text field:
<v-text-field
v-model="inputModel"
#focus="$event.target.select()"
></v-text-field>

The problem is that this.$refs.input is not the underlying HTML input element. To get the input element do something like...
let inputEl = this.$refs.input.$el.querySelector('input')
Also, setting the this.input value and then attempting to immediately focus() and select() will not work. You'd need to use nextTick or setTimeout before attempting to select(). For example:
test() {
let inputEl = this.$refs.input.$el.querySelector('input')
this.input = 'test value'
setTimeout(()=>{
inputEl.select()
},200)
},
Demo

Related

Assigning data to fields on opening dialog in vuetify

I've created a dialog box using vuetify and I want it to be prepopulated with data in the v-select but it's blank when I open the dialog modal. I've assigned the propPackage to the selectPackage which is used in v-model in the v-select. How should I prepopulate it when I open the dialog?
Dialog
<template>
<v-row justify="center">
<v-dialog v-model="dialog" max-width="600px" #click:outside="close">
<v-select
:items="['Basic', 'Standard', 'Premium']"
label="Package*"
required
v-model="selectPackage"
></v-select>
<v-btn #click="close"> Close </v-btn>
</v-dialog>
</v-row>
</template>
<script>
export default {
props: {
dialog: {
type: Boolean,
required: false,
default: false,
},
propPackage: {
type: String,
required: true,
},
},
data: () => ({
selectPackage: this.propPackage,
}),
methods: {
close() {
this.$emit("close");
},
},
};
</script>
Parent component
<template>
<v-btn #click="bookDialog('Basic')"></v-btn>
<form-modal :dialog="openDialog" #close="close" :propPackage="propPackage" />
</template>
<script>
import FormModal from "#/components/FormModal.vue";
export default {
components: {
FormModal,
},
data: () => ({
openDialog: false,
propPackage: null,
}),
methods: {
bookDialog(val) {
this.propPackage = val;
this.openDialog = true;
},
close() {
this.openDialog = false;
},
},
};
</script>
Check this codesandbox I made: https://codesandbox.io/s/stack-70077413-943o6?file=/src/components/FormModal.vue
The main issue is that you're trying to access the prop value directly on your data block:
data: () => ({
selectPackage: this.propPackage,
}),
In this case, it would be better to get the prop value by setting up a watcher instead, just like this:
data: () => ({
selectPackage: ''
}),
watch: {
propPackage(val) {
// Be sure to validate default values
if(val !== '') {
this.selectPackage = val
}
}
},
This way, you can also validate the prop value if you need to.
I added a few more comments in the codesanbox on things you could improve. Since the FormModal component works mainly as a dialog, you can use the 'value' prop and set up a computed property to be able to close the dialog directly from the child component, this way you avoid emitting a #close event to the parent component and the prop mutation warning.
Since you are using arrow functions for data section, this.propPackage will be undefined since this won't refer to vue instance. You can fix that in 2 ways:
Change the arrow function to ES6 notation in your dialog component:
data() {
selectPackage: this.propPackage,
},
Pass the vue instance as a parameter to arrow function and access your prop using that:
data: (instance) => ({
selectPackage: instance.propPackage,
}),
Once you populate your selectPackage data property the right way, your v-select will be populated with the value once you open your dialog.

Vue3js Cutom input component disappearing if value=null

I’m using the following component for custom clic-edit input
<template>
<el-input
v-show="edit"
ref="inputField"
type="text"
placeholder="place"
v-model='value'
#blur.native="
local = $event.target.value;
edit = false;
$emit('input', local);
"
#keyup.enter.native="
local = $event.target.value;
edit = false;
$emit('input', local);"
/>
<span v-show="!edit" #click="startEdit" > {{ local }}</span>
</template>
<script>
export default {
props: ["value"],
data() {
return {
edit: false,
local: this.value,
};
},
watch: {
value: function () {
this.local = this.value;
},
},
methods: {
startEdit() {
this.edit = true;
this.$refs.inputField.focus();
},
},
};
</script>
I am then using it, everything's seems ok.
Text switch to input as expected.
But If I pass a null value then the rendered component disappears.
Why ? How can I avoid this ?
<template>
<ClickEdit :value="'velue-test '" />
</template>
When passing or validating an empty value, the component disappears.
Actually your components is being rendered (you can see in devtools console). But because you pass empty or null as value prop to component there is nothing to show for editing. So you must set a default text to show in case of empty value (for example Edit here...). Then after user update the input replace it.
You can see this codesandbox to understand what I mean.

How to make a checkbox selected by default in VueJs?

EDIT: My problem has shifted somewhat, with a different code focus, so I created a new question.
I have a Beufy Form Field Component, with a Boolean Input Checkbox inside, this Form Field Component allows you to select the option "Later" and this disables the Form Field and Checkbox. I would like to have it so that when "Later" is selected, the Boolean Input Checkbox is ticked/enabled by default.
I've read the Buefy checkbox documentation and I can see that I should use
<b-checkbox :value="true"
but when I attempt add it to my FormField template (the checkbox is a child component of the Form Field component) call it throws errors, this is how the template is rendered:
<FormField
:for="param.editableByOperator"
:label="null"
:disabled="param.populationStrategy.value === 'later'"
:checked="checked"
as="Boolean">
</FormField>
How do I best implement this fix? I'll attach the Checkbox Component
Below:
<template>
<b-checkbox
v-model="localValue"
:name="$props.name"
:checked="checked">
{{label}}
</b-checkbox>
</template>
<script>
import BaseInput from './BaseInput';
export default {
name: 'BooleanInput',
mixins: [BaseInput],
props: {
checked: {
type: Boolean,
default: true,
},
}
};
</script>
edit:
In my component I have found these methods, which set the checkbox as unticked by default. Is there something I can do here which would set the checkbox(editableByOperator) to True when 'Later'(populationStrategy) is set to 'Later.
Methods:
drawMonadParams(monadSlug) {
const monad = this.ccMonad(monadSlug);
monad.params.forEach((x, idx) => {
this.addFormFields(['params', idx], {
value: this.defaultMonadParamValue(x.typeSlug),
populationStrategy: 'now',
editableByOperator: false,
ccRequestParamId: null,
name: x.name,
typeSlug: x.typeSlug,
});
});
},
defaultMonadParamValue(typeSlug) {
return typeSlug === 'boolean' ? false : '';
},
May be try not using the checked prop inside the template . Try a data variable and use that instead.
like this
<b-checkbox :checked="checkValue"></b-checkbox>
props(){
checked:{
type:Boolean,
default:true
}
data(){
return{
checkValue : this.checked
}
}

Vuetify clear autocomplete input programmatically

can you take a look on this pen:
https://codepen.io/slayerbleast/pen/mdJMqwz
Why when you click on reset, it actually sets the input = null but on the input it's still showing the old value. You can get the real value clicking the other btn.
I'd would like to reset the autocomplete input with another btn like this pen instead of the clearable btn.
I tried to add: :search-input.sync="input"
But it causes undesired side effects... (for example it triggers the form validation automatically although it has lazy-validation attribute.
What do you think? Seems a bug? Setting the model to null should clear the input too.
Found the bug: https://github.com/vuetifyjs/vuetify/issues/10688
As noted in comments, this behavior changes in v2.2.15. The release notes show that the change is deliberate,
VAutocomplete: check for inital search input prop (#10642) (e09c916), closes #9757 #9757 #9757
Specifically, the code that changes is the VAutocomplete method setSearch()
setSearch () {
// Wait for nextTick so selectedItem
// has had time to update
this.$nextTick(() => {
if (
!this.multiple ||
!this.internalSearch ||
!this.isMenuActive
) {
this.internalSearch = (
!this.selectedItems.length ||
this.multiple ||
this.hasSlot
)
? this.internalSearch || null // "? null" in v2.2.14
: this.getText(this.selectedItem)
}
})
},
If you're happy with 'patching' within your app, this can be reversed by using a reference on the autocomplete
<template>
<div>
<v-autocomplete ref="autocomplete" v-model="input" :items="items" clearable></v-autocomplete>
<v-btn #click="reset">reset</v-btn>
<v-btn #click="value">get value</v-btn>
<div>{{input}}</div>
</div>
</template>
<script>
export default {
name: "playground",
data: () => ({
input: null,
items: ["a", "b", "c", "d"]
}),
mounted() {
console.clear();
console.log(this.$refs);
},
methods: {
value() {
alert("value: " + this.input);
},
reset() {
this.$nextTick(() => {
this.input = null;
this.$refs.autocomplete.internalSearch = null;
})
}
}
};
</script>
Codesandbox
You can use the built in reset function.
this.$refs[REF].reset()

v-select doesn't recognize label prop

I'm working on a VueJs file and try to use <v-select> so what I'm doing is that :
<v-select :options="divisions" label="text" ></v-select>
and my divisions is an array of object conatining id and text but when i'm going on my page I have <% getOptionLabel(option) %> instead of the text value for each one of my divisions value
here is a screenshot of console.log(this.divisions) :
So this is my code :
<form id="MassUpdateDivisionForm">
<v-select v-bind:label="text" :options="divisions"></v-select>
</form>
<script>
import vSelect from "js/vue-select/vue-select.js"
export default {
props: ['product'],
components: {vSelect},
data() {
return {
divisions: []
}
}
methods: {
getDivisions(){
let self = this
this.$http({
url: 'divisions',
method: 'get'
}).then((response)=>{
self.$set('divisions', response.data)
console.log(self.divisions)
//that's where I got the pic
},(response)=>{
alert('something went wrong')
}
)
}
},
created () {
this.getDivisions()
},
}
</script>
If I am understanding you correctly, you want the text attribute of the selected option to be displayed as the label? If so, you will need to pass the data of the selected option back to the <v-select>. You can emit an event on change to change label to the text value, but make sure you bind to the label attribute using either v-bind:label=textor the shorthand :label=text
I just had the same problem and solved it by passing the name of the label as a string.
<v-select :options="warehouses" :label="'name'"></v-select>
or you could do it with an html attribute without vue binding.
<v-select :options="warehouses" label="name"></v-select>
Cheers,