2017-11-17 2 views
2

내가 child_1 구성 요소의 동작 버튼을 구현하는 데 실패하고 있지만, 다음 코드와 같이 이벤트 핸들러는 하위 하위 구성 요소의 child_2에 있습니다부모/자식 요소 통신이

app.component.html (부모 HTML)

<div style="text-align:center"> 
    <h1> 
    Welcome to {{title}}! 
    </h1> 
    <app-navigation></app-navigation> <!-- Child1--> 
</div> 

app.component.html (부모 요소)

import { Component } from '@angular/core'; 
import { ProductService } from './productservice'; 
import {Product} from './product'; 

@Component({ 
     selector: 'app-root', 
     templateUrl: './app.component.html', 
     styleUrls: ['./app.component.css'], 
    }) 
    export class AppComponent { 
     title = 'MobileShirtShoeApp'; 
    } 

app.module.ts (메인 모듈)

,
import { BrowserModule } from '@angular/platform-browser'; 
import { NgModule } from '@angular/core'; 
import { HttpModule } from '@angular/http'; 
import { Product } from './product'; 
import { ProductService } from './productservice'; 
import { AppComponent } from './app.component'; 
import { NavigationComponent } from './navigation/navigation.component'; 
import { DataTemplateComponent } from './data-template/data-template.component'; 

@NgModule({ 
    declarations: [AppComponent,NavigationComponent,DataTemplateComponent], 
    imports: [BrowserModule,HttpModule], 
    providers: [ProductService], 
    bootstrap: [AppComponent] 
}) 

export class AppModule { } 

navigation.component.html (하위 1 HTML)

<fieldset> 
    <legend>Navigate</legend> 
    <div> 
    <button (click)="loadMobiles()">Mobiles</button> <!--Child_1 Action--> 
    </div> 
    <app-data-template></app-data-template> 
</fieldset> 

navigation.component.ts (하위 1 Component.ts)

import { Component, OnInit } from '@angular/core'; 
import { ProductService } from '../productservice'; 
import {Product} from '../product'; 
import {DataTemplateComponent} from '../data-template/data-template.component'; 


@Component({ 
    selector: 'app-navigation', 
    templateUrl: './navigation.component.html', 
    styleUrls: ['./navigation.component.css'] 
}) 
export class NavigationComponent implements OnInit { 
    error: string; 
    productArray: Product[]; 

    constructor(private myService: ProductService){ 
    this.myService = myService; 
    } 

    dataTemplateComponent: DataTemplateComponent = new DataTemplateComponent(this.myService); 

    ngOnInit() { 
    } 

    loadMobiles() { 
    return this.dataTemplateComponent.loadMobiles(); 
    } 
} 

데이터 템플릿. component.html (어린이 2 HTML) (데이터를 표시하지 않음)

<fieldset> 
    <legend>Requested Data</legend> 
    Welcome 
    <div> 
     <ul> 
      <li *ngFor="let product of productArray"> 
       {{product.id}} {{product.name}} {{product.price}} 
       <img src="{{product.url}}"> 
      </li> 
     </ul> 
    </div> 
</fieldset> 

데이터 template.component.ts (자녀 2 구성 요소)

import { Component} from '@angular/core'; 
import {Product} from '../product'; 
import {ProductService} from '../productservice'; 

@Component({ 
    selector: 'app-data-template', 
    templateUrl: './data-template.component.html', 
    styleUrls: ['./data-template.component.css'] 
}) 

export class DataTemplateComponent { 
    error: string; 
    productArray: Product[]; 
    constructor(private productService: ProductService) { 
    this.productService = productService; 
    } 

    loadMobiles(){ 
    let promise = this.productService.fetchMobiles(); 
    promise.then(productArr => { 
     return this.productArray = productArr; 
     }).catch((err) => { 
     this.error = err; 
     }); 
    } 
} 

ProductService.ts

import 'rxjs/add/operator/toPromise'; 
import {Http, HttpModule} from '@angular/http'; 
import {Injectable} from '@angular/core'; 
import {Product} from './product'; 


@Injectable() 
export class ProductService{ 
    http: Http; 
    constructor(http: Http){ 
    this.http = http; 
    console.log(http); 
} 

fetchMobiles(): Promise<Product[]>{ 
    let url = "https://raw.githubusercontent.com/xxxxx/Other/master/JsonData/MobileData.json"; 
    return this.http.get(url).toPromise().then((response) => { 
     return response.json().mobiles as Product[]; 
    }).catch(this.handleError); 
} 

private handleError(error: any): Promise<any> { 
    console.error('An error occurred', error); 
    return Promise.reject(error.message || error); 
} 
} 

코드가 당신을 귀찮게하는 경우 죄송합니다

(코드를 호출 제품 서비스를 포함합니다). 그래서 기본적으로 child_1.html.The 서비스가 잘 작동하고 Product.ts를 Product.ts를 사용하여 JSON 형식의 데이터를 가져 오는 ProductService로 작업 할 때 child_2.html에 서비스 데이터를 표시하지 못하고 있습니다. 모든 종류의 도움을 주시면 감사하겠습니다.

+0

내가 찾고 있어요 동안 단지 Gona을 코멘트 이 경우 http 호출을 약속으로 변환하는 습관을 벗어나 시도해야합니다. 그렇게 할 필요가 없습니다. – bryan60

답변

2

app-navigation에서 인스턴스화하는 DataTemplateComponent가 페이지의 DataTemplateComponent와 동일한 인스턴스가 아니기 때문에 이는 작동하지 않습니다. 인스턴스화하여 페이지에 전혀 묶이지 않은 완전히 새로운 것입니다. 당신이 달성하고자하는 것은 컴포넌트 커뮤니케이션입니다. 특히, 부모/자식 구성 요소 통신. 이렇게하는 데는 여러 가지 방법이 있지만 공유 서비스 패턴을 사용하면 가장 깨끗하고 유연하며 확장 가능한 방법을 사용할 수 있습니다. 기본적으로, 다른 하나는 여기에 가입하는 동안 다음과 같이 두 서비스에 주입하고 하나가 관찰 갱신 것을 그것에 관찰과 서비스를 선언

@Inject() 
export class MyComponentCommunicationService { 
    private commSubject: Subject<any> = new Subject(); 
    comm$: Observable<any> = this.commSubject.asObservable(); 
    notify() { 
     this.commSubject.next(); 
    } 
} 

는 다음 중 하나를 응용 프로그램 모듈에서이 서비스를 제공 또는 아마도 다음 응용 프로그램 탐색에 필요에 따라 상위 구성 요소에서 :

constructor(private commService: MyComponentCommunicationService) {} 
loadMobiles() { 
    this.commservice.notify(); 
} 

및 데이터 템플릿 :

constructor(private commService: MyComponentCommunicationService, private productService: ProductService) {} 
ngOnInit() { 
    this.commSub = this.commService.comm$.subscribe(e => this.loadMobiles()); 
} 
ngOnDestroy() { this.commSub.unsubscribe(); } // always clean subscriptions 

이 아마 가짜 진주 목걸입니다 전자 제품을 이미 가지고 있기 때문에 불필요합니다. 아마도로드 모바일 로직을 제품 서비스로 옮기고 데이터 템플릿 서비스가 가입되어 있는지 관찰하고, nav 컴포넌트가 제품 서비스에서로드 모바일 메소드를 호출하게 할 수 있습니다. 그러나 이것은 설명하기위한 것일뿐입니다 개념.

아마 이런 식으로 할 거라고 :

@Inject() 
export class ProductService { 
    private productSubject: Subject<Product[]> = new Subject<Product[]>(); 
    products$: Observable<Product[]> = this.productSubject.asObservable(); 
    loadMobiles() { 
     this.fetchMobiles().then(productArr => { 
      this.productSubject.next(productArr); 
      }).catch((err) => { 
      this.productSubject.error(err); 
      }); 
    } 
} 

다음 탐색 구성 요소를 :

loadMobiles() { 
    this.myService.loadMobiles(); 
} 

다음 데이터 템플릿 :

ngOnInit() { 
    this.productSub = this.productService.products$.subscribe(
     products => this.productArray = products, 
     err => this.error = err 
    ); 
} 
ngOnDestroy() { this.productSub.unsubscribe(); } // always clean subscriptions 
+0

설명해 주셔서 감사합니다. @ bryan60하지만, data-template.component의 서비스에서 인스턴스화해야하는 ProductService.ts에서 HTTP를 인스턴스화하고 있기 때문에 catch가 있습니다. 하지만 지금 당신의 접근 방식을 적용하려고합니다. –

+0

이것은 전혀 잡을 수 없습니다. 두 방법 모두 똑같이 잘 작동하며, 두 번째 방법은 단순하고 간단합니다. – bryan60

+0

나는 두 번째 것을 지금 취하고있다. 다시 시도하고 다시 보자. 어쨌든 고맙습니다. –

관련 문제