Vue get sender element with other parameter - vue.js

In my VueJs app i have a html part like this
<MyAwesomeComponent #change="onChangeValue" class="component" />
and in the method i have
onChangeValue: function (event)
{
//here i can access succesfully to event.sender
}
the question is: how is possibile to have custom parameter inside onChangeValue function?
i've tried to add parameter but i only get undefined and null value
any suggestion?

In your onChangeValue function, you will create an event like $emit('nameOfEvent',yourDataToPass) . nameOfEvent will be usefull to get your event in the upper component like #nameOfEvent="yourFunction($event)" . And yourDataToPass will be one of your data in DATA(){mydata;} like this.mydata

In your child component, you can call $emit('change',customArg)

Related

Vue - Emit Child to parent

In a vue2 application i need to send a value from a child to the parent. I try something like this
Child function
goTo(id: string) {
this.$emit('goToSpots', id)
},
Parent Component
<Main
class="px-5"
#goToSpots="goToSpots()"
/>
Parent function
goToSpots(id: string) {
this.selected = id
},
The problem: this.selected returns undefined, can't get param properly.
The question is: Whats is the proper way to send params?
In your HTML template, use
#goToSpots="goToSpots($event)"
or
#goToSpots="goToSpots"
instead. At the moment, you are not passing any argument to the function. If you don't add brackets at all, the parameter is automatically added and if you use brackets, you can pass the reserved variable $event which contains the emitted data.

How could the Vue app pass the additional parameters to the event listener when using vm.$once()?

In the Vue app , it could add the event listener that is called one time by using vm.$once.
For example, in the child component of Vue App, it could emit the event using vm.$emit('myEvent', data). emit event
And then it could be processed by adding the event listener to this event using vm.$once in the Vue app.
At this time, I want to pass the additional data to event handler.
I've tried as following. But it throws an error.
Uncaught ReferenceError: $event is not defined
//In the Vueapp
this.$refs.child.$once(
'myEvent', this.eventHandler($event, additional_data)
);
But I think that it could pass the additional data when using v-on.
<child-component ref="child" v-on:myEvent="eventHandler($event, additional_data)"></child-component>
//$event is the data emitted from the event , "myEvent".
When using vm.$once or vm.$on, couldn't it pass the additional parameter?
Note: the reason that I use vm.$once is that I want to execute the eventHandler only one time when emitting the custom event, myEvent and add it dynamically .
You need to capture the arguments passed into the event handler. You can do this by using an anonymous function for the handler that calls your method. For example
this.$refs.child.$once('myEvent', $event => {
this.eventHandler($event, additional_data)
})
You could also get fancy with Function.prototype.bind() however you would have to reverse the arguments list as bind prepends arguments.
For example
methods: {
eventHandler(data, $event) { // reversed argument list
// etc
}
}
and
this.$refs.child.$once('myEvent', this.eventHandler.bind(this, additional_data))

Passing a function reference through data attribute in Vue

I am trying to pass a function into recaptcha to be used as a callback. I need to write:
data-callback="function"
In Vue how do I add the function reference?
I've tried:
data-callback="{{ this.submitFocus }}"
data-callback="this.submitFocus"
I'm using Vue 2
Recaptcha2 uses the data-callback string to call a globally available function.
From what I can see in the documentation, it doesn't look like there's a programmatic way to set this so you might have to use something like this
beforeMount () {
window.submitFocus = () => { // using arrow function to preserve "this"
this.submitFocus()
}
},
beforeDestroy () {
delete window.submitFocus
}
with
data-callback="submitFocus"
in your template. The attribute value just needs to match the function added to window.
data-callback is an html attribute of a DOM element, it's just a string. It does not know about the context of your object instance, ie. this.
So, you can't use this when setting the attribute for your ReCaptcha, it will only understand functions that can be called without this.
If you had a function defined as
function submitFocus(){ ... }
globally, you could get ReCaptcha to call it by setting data-callback to submitFocus without the reference to this.
data-callback="submitFocus"

Best way of executing js function located in parent page from custom element

Aurelia: I have a custom element that should execute a function that located in the parent page. the custom element doesn't "know" what function it should execute - it depends on the parent page, and currently I send the name of the function as an attribute to the custom element (the attribute - on-focus-out-action-name):
<form-input field-name="firstName" title="First Name" on-focus-out-action-name ="validateInput()" />
I manage to run the function when it has no params, but when I want to send params (simple string type which is also sent as attribute) - no success
Is there a better way to do it ?
The best way was if I could pass the function as an object (Dependency Injection ?)
You should use the call binding command for this. The way to pass parameters to a function when using the call bind is a bit wonky, but once you understand it, it's easy.
In the custom element, you will pass an object to the bound function. Each property of this function will be matched to the named parameters in the binding. Let's look at it in action. In the page VM, I'll have a function:
pageFunction(paramOne, paramtwo) {
//.. stuff happens
}
This function will be called by a custom element. So in the page view, we will write the binding like this:
<my-element some-func.call="pageFunction(paramOne, paramTwo)"></my-element>
Inside my-element's VM, we can call the bound function, and pass the parameters to it like this:
this.someFunc({paramOne: this.someProp, paramTwo: this.otherProp});
I've created a runnable gist example here: https://gist.run/?id=864edc684eb107cdd71c58785b14d2f9
I prefer using a CustomEvent for this, this makes it clear in the template what is going on.
In your component you dispatch the event like this - the "details" can be any object/data you want:
let event = new CustomEvent('on-focus-out-action-name', {
detail: <some-data-you-want-to-send>,
bubbles: true
});
this.element.dispatchEvent(event);
You'll also need to inject the element in the constructor (you'll also need to use autoinject or inject Element manually)
constructor(private element: Element) {}
Your parent template would then look something like this:
<form-input field-name="firstName"
title="First Name"
on-focus-out-action-name.delegate="validateInput($event)" />
And in your parent component, you use the data you sent like this:
validateInput(event) {
let data = event.detail;
// do stuff
}
Check out this blog post for more details https://ilikekillnerds.com/2015/08/aurelia-custom-elements-custom-callback-events-tutorial/
I managed to do it in Aurelia: This is the custom element with the foucusout.trigger which calls to the focusoutAction in the appropriate timing:
<template>
<label>
${title} - ${fieldName}<input title.bind="title"
focusout.trigger="focusoutAction()" focusin.trigger="focusInAction()"
class="${cssClass}" />
</label>
</template>
This is the usage of the custom element in the parent view with the focusout.call attribute:
<form-input field-name="firstName" title="First Name"
place-holder="Enter first name"
on-focusout.call="validateInput(nameOfElement)" />
And this is the relevant code in the view model of the custom control:
#bindable onFocusout;
focusoutAction() {
var args =
{
nameOfElement: this.fieldName
};
this.onFocusout(args);
}

Aurelia set element on ViewModel

How would you add a component to a View from the ViewModel. For example, I have the following:
I have a service injected into a component. Then from the component I fetch data and when I get the response I set the data property to the fetched data. After this I would like to mount the component to the View with the fetched data as a bindable.
this.service.get()
.then(response => response.json())
.then(data =>{
this.data = data.results
//Mount element to View here: <component data.bind="data"></component>
})
Im asking this question because if I set the value when fetched and on the View to this:
<component data.bind="data"></component>
It passes an empty object. I have tried using the service on the canActivate and activate methods.
Component:
export class Component{
#bindable data
bind(){
console.log(this.data)
}
}
I copied your code in to a gist and ran it on gist.run here: https://gist.run/?id=04907ff8d8b6d8b4aee625669d8571a3
It runs as expected for me. I even updated it to set the data inside a promise.
Now, if you want to be notified when the data property changes, you'll need to implement a function called ${propertyName}Changed(newValue, oldValue) so in this case, dataChanged(newValue, oldValue). I created a separate gist to show how you might want to change your code: https://gist.run/?id=34a01ca3f600470691d5b91c9131f33b
You'll notice in my code I didn't use the newValue and oldValue parameters. I did this on purpose to let you know that Aurelia still sets the property value. The callback is just there to let your code do stuff when the property value changes.
The "data" field being bound to is a field on the ViewModel using your component, not a field in your component.