I was just wondering if there's any way, shape or form to reference a function that's created within ngOnInit(), or some sort of closure you can create to do so?
Basically:
component(){
somefunc()
//be able to call the function that's created in ngOnInit from the component via
//click event after the component renders
ngOnInit() {
function somefunc(){ ...whatever }
}
}
Is there any way to do this?
It can be done by assigning the method to a class member property in ngOnInit. In the code below, I define the method as an arrow function, to make sure that this refers to the instance of the component in the body of the method. See this stackblitz for a demo.
export class AppComponent implements OnInit {
public onButtonClick: (event: Event) => void; // Member property will refer to the method
ngOnInit() {
let data = "And this comes from the closure!"; // Can be used inside of onButtonClick
// Assign the method to the member property
this.onButtonClick = (event: Event): void => {
console.log("The button was clicked!", data);
...
};
}
}
The method can then be used as an event handler:
<button (click)="onButtonClick($event)">Click me!</button>
Your pseudo syntax is a bit confusing.
You can call a created function like this:
import { Component, OnInit } from '#angular/core';
#Component({
templateUrl: './product-list.component.html',
styleUrls: ['./product-list.component.css']
})
export class ProductListComponent implements OnInit {
showImage = false;
constructor() {
}
ngOnInit(): void {
this.toggleImage();
}
toggleImage(): void {
this.showImage = !this.showImage;
}
}
You can also call it from a click event on a button like this:
<button class='btn btn-primary'
(click)='toggleImage()'>
Show Image
</button>
Is this what you are asking?
Related
I want to populate the button click from interface value for example
interface IButton {
buttonClickValue: string
}
export class Button implements OnInit {
toolBar: IButton = {
buttonClickValue: "onCML" //I also tried this onCML()
}
constructor() {}
ngOnInit(): void {
}
onCML(){
alert("Alert should appear on click!!!");
}
}
Here is my frontEnd button where I would like to bind the interface value to the button click
<a class="btn btn-primary" (click)="toolBar.buttonClickValue">My Button</a>
However when I click on the button nothing happens I would like to see the alert. Thank you for your help.
The return type for buttonClickValue should match the function.
interface IButton {
buttonClickValue: () => void;
}
export class Button implements OnInit {
toolBar: IButton = {
buttonClickValue: this.onCML,
};
constructor() {}
ngOnInit(): void {}
onCML() {
alert("Alert should appear on click!!!");
}
}
Edit:
I believe you'll also need to invoke said function in the template:
<a class="btn btn-primary" (click)="toolBar.buttonClickValue()">My Button</a>
Define a callback type to the buttonClickValue property instead of string.
Assign the onCML callback using this.onCML or an arrow function. If you intend to use this keyword inside the callback to refer to class member variables, you either need to bind using this.onCML.bind(this) or use an arrow-function (Canonical answer).
import { Component, OnInit } from "#angular/core";
interface IButton {
buttonClickValue: () => void;
}
#Component({
selector: "app-button",
template: `
<a class="btn btn-primary" (click)="toolBar.buttonClickValue()">
My Button
</a>
`
})
export class ButtonComponent implements OnInit {
toolBar: IButton = {
buttonClickValue: () => this.onCML()
};
constructor() {}
ngOnInit(): void {}
onCML() {
alert("Alert should appear on click!!!");
}
}
Working example: Stackblitz
In the following code, passing in showDialogFunc doesn't work, and I cannot see it get called from the child. I'm fairly new to Angular and I guess I'm doing something, very basic, wrong.
/*
* #ngInject
*/
export default function($stateProvider: StateProvider: void {
let _showDialog = false;
$stateProvider.state('manage.user', {
url: '/manageuser',
template: '<manage-user (showDialogFunc)="showDialogFunc"></manage-user>',
reloadOnSearch: false
})
function showDialogFunc() {
this._showDialog = true;
}
}
#Component({
selector: 'manage-user',
templateUrl: 'manage-user.component.html'
})
export class ManageUserComponent implements OnInit, OnDestroy {
#Output() readonly showDialogFunc: EventEmitter<void> = new EventEmitter();
ngOnInit(): void {
if(//....) {
this.showDialogFunc.emit();
}
}
}
When you use (showDialogFun), you define an event. So your line should read like an action to perform (here a function to call) -- not like an object:
(showDialogFunc)="showDialogFunc()"
As opposed to if you want to pass a function object from a parent component to a child component where you would have:
<child-component [function_object]="showDialogFunc">...
and in the child component code:
#Input() function_object: () => number;
// ...
my_function() {
// Call the function given by the parent
this.function_object();
}
You need to execute the function
(showDialogFunc)="showDialogFunc()"
Note the () braces at the end of the function name.
How do I check if Output in Component changes? Then run another method
Here is Parent component,
After it gets data from Child, want to immediately run another event.
Parent HTML:
<div>
Address Type:*
<app-address-type-dropdown (selectedItemOutput) = "test"></app-address-type-dropdown>
</div>
Parent Typescript:
Goal: When value is outputted, detect changes in this parent, and write console command.
export class AddressFormatheaderFormComponent implements OnInit {
constructor() { }
public test: any;
public sayHi(){
console.log(this.test);
}
ngOnInit() {
}
}
You can do so by creating another function, an event handler essentially. So when your child component <app-address-type-dropdown> emits a value, this event handler will take care of what to do next.
E.g. onNewItemSelect($event) is the event handler.
<div>
Address Type:*
<app-address-type-dropdown (selectedItemOutput)="onNewItemSelect($event)"></app-address-type-dropdown>
</div>
export class AddressFormatheaderFormComponent implements OnInit {
constructor() { }
public test: any;
ngOnInit() {
}
onNewItemSelect(itemSelected){
this.test = itemSelected;
console.log(this.test);
//do something else
}
}
Do have read on this section of of Angular official docs on component interaction for more information.
I think you will need EventEmitter so in child component, when value changes, it will emit event and in parent component, it will detect changes and call parent function.
Something like let's say your child component.
import { Component, EventEmitter, Output } from '#angular/core';
#Component({
selector: 'app-address-type-dropdown,
template: `<button class='btn btn-primary' (click)="valueChanged()">Click me</button> `
})
export class AppAddressTypeDropdown{
#Output() selectedItemOutput= new EventEmitter();
Counter = 0;
valueChanged() { // You can give any function name
this.counter = this.counter + 1;
this.selectedItemOutput.emit(this.counter);
}
}
And in parent html, just try update call slightly. Please call any function to know when it changes.
<app-address-type-dropdown (selectedItemOutput) = "changeDetect($event)"></app-address-type-dropdown>
export class AddressFormatheaderFormComponent implements OnInit {
constructor() { }
public test: any;
public sayHi(){
console.log(this.test);
}
ngOnInit() {
}
changeDetect(counter){
console.log(counter);
//do something here
}
This question related to Syntactically anonymous/Arrow Function/add-hoc/factory DP functions:
I have a component which is embedded in the Html.
The component has a click event which is binded to a function. This function content depend on another component which has a reference to this component.
This is the component with the click event:
HTML:
<div (click)="doSomething()">Content.....</div> \\ Should it be with a brackets ?
In the component I just want to define the function signature:
#Component({
selector: 'app-embedded'
})
export class className
{
constructor() { }
ngOnInit() { }
doSomething:(booleanparams: boolean) => any; //The function get a boolean parameter as input and return void or any
}
Now this is where the component is embedded:
<div >
<app-embedded #emb></app-embedded>
</div>
This is the component of the container of the embedded component, which has a reference to the embedded component:
#Component({
selector: 'app-container',
})
export class container
{
#ViewChild('emb') private emb: ElementRef;
booleanParam : booelan;
constructor()
{
emb.doSomething = containerFunction(true);
}
containerFunction(booleanParam : boolean)
{
// do something in this context
}
}
The idea is that this embedded component is embedded in many other containers and whenever the click event triggered a function that was set in the doSomething function variable should be executed.
What changes in the code I need to do in order to accomplish this ?
The best way i see of doing this would be to simply use an event emitter and capture the event on the other side? so embedded would have this:
#Component({
selector: 'app-embedded'
})
export class className
{
#Output()
public something: EventEmitter<boolean> = new EventEmitter<boolean>();
constructor() { }
ngOnInit() { }
doSomething:(booleanparams: boolean) {
this.something.emit(booleanparams);
}; //The function get a boolean parameter as input and return void or any
}
Then where it is called:
<div >
<app-embedded #emb (something)="doSomething($event)"></app-embedded>
</div>
Other solution that would allow a return
#Component({
selector: 'app-embedded'
})
export class className
{
#Input()
public somethingFunc: (boolean)=>any;
constructor() { }
ngOnInit() { }
doSomething:(booleanparams: boolean) {
let w_potato = this.somethingFunc(booleanparams);
//Do whatever you want with w_potato
}; //The function get a boolean parameter as input and return void or any
}
in this case the view would be
<div >
<app-embedded #emb [somethingFunc]="doSomething"></app-embedded>
</div>
I hope this helps! Passing the function or emitting an event will be much more angular than trying to modify an instance of a component. On top of that, a constructor is only called once when Angular starts up so #emb at that time will not be defined to be anything. If you wanted to do it that way you would have to bind yourself in something ngAfterViewInit.
But again, I think that passing it through attributes will be much more angular looking.
Good Luck let me know if this doesn't suit your answer.
How can I run ngOnInit of component A when i call function of this component A?
For example :
export class CompositionComponent implements OnInit {
measure = new MeasureComponent(this.http);
constructor(private http: HttpClient) { }
myFunction(){
measure.functionMeasure();
}
//
export class MeasureComponent implements OnInit {
configCompo;
constructor(private http: HttpClient) { }
ngOnInit() {
this.getConfigCompo().subscribe(data => {
this.configCompo = JSON.parse(data);
});
functionMeasure(){
console.log(this.configCompo)
}
but actualy, this.configCompo is not initialized when I call this function from Composition Component, because it is initialized in ngOnInit()
Even it sounds weird on your requirement as ngOnInit should be called automatically when a component get initialized. But if you still want, there're 3 other ways:
call measure.ngOnInit() to init measure after it is created
add ngOnInit call to myFunction in MeasureComponent this.ngOnInit()
or add ngOnInit to MeasureComponent constructor this.ngOnInit()
And keep in mind that this.getConfigCompo().subscribe(...) is an asynchronous function, so you can't get the value right after it is called. You can get it in the callback function only