https://github.com/vuejs/vue/issues/4827 as a refrence that some lifecycle hooks DO have the event available while not for others.
export default {
props:['hasErrors'],
components: {
'FormErrors': require('./Errors.vue')
},
data() {
return {
input: ''
}
},
mounted () { // get the hidden inputs value
if (this.$el.type == 'hidden') {
this.input = this.$el.value
}
},
watch: { // send data to the central storage to be picked up by the parent
input(val, oldVal) {
storage.data.userInfo[event.target.name] = val;
}
},
}
Cannot read property 'target' of undefinedwithout mounted()
https://cl.ly/3V3p3U2L2I3j/Screen%20Recording%202017-02-01%20at%2007.59%20PM.gif
with
https://cl.ly/3H3p3j3H3n2J/Screen%20Recording%202017-02-01%20at%2008.01%20PM.gif
fiddle
https://jsfiddle.net/svz0hb8j/2/
now if we replaced watch() with updated() the error is gone
updated() {
storage.data.userInfo[event.target.name] = this.input;
},
don't know why this happens specially that both pretty much does the same thing. https://vuejs.org/v2/api/#updated
If you remove the mounted callback, you never update input, therefore your watcher is never called, hence, you never see the error.
event doesn't exist in your watcher because you're not declaring it as a parameter for the function, but even if you did, Vue doesn't pass it to watchers. Watchers are triggered on changed data on the view model. Those changes aren't necessarily originated from DOM (input events), so it doesn't make sense to pass event to watchers.
if u checked the first gif, u will see that i don't need to pass event as param to the watcher because every time the input or whatever the watcher is hooked to change its value, it automatically fires an event which we simply catch it inside the watch() same as updated().
the only reason am using mounted() is to get a pre-init value of a hidden input, also mounted() doesnt care whether the DOM was changed or not, hence we have to use either watch() or updated() to catch those changes if any.
however as i stated in the main ticket, calling event inside updated() works just fine and doesn't triggers any errors, while watch() does & if you need another gif comparing both along with mounted, i can happily provide it.
I have no idea where the event is coming from in your code...
@ctf0, brother, event won't just magically exist if you don't declare it somewhere. In this case, it would be as a param since window.event isn't a thing (except for IE, but never mind that). There is no global event identifier you can use here.
There is no event fired that is "caught" by watch. watch is a callback invoked by the VM when whatever it is watching changes. In this case, you are watching input. The only place you are changing its value is in your mounted callback by doing this.input = this.$el.value (this is the reason your watcher is called). That statement does not produce any new DOM event that could be sent to your watcher.
event will never mean anything relevant to your needs in either updated or your watcher.
Now, if you comment out your mounted callback, there is nothing in your code that is changing input. This means your watcher will never be called. This is the reason you never see the error.
Regarding not seeing the error when using updated. You are not doing anything in your code that would cause a DOM update. Your updated callback is therefore never called. This is the reason you never see the error.
I hope this makes it clearer for you.
okay then, i will make a small demo video to clear things up and make it easier to understand why i opened those 2 tickets.
Closing since I don't see anything actionable here, neither a bug or a feature request. Please discuss elsewhere so that only fully reproducible bugs or properly elaborated feature requests are opened as issues.
@yyx990803 all i was asking for is little more time to present the issue more clearly and prov that there is a bug and its not related to what everyone is describing.
@ctf0 You can take all the time you need, and when your reproduction is ready, please open a new issue.
@yyx990803 @hector-humberto @LinusBorg @HerringtonDarkholme https://drive.google.com/open?id=0B1q9LR33Y0lNZXR5TGVMTWlkN28
and here is the code to test with if u want
https://github.com/ctf0/vuebug
Thanks for providing a video and repository.
But as I don't use composer and don't want to install it only for a reproduction that should be achievable in a fiddle on jsfiddle.net just as well (the fiddle from your original post does *not reproduce the problem*), sorry.
I also have no idea where in that deeply nested folder structure the component(s) in question are to be found, so I can only talk about what I could deduce from watching the video.
That being said, I can say the following:
That event variable that you use is non-standard. Not all browsers support it,certainly not Firefox.
https://developer.mozilla.org/en-US/docs/Web/API/Window/event
So it's generally a very bad idea to rely on this, unless you know none of your users will ever use Firefox.
This variable will only be available in any of those, if those methods are run synchronously after some event was fired in the DOM, presumably be the user.
Since some of those are run asynchronously, this variable will/should be gone in most cases by the time they are called. It simply doesn't exist anymore in the browser.
In mounted, it may be there if the component was rendered & mounted because of a click. If it was another reason (some async code like setTimeout, oralso the initial page render) there simply is no event because no DOM event happened at that moment.
Honestly, I'm a bit flabbergasted that it is there in the watch in the beginning.
This whole approach of yours is very brittle and will certainly bring you a lot more pain.
As far as I could follow your explanations in the video, updated() only has this event because it is fired just after the component has been updated and has been inserted into the DOM - and the insertion into the DOM triggered the blur event. That's why the event is there. By chance.
So the fact that the event is not there is not because somehow update "has it" and mounted doesn'T have it, and it's not a bug in Vue - it's there "by accident", because updated ran just as the blur event fires.
And its not avaliable in mounted because the while the component was mounted, that blur event hasn't fired yet, it will fire just after mounted.
@LinusBorg appreciate the thoughtful explanation, just a couple of points
watch event undefined error.if u r still interested, here is the link to the js files only https://github.com/ctf0/vuebug/tree/master/resources/assets/js
regarding the event, i originally got the idea from (https://vuejs.org/v2/guide/components.html#Form-Input-Components-using-Custom-Events) and thought that its being registered by vue.
yes i may have misinterpreted this as a bug but there is definitely something unclear of why we are seeing this behavior.
i believe the event is available in updated(), watch & even in computed because all of them gets triggered when the property gets changed, which in our case was the @input.
at last, the reason i made this is because i wanted to keep the parent component stateless so i share it across different forms.
so i was thinking maybe i can use $children inside the parent component to extract everything i want from the child components but didnt know how to exactly use it 馃槩 or if it even offer such ability.
so in ur opinion what would be the best way to achieve that & how we can treat an input with pre-ini value same as we do with others that use v-model
To be clear, the event you are accessing has absolutely nothing to do with Vue, nor any of the lifecycle hooks or watch callbacks. Variables don't magically appear in JavaScript functions - the only special keywords available in every function are this and arguments. You just happened to be able to access event because it is exposed on window as a global variable. It's browser quirk that only exists in some browsers: they set window.event when a native DOM event is triggered. But this has nothing to do with Vue: Vue's custom event system and the browser's DOM event system are two separate concepts.
I suggest taking this discussion elsewhere since it's really about understanding JavaScript and browser event systems.
Most helpful comment
To be clear, the
eventyou are accessing has absolutely nothing to do with Vue, nor any of the lifecycle hooks or watch callbacks. Variables don't magically appear in JavaScript functions - the only special keywords available in every function arethisandarguments. You just happened to be able to accesseventbecause it is exposed onwindowas a global variable. It's browser quirk that only exists in some browsers: they setwindow.eventwhen a native DOM event is triggered. But this has nothing to do with Vue: Vue's custom event system and the browser's DOM event system are two separate concepts.I suggest taking this discussion elsewhere since it's really about understanding JavaScript and browser event systems.