typescript 将值传递给子组件 Angular 7
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/54208454/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Pass values to child component Angular 7
提问by Robert Nish
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.
我经历了这个,并明白在声明数据绑定输入属性后,Angular 应该自动更新输入值。在我创建的组件中,它似乎不是这样。
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.
当我单击父级网格上的项目时,它会正确显示详细信息。当我在那之后单击另一个项目时,它不会更新子组件。我已经放置了一个 console.log 来监控选定的记录。它会根据用户的选择不断变化。
Can you please have a look and help me to understand where the issue is?
您能看一下并帮助我了解问题出在哪里吗?
lists.component.html [Parent]
list.component.html [父]
<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]
list.component.ts [父级]
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]
list-item-view.component.html [子项]
<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]
list-item-view.component.ts [子项]
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');
}
}
回答by Kushan Randima
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.
当您在 Angular 7 中编写子组件时,它会在输入更改时更新其内容。因此,您可以将所有必要的计算添加到ngOnChanges
生命周期挂钩。ngOnInit
只调用一次。
Please add the following code to list.item-view.component.ts
请将以下代码添加到 list.item-view.component.ts
ngOnChanges() {
this.school = this.schoolObject;
}
Good Luck!
祝你好运!
回答by alchi baucha
I think what's happening is: you are getting the school information on the 'schoolObject'. But what you are binding your values on the html file are 'school' object's properties. And on the current version of your ts file, I see that the school object is set only once on ngOnInit (disregarding the initialization).
我认为正在发生的事情是:您正在获取有关“schoolObject”的学校信息。但是您在 html 文件上绑定的值是“学校”对象的属性。在当前版本的 ts 文件中,我看到学校对象仅在 ngOnInit 上设置了一次(不考虑初始化)。
I think you need to set the school object every time the schoolObject gets a new Input. Then it will run fine. This is what you can do:
我认为每次 schoolObject 获得新输入时都需要设置 school 对象。然后它会运行良好。这是你可以做的:
schoolObject: School;
@Input()
set SchoolObject(schoolObj){
this.schoolObject = schoolObj;
this.school = schoolObj;
}
You will need to update the html to get the values using SchoolObject on your parent as:
您将需要更新 html 以在您的父级上使用 SchoolObject 获取值:
<app-list-item-view *ngIf="showViewScreen" [SchoolObject]="selectedSchool" (notifyParentOnUpdate)='onViewItem($event)'></app-list-item-view>