У меня есть компоненты Angular, и первый компонент использует второй как директиву. Они должны использовать один и тот же объект модели, который инициализируется в первом компоненте. Как я могу передать эту модель второму компоненту?
Как передать объект из одного компонента в другой в Angular 2?
Ответы (5)
Компонент 2, компонент директивы может определять свойство ввода (аннотация @input
в Typescript). И Компонент 1 может передать это свойство директивному компоненту из шаблона.
См. этот ответ SO ">Как сделать взаимодействие между основным и подробным компонентом в Angular2?
и как ввод передается дочерним компонентам. В вашем случае это директива.
Для односторонней привязки данных от родителя к дочернему используйте декоратор @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 — Angular RC.2
вы также можете хранить свои данные в службе с сеттером и получать их через геттер
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;
}
}
Используйте выходную аннотацию
@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);
Из компонента
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
}
}