Pass values to child component Angular 7

12,909

When you write a child component in Angular 7, that updates its content whenever input changes. So, you can add all necessary computations to the ngOnChanges lifecycle hook. ngOnInit called once only.

Please add the following code to list.item-view.component.ts

  ngOnChanges() {
    this.school = this.schoolObject;
  }

Good Luck!

Share:
12,909
Robert Nish
Author by

Robert Nish

Updated on June 27, 2022

Comments

  • Robert Nish
    Robert Nish almost 2 years

    I went though this, and understand that after declaring a data-bound input property, Angular should automatically update the input value. In the component I created, it doesn't seems like that.

    When I click on a item on the grid on the parent it shows me the details properly. When I click on another item after that, it doesn't update the child component. I have put a console.log to monitor the selected record. It keeps changing according to the user selection.

    Can you please have a look and help me to understand where the issue is?

    lists.component.html [Parent]

    <div class="container-fluid">
      <div class="row mt-2 mb-2">
        <div class="col-8">
          <app-list-item-add *ngIf="showAddnewScreen" (notifyParentOnUpdate)='onAddItem($event)'></app-list-item-add>
          <app-list-item-view *ngIf="showViewScreen" [studentObject]="selectedstudent" (notifyParentOnUpdate)='onViewItem($event)'></app-list-item-view>
        </div>
      </div>
    </div>
    

    lists.component.ts [Parent]

    import { Component, OnInit, ViewChild } from '@angular/core';
    import { studentsService, student } from '../services/students.service';
    import { Router, ActivatedRoute } from '@angular/router';
    import { GridComponent, ToolbarItems, SortEventArgs, RowSelectEventArgs, SelectionSettingsModel } from '@syncfusion/ej2-ng-grids';
    import { ClickEventArgs } from '@syncfusion/ej2-ng-navigations';
    import * as moment from 'moment';
    import { Internationalization } from '@syncfusion/ej2-base';
    
    @Component({
      selector: 'app-lists',
      templateUrl: './lists.component.html',
      styleUrls: ['./lists.component.scss']
    })
    export class ListsComponent implements OnInit {
    
      constructor(public router: Router, private route: ActivatedRoute, private studentsService: studentsService) { }
      selectedstudent: student = null;
      students: student[] = new Array<student>();
      intl: Internationalization = new Internationalization();
      showAddnewScreen = false;
      showViewScreen = false;
    
      // Syncfusion GRID settings for the students grid.
      // Documentation: https://ej2.syncfusion.com/16.1.32/angular/documentation/grid/getting-started.html
      studentsGridId = 'studentsGrid';
      @ViewChild('studentsGrid')
      studentsGrid: GridComponent;
      toolbar: ToolbarItems[];
    
      // https://ej2.syncfusion.com/16.1.32/angular/documentation/grid/api-filterSettings.html
      studentsFilteringSettings = {
      };
    
      // https://ej2.syncfusion.com/16.1.32/angular/documentation/grid/api-pageSettings.html
      studentsPageSettings = {
        currentPage: 1,
        enableQueryString: true,
        pageSizes: [10, 25, 50, 100],
        pageSize: 10
      };
    
      // https://ej2.syncfusion.com/16.1.32/angular/documentation/grid/api-selectionSettings.html
      studentsSelectionOptions: SelectionSettingsModel;
    
      studentsToolbarClick(args: ClickEventArgs) {
        // handles multiple grids on the page by prepending the Grid ID to the _eventname
        // E.g.
        // if (args.item.id == studentsGrid_excelexport)....
        if (args.item.id === (this.studentsGridId + '_excelexport')) {
          this.studentsGrid.excelExport();
        }
        if (args.item.id === (this.studentsGridId + '_pdfexport')) {
          this.studentsGrid.pdfExport();
        }
      }
    
      studentsRowSelected(args: RowSelectEventArgs) {
        const selectedrowindex: number[] = this.studentsGrid.getSelectedRowIndexes();  // Get the selected row indexes.
        console.log(selectedrowindex);
        const selectedRecords: student[] = this.studentsGrid.getSelectedRecords() as student[];  // Get the selected records.
        const selectedRecord = selectedRecords[0];
        if (selectedRecord) {
        }
      }
    
      gridActionHandler(args: SortEventArgs) {
        console.log(args.requestType + ' ' + args.type);
      }
    
      ngOnInit() {
        this.toolbar = ['Print', 'Search', 'ExcelExport', 'PdfExport'];
        this.studentsSelectionOptions = {
          type: 'Single',
          mode: 'Row'
        };
    
        this.studentsService.getstudents(1000).subscribe((students) => {
          this.students = students;
          this.students.sort(this.sortBystudentNumber);
          this.studentsGrid.dataSource = this.students;
        });
    
        // Listen for changes to list items
        this.studentsService.studentAdded$.subscribe(student => {
          // convert the students date strings into dates
          student.createdOn = moment(student.createdOn).toDate();
          student.modifiedOn = moment(student.modifiedOn).toDate();
          // Add the new student to the list
          this.students.push(student);
          // resort the grid data
          this.students.sort(this.sortBystudentNumber);
          // refresh the grid
          this.studentsGrid.refresh();
        });
        this.studentsService.studentChanged$.subscribe(student => {
          // convert the students date strings into dates
          student.createdOn = moment(student.createdOn).toDate();
          student.modifiedOn = moment(student.modifiedOn).toDate();
          // Update the student in the list.
          this.students.splice(this.students.findIndex(s => s.id === student.id), 1, student);
          // resort the grid data
          this.students.sort(this.sortBystudentNumber);
          // refresh the grid
          this.studentsGrid.refresh();
        });
        this.studentsService.studentDeleted$.subscribe(id => {
          // Remove the student from the list
          this.students.splice(this.students.findIndex(s => s.id === id), 1);
          // resort the grid data
          this.students.sort(this.sortBystudentNumber);
          // refresh the grid
          this.studentsGrid.refresh();
        });
    
      }
    
      addNew() {
        this.showAddnewScreen = true;
        this.showViewScreen = false;
      }
    
      viewstudent(data: student) {
        console.log(data);
        this.selectedstudent = data;
        this.showViewScreen = true;
        this.showAddnewScreen = false;
      }
    
      onAddItem(student: student): void {
        this.showAddnewScreen = false;
      }
    
      onViewItem(command: string) {
        this.showViewScreen = false;
    
        if (command === 'cancel') {
        } else if (command === 'save') {
        } else if (command === 'delete') {
        }
      }
    
      sortBystudentNumber = (s1, s2) => s1.studentNumber - s2.studentNumber;
    }
    

    list-item-view.component.html [Child]

    <div class="row">
      <div class="col-12">
        <section class="studentDetails">
          <app-section-title heading="student Details" level="4"></app-section-title>
    
          <form #studentForm="ngForm" class="pt-2">
            <div class="row">
              <div class="col-10">
    
                <div class="form-group">
                  <div class="row">
                    <div class="col-4">
                      <span>student number</span>
                    </div>
                    <div class="col-6">
                      <input type="text" class="form-control" aria-label="student number"
                             [(ngModel)]="student.studentNumber" name="student Number" />
                    </div>
                  </div>
                </div>
    
                <div class="form-group">
                  <div class="row">
                    <div class="col-4">
                      <span>student name</span>
                    </div>
                    <div class="col-6">
                      <input type="text" class="form-control" aria-label="student name"
                             [(ngModel)]="student.studentName" name="student Name" />
                    </div>
                  </div>
                </div>
    
                <div class="form-group">
                  <div class="row">
                    <div class="col-4">
                      <span>student description</span>
                    </div>
                    <div class="col-6">
                      <input type="text" class="form-control" aria-label="student description"
                             [(ngModel)]="student.description" name="Description" />
                    </div>
                  </div>
                </div>
    
                <div class="form-group">
                  <div class="row">
                    <div class="col-4">
                      <span>Created date</span>
                    </div>
                    <div class="col-6">   
                      <ejs-datepicker placeholder='Enter date' format="dd-MM-yyyyy" aria-label="Created date" [readonly]="true"
                                      [(ngModel)]="student.createdOn" name="Created On"></ejs-datepicker>
                      <label class="col-8 col-lg-9 col-form-label">({{student.createdOn | timeago}})</label>
                    </div>
                  </div>
                </div>
    
                <div class="form-group">
                  <div class="row">
                    <div class="col-4">
                      <span>Created by</span>
                    </div>
                    <div class="col-6">
                      <input type="text" class="form-control" aria-label="Created by" [readonly]="true"
                             [(ngModel)]="student.createdBy" name="Created By" />
                    </div>
                  </div>
                </div>
    
                <div class="form-group">
                  <div class="row">
                    <div class="col-4">
                      <span>Modified date</span>
                    </div>
                    <div class="col-6">
                      <ejs-datepicker placeholder='Enter date' format="dd-MM-yyyyy" aria-label="Modified date"
                                      [(ngModel)]="student.modifiedOn" name="Modified On"></ejs-datepicker>
                      <label *ngIf="student.modifiedOn" class="col-8 col-lg-9 col-form-label">({{student.modifiedOn | timeago}})</label>
                    </div>
                  </div>
                </div>
    
                <div class="form-group">
                  <div class="row">
                    <div class="col-4">
                      <span>Modified by</span>
                    </div>
                    <div class="col-6">
                      <input type="text" class="form-control" aria-label="Modified by"
                             [(ngModel)]="student.modifiedBy" name="Modified By" />
                    </div>
                  </div>
                </div>
    
              </div>
            </div>
          </form>
        </section>
      </div>
    </div>
    

    list-item-view.component.ts [Child]

    import { Component, OnInit, ViewChild, EventEmitter, Output, Input } from '@angular/core';
    import { studentsService, student } from '../services/students.service';
    import { ActivatedRoute } from '@angular/router';
    import { DatePicker } from '@syncfusion/ej2-calendars';
    import * as moment from 'moment';
    import { NgForm } from '@angular/forms';
    
    @Component({
      selector: 'app-list-item-view',
      templateUrl: './list-item-view.component.html',
      styleUrls: ['./list-item-view.component.scss']
    })
    
    export class ListItemViewComponent implements OnInit {
      @Output() notifyParentOnUpdate: EventEmitter<any> = new EventEmitter<any>();
      @Input() studentObject: student;
    
      studentNumber: number;
    
      constructor(private route: ActivatedRoute, private studentsService: studentsService) { }
    
      @ViewChild(NgForm) studentForm: NgForm;
    
      public student = new student();
    
      ngOnInit() {
        this.student = this.studentObject;
      }
    
      save() {
        this.studentsService.updatestudent(this.student).subscribe(newstudent => {
          this.notifyParentOnUpdate.emit('save');
        });
    
      }
    
      delete() {
        this.studentsService.deletestudent(this.student.id).subscribe(newstudent => {
          this.notifyParentOnUpdate.emit('delete');
        });
      }
    
      editOnBlur() {
        this.notifyParentOnUpdate.emit('editOnBlur');
      }
    
      cancel() {
        this.notifyParentOnUpdate.emit('cancel');
      }
    }
    
    
  • Robert Nish
    Robert Nish over 5 years
    I am sorry, this solution did not work for me. Thank you
  • Kushan Randima
    Kushan Randima over 5 years
    @alchi, Your concept is correct. Robert needs to set the school object every time the schoolObject gets a new Input.
  • alchi baucha
    alchi baucha over 5 years
    I wonder why it didn't work. Every time the input's value is changed, the new value is passed to the SchoolObject's setter.