我有Angular 组件,第一个组件使用第二个组件作为指令。它们应该共享相同的模型对象,该对象在第一个组件中初始化。如何将该模型传递给第二个组件?
5 回答
对于从父组件到子组件的单向数据绑定,使用@Input
装饰器(按照样式指南的建议)在子组件上指定输入属性
@Input() model: any; // instead of any, specify your type
并在父模板中使用模板属性绑定
<child [model]="parentModel"></child>
由于您正在传递一个对象(JavaScript 引用类型),因此您对父组件或子组件中的对象属性所做的任何更改都将反映在另一个组件中,因为两个组件都引用了同一个对象。我在Plunker中展示了这一点。
如果在父组件中重新分配对象
this.model = someNewModel;
Angular 会将新对象引用传播到子组件(自动地,作为更改检测的一部分)。
您唯一不应该做的就是在子组件中重新分配对象。如果这样做,父对象仍将引用原始对象。(如果您确实需要双向数据绑定,请参阅https://stackoverflow.com/a/34616530/215945)。
@Component({
selector: 'child',
template: `<h3>child</h3>
<div>{{model.prop1}}</div>
<button (click)="updateModel()">update model</button>`
})
class Child {
@Input() model: any; // instead of any, specify your type
updateModel() {
this.model.prop1 += ' child';
}
}
@Component({
selector: 'my-app',
directives: [Child],
template: `
<h3>Parent</h3>
<div>{{parentModel.prop1}}</div>
<button (click)="updateModel()">update model</button>
<child [model]="parentModel"></child>`
})
export class AppComponent {
parentModel = { prop1: '1st prop', prop2: '2nd prop' };
constructor() {}
updateModel() { this.parentModel.prop1 += ' parent'; }
}
Plunker- 角RC.2
组件 2,指令组件可以定义一个输入属性(@input
Typescript 中的注解)。组件 1 可以将该属性从模板传递给指令组件。
请参阅此 SO 答案How to do inter communication between a master and detail component in Angular2?
以及如何将输入传递给子组件。在您的情况下,它是指令性的。
您还可以使用 setter 将数据存储在服务中并通过 getter 获取
import { Injectable } from '@angular/core';
@Injectable()
export class StorageService {
public scope: Array<any> | boolean = false;
constructor() {
}
public getScope(): Array<any> | boolean {
return this.scope;
}
public setScope(scope: any): void {
this.scope = scope;
}
}
从组件
import { Component, OnInit, ViewChild} from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { dataService } from "src/app/service/data.service";
@Component( {
selector: 'app-sideWidget',
templateUrl: './sideWidget.html',
styleUrls: ['./linked-widget.component.css']
} )
export class sideWidget{
TableColumnNames: object[];
SelectedtableName: string = "patient";
constructor( private LWTableColumnNames: dataService ) {
}
ngOnInit() {
this.http.post( 'getColumns', this.SelectedtableName )
.subscribe(
( data: object[] ) => {
this.TableColumnNames = data;
this.LWTableColumnNames.refLWTableColumnNames = this.TableColumnNames; //this line of code will pass the value through data service
} );
}
}
数据服务
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
@Injectable()
export class dataService {
refLWTableColumnNames: object;//creating an object for the data
}
到组件
import { Component, OnInit } from '@angular/core';
import { dataService } from "src/app/service/data.service";
@Component( {
selector: 'app-linked-widget',
templateUrl: './linked-widget.component.html',
styleUrls: ['./linked-widget.component.css']
} )
export class LinkedWidgetComponent implements OnInit {
constructor(private LWTableColumnNames: dataService) { }
ngOnInit() {
console.log(this.LWTableColumnNames.refLWTableColumnNames);
}
createTable(){
console.log(this.LWTableColumnNames.refLWTableColumnNames);// calling the object from another component
}
}
使用输出注释
@Directive({
selector: 'interval-dir',
})
class IntervalDir {
@Output() everySecond = new EventEmitter();
@Output('everyFiveSeconds') five5Secs = new EventEmitter();
constructor() {
setInterval(() => this.everySecond.emit("event"), 1000);
setInterval(() => this.five5Secs.emit("event"), 5000);
}
}
@Component({
selector: 'app',
template: `
<interval-dir (everySecond)="everySecond()" (everyFiveSeconds)="everyFiveSeconds()">
</interval-dir>
`,
directives: [IntervalDir]
})
class App {
everySecond() { console.log('second'); }
everyFiveSeconds() { console.log('five seconds'); }
}
bootstrap(App);