Angular 1.xx에서는 단순히 동일한 서비스를 요청하면 동일한 인스턴스로 끝나므로 서비스에서 데이터를 공유 할 수 있습니다.
이제 Angular 2에는 내 서비스에 대한 참조가있는 구성 요소가 있습니다. 나는 서비스의 데이터를 읽고 수정할 수 있습니다. 다른 구성 요소에 동일한 서비스를 삽입하려고하면 새 인스턴스를 얻는 것처럼 보입니다.
내가 도대체 뭘 잘못하고있는 겁니까? 패턴 자체가 잘못되었거나 (서비스를 사용하여 데이터를 공유) 서비스를 싱글 톤 (앱의 한 인스턴스 내) 또는 다른 것으로 표시해야합니까?
나는 2.0.0-alpha.27/
btw에있다
주석의 appInjector
(edit : now providers
)를 통해 서비스를 삽입 한 @Component
다음 생성자에 참조를 저장합니다. 내가 생각했던 것처럼 구성 요소간에 로컬로 작동하지 않습니다 (동일한 서비스 인스턴스를 공유하지 않음).
업데이트 : Angular 2.0.0부터는 @ngModule이 있습니다. 여기서 providers
속성 아래에 서비스를 정의합니다 @ngModule
. 그러면 해당 서비스의 동일한 인스턴스가 해당 모듈의 각 구성 요소, 서비스 등에 전달됩니다.
https://angular.io/docs/ts/latest/guide/ngmodule.html#providers
업데이트 : 일반적으로 Angular 및 FE 개발에 많은 일이 발생했습니다. @noririco가 언급했듯이 NgRx와 같은 상태 관리 시스템을 사용할 수도 있습니다 :
https://ngrx.io/
답변
서비스 싱글 톤은 좋은 솔루션입니다. 다른 방법- 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 데코레이터의 입력과 출력을 사용해야합니다. 다음은 둘 다 사용하는 가장 기본적인 예입니다.
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 샘플을 제공 할 수 있다면 이것은 매우 좋을 것입니다 😉
서비스 제공자를 사용하여 다른 방법을 찾을 수 있습니다. 참고로이 비디오를 볼 수도 있습니다. ( Angular의 구성 요소 간 데이터 공유 )
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.component.ts
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>