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()
Related
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.
I seem to be having difficulty in updating a value in a component from the vuex store when it is updated. I have looked at this question (vue.js 2 how to watch store values from vuex) and followed the accepted answer but it is not working for me. Here goes with my explanation.
Data is received by my app and a mutation to the store happens (I have verified that this is working using vuejs devtools). Here is the relevant code:
uibuilder.onChange('msg', function(newVal){
//console.info('[indexjs:uibuilder.onChange] msg received from Node-RED server:', newVal)
switch(newVal.topic) {
// Process new data from a sensor
default:
var parts = newVal.topic.split("/")
for (const [key, value] of Object.entries(newVal.payload)) {
if (!(key === "heater" || key === "battery")){
var device = { id: parts[2], name: parts[3] + '/' + parts[4], function: key, value: value }
this.$store.commit('rooms/UPDATE_VALUE', device)
}
}
this triggers the mutation in the store/rooms.js module:
mutations = {
UPDATE_VALUE(state, payload){ // Updates the value of a device in room
let device = state.rooms.find(room => room.id === payload.id).devices
.find(device => device.name === payload.name && device.function === payload.function)
device.value = parseFloat(payload.value)
},
}
and as I say this is all happening. I have a component that is displaying the device value (on a gauge, but I have removed that for now and just display the value on the page to simplify).
<template>
<b-card no-body class="bg-secondary text-light">
<b-card-body class="bg-secondary m-0 pt-0 pb-0">
<button #click="test">Test</button>
{{ deviceValue }}
</b-card-body>
</b-card>
</template>
<script>
module.exports = {
props: {
'gDevice': {type: Object},
'gRoom': {type: String},
},
data: function () {
return {
}
},
computed: {
deviceValue() {
return this.$store.getters['rooms/getDeviceValue'](this.gRoom, this.gDevice.name);
},
},
methods: {
test: function(event){
console.log(this.deviceValue)
}
},
created(){
console.log(this.deviceValue) // Check a value is being returned (it is)
},
mounted: function () {
},
watch: {
deviceValue (newval, oldval) {
console.log(newval)
},
}
}
</script>
When a new value comes into the app the store is definitely updated but it is not triggering anything to happen in my component. I added a button to test whether the computed value is changing - it is not! I guess this explains why the watch event is not being fired. I just don't understand why the computed value is not updating even though the value in the store has definitely changed. Hopefully someone can see my error.
Here is the getter in the store:
getters = {
getDeviceValue: (state) => (roomname, devicename) => { // returns the value from a device in a room
return state.rooms.find(room => room.name === roomname).devices.find(dev => dev.name === devicename).value;
},
}
!!UPDATE!!
I just discovered that the mutation to the value is not being committed. If I use the devtools and press the "Commit all" then everything updates as expected. But if I reload the app then I have to do this again. I have no clue how to fix this???
Thanks
Martyn
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
I use vuetify in my project and need typeahead component. Sadly v-autocomplete implemented as combobox with filter, so it doesn't allow setting user input as v-model (or at least I can't find I way how to do so).
Could someone please explain me how to implement such functionality (maybe by another vuetify component)? I load items from server, but they are serve just as suggestions. Users need to have an ability to type and set any value they want to.
Here is a base example https://codepen.io/miklever/pen/oMZxzZ. The problem is that if I type any word that doesn't start with 'John' v-autocomplete clears it on blur. I've tried to set v-model manually and to add user input to array, but any of this methods has issues and doesn't work as expected.
<div id="app">
<v-app>
<v-content>
<v-container>
<p>Name: {{ select || 'unknown'}}</>
<v-autocomplete
:items="items"
:search-input.sync="search"
v-model="select"
cache-items
flat
hide-no-data
label="Name"
></v-autocomplete>
</v-container>
</v-content>
</v-app>
</div>
new Vue({
el: "#app",
data: () => ({
items: [],
search: null,
select: null,
commonNames: ["John", "John2", "John3"]
}),
watch: {
search(val) {
val && val !== this.select && this.querySelections(val);
}
},
methods: {
querySelections(v) {
setTimeout(() => {
this.items = this.commonNames.filter(e => {
return (e || "").toLowerCase().indexOf((v || "").toLowerCase()) > -1;
});
}, 500);
}
}
});
In Vuetify 1.1.7 Combobox has new feature which you can refer to.
Its on the Advance custom options.
had this same issue and solved it with the v-combobox it's kinda like the same as v-autocomplete so, you can just replace your tags with <v-combobox></v-combobox> or check the documentation here: https://vuetifyjs.com/en/components/combobox/#usage
When I update the parent's singleIssue variable, it does not get updated inside my <issue> component. I am passing it there using props. I have achieved this in other projects already, but I can't seem to get what I am doing wrong.
I have reduced my code to the relevant parts, so it is easier to understand.
IssueIndex.vue:
<template>
<div class="issue-overview">
<issue v-if="singleIssue" :issue="singleIssue"></issue>
<v-server-table url="api/v1/issues" :columns="columns" :options="options" ref="issuesTable">
<span slot="name" slot-scope="props">{{props.row.name}}</span>
<div slot="options" slot-scope="props" class="btn-group" role="group" aria-label="Order Controls">
<b-btn class="btn-success" v-b-modal.issueModal v-
on:click="showIssue(props.row)">Show</b-btn>
</div>
</v-server-table>
</div>
</template>
<script>
export default {
mounted() {
let app = this;
axios.get('api/v1/issues/')
.then(response => {
app.issues = response.data;
})
.catch(e => {
app.errors.push(e);
});
},
data: () => {
return {
issues: [],
singleIssue: undefined,
columns: ['name', 'creation_date', 'options'],
options: {
filterByColumn: true,
filterable: ['name', 'creation_date'],
sortable: ['name', 'creation_date'],
dateColumns: ['creation_date'],
toMomentFormat: 'YYYY-MM-DD HH:mm:ss',
orderBy: {
column: 'name',
ascending: true
},
initFilters: {
active: true,
}
}
}
},
methods: {
showIssue(issue) {
let app = this;
app.singleIssue = issue;
// This gets the action history of the card
axios.get('api/v1/issues/getCardAction/' + issue.id)
.then(response => {
app.singleIssue.actions = response.data;
})
.catch(error => {
// alert
});
}
}
}
</script>
Issue.vue:
<template>
<div>
{{ issue }}
</div>
</template>
<script>
export default {
props: ['issue']
}
</script>
So after showIssue() is triggered, it will get actions for the issue. But after then, I can't see the actions in the issue component.
If I update the issue-model in the issue component using form inputs, it will also start showing the actions. So I assume it's just in a weird state where it needs a refresh.
Thanks in advance!
If the singleIssue.actions property does not exist at the time when you're setting it, Vue will not be able to detect it. You need to use $set, or just define the property before you assign singleIssue to app.
Change this:
app.singleIssue = issue;
to this:
issue.actions = undefined;
app.singleIssue = issue;
The app.singleIssue property is reactive (because it was declared in the data section), so Vue will detect when this property is assigned to and make the new value reactive if it isn't already. At the time when issue is being assigned, it will be made reactive without the actions property, and Vue cannot detect when new properties are being added to reactive objects later on (hence why $set is required for those situations).