1đź‘Ť
The code works as you wrote it:
-
<p>{{input}}</p>
– this is the first line. On init it’s empty, so now lines are shown. -
<input v-model="input" list="list" />
this is the second line, but on init it is displayed first.
So, when your app reacts to data change, the input
is pushed one line down. If you initialize your input
data with something else than ''
, then you can see that nothing unexpected happens (OK, maybe unexpected, but not extraordinary 🙂 ):
new Vue({
el: '#app',
data: {
input: '',
list: [{
name: "Item 1",
code: "i1"
},
{
name: "Item 2",
code: "i2"
},
{
name: "Item 3",
code: "i3"
},
{
name: "Item 4",
code: "i4"
},
]
},
methods: {
loseFocus(evt) {
evt.target.blur()
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<p>{{ input || 'Data comes here' }}</p>
<input v-model="input" list="list" @input="loseFocus" />
<datalist id="list">
<option v-for="item in list" :value="item.code">{{item.name}}</option>
</datalist>
</div>
EDIT
The problem was not the “jumping” of the input, but that the datalist appeared open after picking an option.
The problem is that this element stays focused after the input/change event, so it behaves in an unwanted way. (But as it’s supposed to behave.)
I added @input
on the element, and created a method
to blur the element (so it loses focus, and the datalist doesn’t open/closes).
2nd EDIT
We discussed the question a bit more in the chat, and came up a with a snippet that is closer to the actual solution @KshitijDhakal sought:
new Vue({
el: "#app",
data: {
input: '',
list: [{
type: 'posts',
title: 'Posts',
code: 'i1'
},
{
type: 'albums',
title: 'Albums',
code: 'i2'
}
],
singleItem: {
title: ''
}
},
methods: {
fetchData: function(type, id) {
return fetch(`https://jsonplaceholder.typicode.com/${type}/${id}`)
.then(response => response.json())
.then(json => {
return json
})
},
onSelect: async function(e) {
if (this.list.map(el => el.code).includes(e.target.value)) e.target.blur()
this.singleItem = await this.fetchData(this.list.find(el => el.code === e.target.value).type, 1)
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input v-model="input" list="list" @input="onSelect" />
<datalist id="list">
<option v-for="item in list" :value="item.code">{{item.title}}</option>
</datalist>
<div>
<h2>
{{singleItem.title}}
</h2>
</div>
</div>