Передать значения дочернему компоненту Angular 7 - PullRequest
0 голосов
/ 16 января 2019

Я прошел через это и понял, что после объявления свойства ввода с привязкой к данным Angular должен автоматически обновить значение ввода. В компоненте, который я создал, это не так.

Когда я нажимаю на элемент в сетке на родительском элементе, он правильно показывает мне детали. Когда я нажимаю на другой элемент после этого, он не обновляет дочерний компонент. Я поставил console.log для мониторинга выбранной записи. Он постоянно меняется в зависимости от выбора пользователя.

Не могли бы вы взглянуть и помочь мне понять, в чем проблема?

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');
  }
}

Ответы [ 2 ]

0 голосов
/ 16 января 2019

Когда вы пишете дочерний компонент в Angular 7, он обновляет его содержимое при каждом изменении ввода.Таким образом, вы можете добавить все необходимые вычисления в хук жизненного цикла ngOnChanges.ngOnInit вызывается только один раз.

Пожалуйста, добавьте следующий код в list.item-view.component.ts

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

Удачи!

0 голосов
/ 16 января 2019

Я думаю, что происходит: вы получаете информацию о школе в «schoolObject». Но то, что вы связываете свои значения в html-файле, это свойства объекта 'school'. А в текущей версии вашего ts-файла я вижу, что школьный объект устанавливается только один раз в ngOnInit (без учета инициализации).

Я думаю, вам нужно устанавливать школьный объект каждый раз, когда школьный объект получает новый вход. Тогда все будет нормально. Вот что вы можете сделать:

schoolObject: School;
@Input()
set SchoolObject(schoolObj){
    this.schoolObject = schoolObj;
    this.school = schoolObj;
}

Вам нужно будет обновить html, чтобы получить значения с использованием SchoolObject для вашего родителя как:

<app-list-item-view *ngIf="showViewScreen" [SchoolObject]="selectedSchool" (notifyParentOnUpdate)='onViewItem($event)'></app-list-item-view>
...