2.0.0.rc.7 and older
https://jsfiddle.net/Lonzpg7h/
this.isDirty = value !== '' or 'is-dirty': this.isDirty declaration - value shows up immediatelyI think input value should be visible on the first keystroke as well
In some case input value doesn't show up until you enter text for the second time.
Any idea what's going on here?
Also noticed that when I remove v-model from my component, it's working correctly
Hi, thanks for filling this issue.
For v-model to work on custom components, you need to manually $emit an 'input' event: https://jsfiddle.net/gypskp9h/
Checkout the docs here: http://rc.vuejs.org/guide/components.html#Form-Input-Components-using-Custom-Events
@fnlctrl so I always need to emit this input event?
Maybe i will try to explain what I am trying to do here. Basically i am trying to create custom textfield component but i need to recreate lazy modifier. I thought I'd handle it this way:
onInput(e) {
const value = e.target.value;
this.isDirty = value !== ''; // btw. this need to be updated immediately, so I can't use onChange listener
if (!this.lazy) {
this.$emit('input', value);
}
}
if lazy prop is enabled i would emit input event on blur
if (this.lazy) {
this.$watch('focused', (focused) => {
if (!focused) {
this.$emit('input', this.$refs.input.value)
}
})
}
but as you see there's this issue when i don't emit input event inside onInput function and I am not sure how to handle this.
@fnlctrl also you didn't explain the part where removing this.isDirty = value !== '' fixes the issue
/cc @yyx990803
I always need to emit this input event
Yes.. this is how using v-model on components work.
you didn't explain the part when removing this.isDirty = value !== '' fixes the issue
Sorry I didn't notice it.. I only noticed the $emit part being missing. I don't quite have the time to dig into it now, so I'll leave this open.. Maybe @posva @LinusBorg would kindly explain what's going on here : )
@sqal
In vue 2.0,
<textfield v-model="text"></textfield>
means if you don't fire input event from textfield, the value prop of textfield will always remain the initial value of text which is ''.
Since you never fire any input event, so value prop never changes, so the only thing that can trigger the re-render of textfield is the isDirty state.
When you input a char for the first time, the char appears first, this is the native behavior of input tag. Then this input causes the change of isDirty from false to true, which in turn causes the re-render of textfield, notice that it's value is still empty, so the content of the input gets cleared.
For the subsequent char inputs, the native behavior of input still takes effect so you can see them as well. But this time, isDirty remains true, so no re-render occurred on textfield so the content is not cleared.
If this.isDirty = value !== '' is removed, even the first re-render does not occur because isDirty has not changed, so you can see what you have input immediately, that is just the consequence of textfield not being re-rendered.
I modified your code into a template-based one to make things clearer.
So what happens here is this:
isDirty from true to falseisDirty is used in the render functionthis.value is still an empty string '', the content of the input is reset.this.isDirty is already trueThis only happens because you don't $emit the event. If you do,
value prop in the child...and everything would be fine. Your example broke the cycle, so to speak.
Edit: ah, Centaur beat me to it.
Thank you @Centaur and @LinusBorg for detailed explanation. Your answers helped me to understand Vue a little bit better :)
Have review your code made changes.
you just have to emit the event while changes happens in child
https://jsfiddle.net/f5k0kLob/
Most helpful comment
So what happens here is this:
isDirtyfrom true to falseisDirtyis used in the render functionthis.valueis still an empty string'', the content of the input is reset.this.isDirtyis already trueThis only happens because you don't $emit the event. If you do,
valueprop in the child...and everything would be fine. Your example broke the cycle, so to speak.
Edit: ah, Centaur beat me to it.