I've this parent-child components in Angular and I'm trying to pass an object from the child component to the parent in order to update a value from the parent's object array. I've been followint the angular documentation example but seems like it's not sending the new object to the paren component but it's not showing any error neither the console or the VSC terminal.
This is the angular guide I followed: https://angular.io/guide/inputs-outputs#sending-data-to-a-parent-component
Parent view:
<h1>Customers list</h1>
<mat-list>
<a mat-list-item *ngFor="let customr of customers" [routerLink]="[customr.id, {name: customr.name}]">{{ customr.name }}</a>
</mat-list>
<router-outlet (newItemEvent)="addItem($event)"></router-outlet>
Parent controller:
import { Component, OnInit, Output } from '@angular/core';
@Component({
selector: 'app-customer-list',
templateUrl: './customer-list.component.html',
styleUrls: ['./customer-list.component.scss']
})
export class CustomerListComponent implements OnInit {
// list = [
// { id: 1, name: 'John Smith' },
// { id: 2, name: 'Anna Highland' },
// { id: 3, name: 'Emilie Poiret' }
// ];
customers: Array<Object> = [
{
id: 1,
name: 'John Smith'
},
{
id: 2,
name: 'Anna Highland'
},
{
id: 3,
name: 'Emilie Poiret'
}
];
addItem(customer){
console.log(`add customer ${customer}`);
}
constructor() { }
updateCustomer(data){
console.log(data);
}
ngOnInit(): void {
}
}
Child view:
<p>{{ name }}</p>
<form [formGroup]="formGroup" (ngSubmit)='addNewItem()'>
<mat-form-field>
<mat-label>Customer name:</mat-label>
<input matInput name="customerName" formControlName="customerName">
</mat-form-field>
<button mat-raised-button type="submit">Action</button>
</form>
Child controller:
import { ActivatedRoute, Params } from '@angular/router';
import { Component, Input, OnInit } from '@angular/core';
import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-customer-detail',
templateUrl: './customer-detail.component.html',
styleUrls: ['./customer-detail.component.scss']
})
export class CustomerDetailComponent implements OnInit {
// https://angular.io/guide/inputs-outputs#sending-data-to-a-parent-component
@Output() newItemEvent = new EventEmitter<object>();
formGroup: FormGroup;
id: string;
name: string;
addNewItem(){
// console.log(`emit runs ${value}`);
let id: any = this.id;
let name = this.formGroup.value.customerName;
console.log(`id: ${this.id} i name: ${this.formGroup.value.customerName}`);
let customer = {
'id': this.id,
'name': this.formGroup.value.customerName
};
console.warn(customer);
this.newItemEvent.emit(customer);
}
constructor(private fb: FormBuilder, private routes: ActivatedRoute) { }
ngOnInit(): void {
this.routes.params.subscribe(
(params: Params) => {
this.id = params.id;
this.name = params.name;
}
);
console.log(`ngOnInit ${this.name}`);
this.buildForm();
}
private buildForm(): void {
console.log(`buildForm ${this.name}`);
this.formGroup = this.fb.group({
customerName: [this.name, Validators.required]
});
}
public saveEdit() {
console.log(`Save edit`);
return { 'id': this.formGroup.value.customerId, 'name': this.formGroup.value.customerName };
}
}
When I click on the button I se the console.log that the addNewItem it's executing but on the addItem on the parent component function I don't see the console.log, the goal is to pass the id and customer's name so I can update the customers array with the customer's new information
The router outlet component is just a marker that is used by the angular router in order to know where to place the components being rendered for the different routes. Placing an event listener on this component will result in nothing since it's not the actual route component.
You could use a service
or do something like this:
export class AppComponent {
@ViewChild(RouterOutlet) outlet: RouterOutlet;
constructor(router: Router) {
router.events.pipe(filter(e => e instanceof NavigationEnd)).subscribe(() => {
const c = this.outlet.component;
});
}
}
Query the router outlet component
Listen for the navigation end event in order to get notified whenever the component for the route has changed.
Get the current component instance and do something on it. In your case you will have an event emitter and you can subscribe for the event.
Here I'm assuming that this will be used in the AppComponent and I haven't unsubscribed but if you attend to use it in an inner component where you have a named outlet and the component might get destroyed at some time, make sure that you unsubscribe from the stream in order to prevent memory leaks.