0

So I have two components the add-contact-component (child component) and the contact-manager-component(parent component) How can I use output and event emitter for my object array to be pass from child to parent component whenever I press the update button? Also is there a way for the create button to be changed to update button whenever I click the edit button on the parent component?

Contact App

Child Component

import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { MyContact } from '../models/myContact';
import { ContactService } from '../services/contact.service';

@Component({
  selector: 'app-add-contact',
  templateUrl: './add-contact.component.html',
  styleUrls: ['./add-contact.component.css']
})

export class AddContactComponent implements OnInit {
  public loading:boolean = false;
  @Input() contact:MyContact = {} as MyContact;
  @Output() contactChange:EventEmitter<MyContact> =new EventEmitter<MyContact>();

 
  public editMode:boolean = false;
  

  constructor(private contService:ContactService, private router:Router) { }

  ngOnInit(): void {}
   
  onSubmit(contactForm: { value: any; }) {
    this.contService.CreateContacts(this.contact).subscribe((data:MyContact)=>{
      this.router.navigate(['/']).then(()=>{
        window.location.reload();
      });       
 
  }
  
  update() {
  this.contactChange.emit(this.contact);
 }


 
}
<div class="container">
    <div class="row">
        <div class="col-sm-4">
            <form (ngSubmit)="onSubmit(contactForm)" #contactForm="ngForm" novalidate #contactChange>
                <div class="mb-2">
                    <input required [(ngModel)]="contact.name" name="name" type="text" class="form-control" placeholder="Name (required)" #name="ngModel" spellcheck="false">
                </div>
                <div *ngIf="!name?.valid && (name?.dirty || name?.touched)">Name Required</div>
                <div class="mb-2">
                    <input required email [(ngModel)]="contact.email" name="email" type="email" class="form-control" placeholder="Email (required)" #email="ngModel" spellcheck="false">
                </div>
                <div *ngIf="!email?.valid && (email?.dirty || email?.touched)">Email Not Valid</div>
                <div class="mb-2">
                    <input required [(ngModel)]="contact.mobile" name="mobile" type="number" class="form-control" placeholder="Mobile (required)" #mobile="ngModel" spellcheck="false">
                </div>
                <div *ngIf="!mobile?.valid && (mobile?.dirty || mobile?.touched)">Mobile Required</div>
                <div class="mb-2">
                    <input [(ngModel)]="contact.company" name="company" type="text" class="form-control" placeholder="Company (optional)" spellcheck="false">
                </div>
                <div class="mb-2">
                    <input [(ngModel)]="contact.title" name="title" type="text" class="form-control" placeholder="Title (optional)" spellcheck="false">
                </div>
                <div class="mb-2">
                    <input [(ngModel)]="contact.photo" name="photo" type="text" class="form-control" placeholder="Photo Url (optional)" spellcheck="false">
                </div>
                <div class="mb-2">
                    <button type="submit" class="btn btn-success" [disabled]="!contactForm.valid">Create</button>
                </div>
                <div class="mb-2">
                    <button (click)="update()" class="btn btn-primary" >Update</button>
                </div>
            </form>
        </div>
    </div>
</div>

Parent Component

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { MyContact } from '../models/myContact';
import { ContactService } from '../services/contact.service';

@Component({
  selector: 'app-contact-manager',
  templateUrl: './contact-manager.component.html',
  styleUrls: ['./contact-manager.component.css']
})
export class ContactManagerComponent implements OnInit {
  public loading:boolean = false;
  public contacts:MyContact[] = [];
  public contactId:string | null = null;

  selectedContact:MyContact = new MyContact();

  constructor(private contService:ContactService, private router:Router, private activatedRoute:ActivatedRoute) { }

  ngOnInit(): void {
    this.getAllContactData(); 
  }

  getAllContactData(){
    this.loading = true;
    this.contService.getAllContacts().subscribe((data:MyContact[])=>{
      this.contacts = data;
      this.loading = false;
    })
  }
  deleteContact(contactId:string | undefined){
    if(contactId){
      this.contService.deleteContacts(contactId).subscribe((data:{})=>{
        this.getAllContactData();        
      });
    }
  }

 showDetails(contact:MyContact) {
  this.selectedContact=Object.assign({},contact)
  this.isupdate = true;
  console.log(this.isupdate);
  console.log(this.selectedContact);
}

update(contact: MyContact) {
*INSERT FUNCTION HERE FOR contact to be send to the array object MyContact in parent component*
}

}
<app-add-contact [contact]="selectedContact" (contactChange)="update($event)" *ngIf="visible "></app-add-contact>

<div class="container mt-3">
   
    <h2>Contact List</h2>
     
    <table class="table table-bordered border-secondary border-5 table-light table-hover">
      <thead class="table table-bordered table-dark">
          <tr>
            <th>#</th>
            <th>Id</th>
            <th>Name</th>
            <th>Email</th>
            <th>Contact</th>
            <th>Action</th>
          </tr>
      </thead>
      <tbody>
        <tr *ngFor="let contact of contacts ; let i = index">
          <td>{{ i + 1 }}</td>
          <td>{{ contact.id }}</td>
          <td>{{ contact.name }}</td>
          <td>{{ contact.email }}</td>
          <td>{{ contact.mobile }}</td>
          <td><div class="d-flex align-items- justify-content-around">
            <a routerLink="/contacts/view/{{contact.id}}" class="btn btn-warning my-1" data-toggle="tooltip" data-placement="top" title="View Contact Details">
                <i class="fa fa-eye"></i>
            </a>
            <button class="btn btn-primary my-1" data-toggle="tooltip" data-placement="top" title="Edit Contact" (click)="showDetails(contact)">Edit</button>
            <a routerLink="/contacts/edit/{{contact.id}}" class="btn btn-primary my-1" data-toggle="tooltip" data-placement="top" title="Edit Contact">
                <i class="fa fa-pen"></i>
            </a>
            <button class="btn btn-danger my-1" data-toggle="tooltip" data-placement="top" title="Delete Contact" (click)="deleteContact(contact.id)">
                <i class="fa fa-trash"></i>
            </button>
        </div></td>
        </tr>
      </tbody>
    </table>
  </div>

I've been stuck on this one for a few days already.

Tried to follow this tutorial still to no avail. Kept getting errors and data not reflecting. Angular @input, @output & EventEmitter

1 Answer 1

1

You are missing handling the output from the child component into the parent one.

In your parent template HTML, you probably have the child component, and you are passing down the contact @Input:

<app-add-contact [contact]="theContactYouWanToPass"></app-add-contact>

Since your child component is emitting an event when updating the contact, you need to specify that event in your parent component, so it can listen to that particular event:

<app-add-contact 
  [contact]="theContactYouWanToPass"
  (contactChange)="update($event)">
</app-add-contact>

The name for that event has to be the same as the one declared in your child component.

I've been stuck on this one for a few days already.

I recommend reading the official docs from Angular website

Sign up to request clarification or add additional context in comments.

1 Comment

Yep I somehow made it work. Thanks. Follow up question though when I pass the update contact to the parent component it is not saving on my fake json database. Though it's reflecting it will be removed when I refresh the browser. update(contact: MyContact) { this.contacts = this.contacts.map(cont => { if(contact.id === cont.id) { return contact; } return cont; })

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.