2.5.2
https://codepen.io/anon/pen/OxKqbL?editors=1111
Please open codepen example and type something into input
Input should not lose focus
input rerenders and loses focus
happens only if there is such conditional elements exists before and after input. Workaround is to use v-show instead of v-if in such cases.
You can also simply give the <input> a key to ensure it is not replaced.
i tried your solution in codepen and still cant get it working.
i tried this
<input type="text" v-model="inputVal" :key="1">
U need to have same DOM structure before your input. Look this. It can be after update your DOM before your input tag
Actually, it is the same input element, but first remove from the document then move it to other places, for example:
it first renders like
<!----> // A
<input />
<!----> // B
then you focus input and input some words, then virtual dom insert <span>before</span>, and it then parent.insertBefore(input, A), it moves the input element before the A comment element, so it will eventually lose focus, then it will delete the comment node.
so, I think you could use v-show better to avoid the insertBefore move problem(remove from the document then insert before the reference node, in this case, which is comment A ). This is the default action for virtual dom of vue which doesn't replace comment node.
You can also simply give the
<input>a key to ensure it is not replaced.
<input> element focus is lost in either case.
https://github.com/google/incremental-dom/issues/237
seems like this one
I have tried to fix this issue
But I encountered some problem
have we got some way to access vnode from html element?
I want to get vnode path as https://github.com/google/incremental-dom/issues/237
But I did not find a good way to do that
have i missing something? or have other better solution?😅
@Kingwl you can use v-show. It works correctly.
Alternative way:
https://codepen.io/furrya_black/pen/ZVVLpQ
Just html-layout usually has a more complex structure. What do you thing?
As a proof you can see any css framework: material disign, bulma, bootstrap, etc (what else)
UPD: if your case require rerender-mehanic (with v-if)
It also seems to break (loose focus) if the spans are shown initially:
https://codepen.io/janschoenherr/pen/NoJpoY?editors=1111
I would think that it doesn't need to do insertBefore in this case.
Other reproductions:
https://codepen.io/adamwathan/pen/vMJrYj
https://codesandbox.io/s/q9mqnjnxr9
F.Y.I. It seems that #9473, #9496, #9808 all share the same root cause.
I'm using Vue 2.6.7 and this issue is still relevant, i was able to work it out by using v-show instead of v-if on a sibling, but it's still confusing why it doesn't work when v-if is used
I found that @focus is not reliable when using DOM manipulation, such as v-if and therefore, directives would be the best approach:
<template>
<form method="POST"
autocomplete="off"
@submit.prevent="onSubmit">
<!-- We set the directive here v-focus with the function prop handleFocus -->
<div class="flex mt-1 rounded-md shadow-sm">
<input id="title"
type="text"
v-focus="handleFocus"
v-model="form.title">
</div>
</form>
</template>
<script>
export default {
name: "FormComponent",
data() {
return {
// A form class example, but you could just have a var
form: new this.$form({
title: null,
})
}
},
directives: {
focus: {
inserted(el,binding) {
// We set focus on the element
el.focus();
// optional if you had other operations. Data and props, etc. are not available inside
// a direective uless yoru decorate the provider, which is a pain. So we call the binding
// which is the handleFocus set on input. We pass the el but we could inject nothing or a event, binding, etc
if (!_.isUndefined(binding.value)) binding.value(el)
}
}
},
methods: {
handleFocus: function() {
// For example reset a form v-model
this.form.title = null;
},
}
}
</script>
Most helpful comment
Actually, it is the same input element, but first remove from the document then move it to other places, for example:
it first renders like
then you focus input and input some words, then virtual dom insert
<span>before</span>, and it then parent.insertBefore(input, A), it moves the input element before the A comment element, so it will eventually lose focus, then it will delete the comment node.so, I think you could use v-show better to avoid the insertBefore move problem(remove from the document then insert before the reference node, in this case, which is comment A ). This is the default action for virtual dom of vue which doesn't replace comment node.