在开始本文之前,建议先阅读之前的两篇文章以获得更好的理解。本文提到的源代码可以在之前的文章中找到。本文将介绍如何在Angular 2框架中创建一个嵌套组件,并从父组件向子组件传递数据。
先决条件:
开始之前
首先,复制之前文章的源代码()到一个新的文件夹中,命名为nestedComponent
。然后在nestedComponent
文件夹中重新安装npm
包,使用命令npm install
。安装完成后,文件夹结构应该如下所示:
创建嵌套组件
将从student-form
组件中移除标签,这是更新后的student-form.html
的样子:
<div>
Student First Name :-<br/>
<input [(ngModel)]="Student.FirstName" type="text"><br/>
Student Last Name :-<br/>
<input [(ngModel)]="Student.LastName" type="text"><br/>
Student Age :-<br/>
<input [(ngModel)]="Student.Age" type="text"><br/>
</div>
接下来,在app
文件夹中添加一个新的文件,命名为student-detail.component.ts
。这个文件将包含student-detail
组件的逻辑:
import { Component, Input } from '@angular/core';
@Component({
selector: 'student-detail',
templateUrl: '../view/student-detail.html'
})
export class StudentDetailComponent {
@Input() FirstName: String;
@Input() LastName: String;
@Input() Age: number;
}
在这个组件中,将从父组件传递数据以便渲染。为此,还需要导入Input
。在第4行和第5行定义了selector
和templateUrl
。为了将父组件的输入映射到Student-Detail
组件,在第9行、第10行和第11行定义了@Input()
并定义了FirstName
、LastName
和Age
。
还可以为变量和属性名设置不同的名称。要设置不同的属性名,需要在括号内定义名称,例如:@Input('first-name')
。
import { Component, Input } from '@angular/core';
@Component({
selector: 'student-detail',
templateUrl: '../view/student-detail.html'
})
export class StudentDetailComponent {
@Input('first-name') FirstName: String;
@Input('last-name') LastName: String;
@Input() Age: number;
}
类似地,也可以从父组件使用Output
来传递方法。为此,需要注入Output
和EventEmitter
依赖,然后添加一个方法来调用父组件的方法。
import { Component, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'student-detail',
templateUrl: '../view/student-detail.html'
})
export class StudentDetailComponent {
@Input('first-name') FirstName: String;
@Input('last-name') LastName: String;
@Input() Age: number;
@Output('onButtonClick') buttonClick = new EventEmitter();
onCLick() {
this.buttonClick.emit();
}
}
现在需要添加在第5行引用的HTML文件。将此文件添加到view
文件夹中,并将其命名为student-detail.html
。
<section>
<br/>
<div>
Student Details are ...
</div>
<div>
First Name : {{FirstName}}
<br/>
Last Name : {{LastName}}
<br/>
Age : {{Age}}
</div>
<button (click)="onCLick()">
Click Me
</button>
<br/>
<ng-content></ng-content>
</section>
在刚刚添加的HTML模板中,引用了student-detail.component.ts
中定义的变量(第5、6和7行)。在上面的HTML模板中突出显示了这个变量名称。在第7行,映射了onClick
方法,它将内部调用父组件映射到它的方法。
在HTML模板中,还添加了ng-content
标签。这个标签将渲染放置在student-detail
标签之间的内容。当在主组件student-form
中添加student-detail
标签时,将更多地讨论这一点。让开始在student-form
中注入新创建的组件。这是带有student-detail
标签的更新模板:
<div>
Student First Name :-<br/>
<input [(ngModel)]="Student.FirstName" type="text"><br/>
Student Last Name :-<br/>
<input [(ngModel)]="Student.LastName" type="text"><br/>
Student Age :-<br/>
<input [(ngModel)]="Student.Age" type="text"><br/>
<student-detail first-name="{{Student.FirstName}}" last-name="{{Student.LastName}}" [Age]="{{Student.Age}}" (onButtonClick)="onButtonClick()">
<div>
This is inside nested control
</div>
</student-detail>
</div>
在第5行和第6行,添加了student-detail
标签属性FirstName
、LastName
和Age
,并映射了相应的父变量。onButtonClick()
方法映射到子控件。使用了花括号来映射变量,但也可以像下面提到的那样使用方括号:
<student-detail [first-name]="Student.FirstName" [last-name]="Student.LastName" [Age]="Student.Age" (onButtonClick)="onButtonClick()">
<div>
This is inside nested control
</div>
</student-detail>
现在需要在student.component.ts
中添加onButtonClick
方法。
import { Component } from '@angular/core';
import { StudentModel } from './student.model';
@Component({
selector: 'student-form',
templateUrl: '../view/student-form.html'
})
export class StudentComponent {
Student: StudentModel = new StudentModel();
onButtonClick = function() {
alert('Hey, button was clicked in child control');
}
}
如果注意到student-detail
标签之间的div
标签,它将被传递到student-detail
组件中,并将在添加到student-detail
组件中的ng-content
标签内渲染。如果使用过Angular 1.x,这类似于ng-transclude
。
最后一步是在student.module.ts
中映射依赖。以下是更新后的student.module.ts
,已经突出显示了对文件所做的更改。
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { StudentComponent } from './student.component';
import { StudentDetailComponent } from './student-detail.component';
import { FormsModule } from '@angular/forms';
@NgModule({
imports: [ BrowserModule, FormsModule ],
declarations: [ StudentComponent, StudentDetailComponent ],
bootstrap: [ StudentComponent ]
})
export class AppModule { }
在第4行,导入了studentDetailComponent
,在第9行,将同一个对象映射到声明中。这是最终的文件夹结构:
现在打开命令提示符,导航到基础文件夹并执行npm start
。现在应该可以在默认浏览器中看到最终输出。如果在文本框中输入,相同的内容应该在嵌套组件中显示。