Как я могу обмениваться данными между компонентами в Angular 2?
В Угловой 1.x.x вы просто просите одну и ту же службу, и вы получаете один и тот же экземпляр, что позволяет обмениваться данными в службе.
теперь в Angular 2 у меня есть компонент, который имеет ссылку на мой сервис. Я могу читать и изменять данные в Службе, что хорошо. Когда я пытаюсь внедрить ту же службу в другой компонент, кажется, что я получаю новый экземпляр.
что я делаю не так? Это сам шаблон, который является неправильным (с помощью сервис для обмена данными) или мне нужно пометить сервис как синглтон (в одном экземпляре приложения) или что-то еще?
Я 2.0.0-alpha.27/ кстати
Я впрыскиваю услугу через appInjector (edit: now providers) в @Component аннотация, а затем сохраните ссылку в конструкторе. Он работает локально в компоненте-просто не между компонентами (они не используют один и тот же экземпляр службы), как я думал.
обновление: по состоянию на угловой 2.0.0 теперь у нас есть @ngModule, где вы бы определили сервис под providers собственность на указанный @ngModule. Это гарантирует, что один и тот же экземпляр этой службы будет передан каждому компоненту, службе и т. д. в этом модуле.
https://angular.io/docs/ts/latest/guide/ngmodule.html#providers
5 ответов:
сервис синглтон является хорошим решением. Другой способ -
data/events bindings.вот пример:
class BazService{ n: number = 0; inc(){ this.n++; } } @Component({ selector: 'foo' }) @View({ template: `<button (click)="foobaz.inc()">Foo {{ foobaz.n }}</button>` }) class FooComponent{ constructor(foobaz: BazService){ this.foobaz = foobaz; } } @Component({ selector: 'bar', properties: ['prop'] }) @View({ template: `<button (click)="barbaz.inc()">Bar {{ barbaz.n }}, Foo {{ prop.foobaz.n }}</button>` }) class BarComponent{ constructor(barbaz: BazService){ this.barbaz = barbaz; } } @Component({ selector: 'app', viewInjector: [BazService] }) @View({ template: ` <foo #f></foo> <bar [prop]="f"></bar> `, directives: [FooComponent, BarComponent] }) class AppComponent{} bootstrap(AppComponent);
комментарий @maufarinelli заслуживает своего собственного ответа, потому что до тех пор, пока я его не увидел, я все еще бил головой об стену с этим вопросом даже с ответом @Alexander Ermolov.
проблема в том, что при добавлении
providersнаcomponent:@Component({ selector: 'my-selector', providers: [MyService], template: `<div>stuff</div>` })это приводит к введению нового экземпляра службы... вместо синглтон.
так что удалите все экземпляры вашего
providers: [MyService]в приложения кроме как вmodule, и он будет работать!
вы должны использовать входы и выходы @ Component decorator. Вот самый простой пример использования обоих;
import { bootstrap } from 'angular2/platform/browser'; import { Component, EventEmitter } from 'angular2/core'; import { NgFor } from 'angular2/common'; @Component({ selector: 'sub-component', inputs: ['items'], outputs: ['onItemSelected'], directives: [NgFor], template: ` <div class="item" *ngFor="#item of items; #i = index"> <span>{{ item }}</span> <button type="button" (click)="select(i)">Select</button> </div> ` }) class SubComponent { onItemSelected: EventEmitter<string>; items: string[]; constructor() { this.onItemSelected = new EventEmitter(); } select(i) { this.onItemSelected.emit(this.items[i]); } } @Component({ selector: 'app', directives: [SubComponent], template: ` <div> <sub-component [items]="items" (onItemSelected)="itemSelected($event)"> </sub-component> </div> ` }) class App { items: string[]; constructor() { this.items = ['item1', 'item2', 'item3']; } itemSelected(item: string): void { console.log('Selected item:', item); } } bootstrap(App);
в шаблоне родительского компонента:
<hero-child [hero]="hero"> </hero-child>в дочернем компоненте:
@Input() hero: Hero;Источник:https://angular.io/docs/ts/latest/cookbook/component-communication.html
есть много способов. Это один из примеров использования распространения между родительскими и дочерними элементами. Это очень эффективно.
Я представил пример, который позволяет просматривать использование двух способов привязки данных в двух формах. Если кто-нибудь может предоставить образец plunkr это было бы очень приятно ;-)
вы можете искать другой способ, используя поставщика услуг. Вы можете посмотреть на это видео тоже для справки: (обмен данными между компонентами в Угловой)
mymodel.ts (данные для обмена)
// Some data we want to share against multiple components ... export class mymodel { public data1: number; public data2: number; constructor( ) { this.data1 = 8; this.data2 = 45; } }помните: должен быть родитель, который будет совместно использовать "mymodel" для дочерних компонентов.
родительский компонент
import { Component, OnInit } from '@angular/core'; import { mymodel } from './mymodel'; @Component({ selector: 'app-view', template: '<!-- [model]="model" indicates you share model to the child component --> <app-mychild [model]="model" > </app-mychild>' <!-- I add another form component in my view, you will see two ways databinding is working :-) --> <app-mychild [model]="model" > </app-mychild>', }) export class MainComponent implements OnInit { public model: mymodel; constructor() { this.model = new mymodel(); } ngOnInit() { } }дочерний компонент, mychild.деталь.ТС
import { Component, OnInit,Input } from '@angular/core'; import { FormsModule } from '@angular/forms'; // <-- NgModel lives here import { mymodel } from './mymodel'; @Component({ selector: 'app-mychild', template: ' <form #myForm="ngForm"> <label>data1</label> <input type="number" class="form-control" required id="data1 [(ngModel)]="model.data1" name="data1"> <label>val {{model.data1}}</label> label>data2</label> <input id="data2" class="form-control" required [(ngModel)]="model.data2" name="data2" #data2="ngModel"> <div [hidden]="data2.valid || data2.pristine" class="alert alert-danger"> data2 is required </div> <label>val2 {{model.data2}}</label> </form> ', }) export class MychildComponent implements OnInit { @Input() model: mymodel ; // Here keywork @Input() is very important it indicates that model is an input for child component constructor() { } ngOnInit() { } }Примечание: В некоторых редких случаях может возникнуть ошибка при анализе HTML-кода, поскольку модель не "готова" к использованию при инициализации страницы. В этом случае префикс HTML-кода с помощью состояние ngIf:
<div *ngIf="model"> {{model.data1}} </div>
Comments