2017-11-24 3 views
1

マイ状況:アンギュラ4 - 別のコンポーネントからオブジェクトを渡し(ノー親 - 子階層)

私は以上のループされる配列からオブジェクトを表す各タイルとタイルを示す成分を持ちますありがとう。 タイルをクリックすると、オブジェクトを別のコンポーネントに渡します。このコンポーネントは、変更可能なフィールドにそのオブジェクトのすべてのプロパティを表示することができます。 - 子階層と、共有サービスを使用する必要があることを説明するいくつかの記事

をいくつかの研究を行うと、親のためにこれを達成するためにどのように私を示す複数の投稿渡って来た後:私が試してみました何

必要な機能を実現するために、このようなサービスを試して設定することにしました。

しかし、私は別のルートに移動する必要があるとは思わない。ディテールコンポーネントでサービスを取得するときに、サービスに渡されるオブジェクトが定義されていないため、ナビゲーションが早い場所を見つけるようです。

マイコード:

タイルを示す成分が共有サービスにクリックされたオブジェクトを渡すために、以下の機能を有する:

editPropertyDetails(property: Property) { 
    console.log('Edit property called'); 

    return new Promise(resolve => { 
     this.sharedPropertyService.setPropertyToDisplay(property); 
     resolve(); 
    }).then(
    () => this.router.navigate(['/properties/detail']) 
    ) 
    } 

共有サービスは、プロパティオブジェクトを設定する機能を有しますこれを検索すると、次のようになります。

@Injectable() 
export class SharedPropertyService { 
    // Observable 
    public propertyToDisplay = new Subject<Property>(); 

    constructor(private router: Router) {} 

    setPropertyToDisplay(property: Property) { 
    console.log('setPropertyToDisplay called'); 
    this.propertyToDisplay.next(property); 
    } 

    getPropertyToDisplay(): Observable<Property> { 
    console.log('getPropertyToDisplay called'); 
    return this.propertyToDisplay.asObservable(); 
    } 
} 

最後に、受信する必要のある詳細コンポーネントクリックされたが未定義のオブジェクトを取得したオブジェクト:

export class PropertyDetailComponent implements OnDestroy { 

    property: Property; 
    subscription: Subscription; 

    constructor(private sharedPropertyService: SharedPropertyService) { 
     this.subscription = this.sharedPropertyService.getPropertyToDisplay() 
      .subscribe(
      property => { this.property = property; console.log('Detail Component: ' + property.description);} 
     ); 
    } 

    ngOnDestroy() { 
    // When view destroyed, clear the subscription to prevent memory leaks 
    this.subscription.unsubscribe(); 
    } 
} 

ありがとうございます!

+0

これをスタックブリッツで再現できれば分かりにくいですが、理解しやすくなります。今のところ[共有サービス](https://rahulrsingh09.github.io/AngularConcepts)より簡単な説明として、 –

+0

では、両方のコンポーネントを含むモジュールで共有サービスを提供する必要があります。これは本当ですか?さもなければ、それはシングルトンではなく、サービスはその目的を逸するでしょう。 – marvstar

+0

はい、サービスはフィーチャモジュールのプロバイダにリストされています。 – DennisN

答えて

0

Iルートのナビゲーションエキストラのようにクリックした後、渡されたIDに基づいてオブジェクトをフェッチするために、詳細コンポーネントにサービスを利用したタイルのオブジェクトのIDを渡すことによって、問題を解決しルート経由で。

私は以下のコードを提供しますので、誰もこのすべてをもう一度やり直さなくてはなりません。

そこに含まれるオブジェクトの詳細を見るためにクリックすることができるタイルを示すコンポーネント:

editPropertyDetails(property: Property) { 
    console.log('Edit property called'); 

    let navigationExtras: NavigationExtras = { 
      queryParams: { 
       "property_id": property.id 
      } 
     }; 

    this.router.navigate(['/properties/detail'], navigationExtras); 
    } 

上でクリックされたオブジェクトを受け取り、詳細コンポーネント
private sub: any; 
    propertyToDisplay: Property; 

    constructor 
    (
    private sharedPropertyService: SharedPropertyService, 
    private router: Router, 
    private route: ActivatedRoute 
) {} 

    ngOnInit() { 
    this.sub = this.route.queryParams.subscribe(params => { 
     let id = params["property_id"]; 

     if(id) { 
      this.getPropertyToDisplay(id); 
     } 

    }); 
    } 

    getPropertyToDisplay(id: number) { 
    this.sharedPropertyService.getPropertyToDisplay(id).subscribe(
      property => { 
       this.propertyToDisplay = property; 
      }, 
      error => console.log('Something went wrong')); 
    } 

    // Prevent memory leaks 
    ngOnDestroy() { 
    this.sub.unsubscribe(); 
    } 

サービス

properties: Property[]; 

    constructor(private propertyService: PropertyService) {} 

    public getPropertyToDisplay(id: number): Observable<Property> { 
    if (this.properties) { 
     return this.findPropertyObservable(id); 
    } else { 
      return Observable.create((observer: Observer<Property>) => { 
       this.getProperties().subscribe((properties: Property[]) => { 
        this.properties = properties; 
        const prop = this.filterProperties(id); 
        observer.next(prop); 
        observer.complete(); 
       }) 
      }).catch(this.handleError); 
    } 
    } 

    private findPropertyObservable(id: number): Observable<Property> { 
    return this.createObservable(this.filterProperties(id)); 
    } 

    private filterProperties(id: number): Property { 
     const props = this.properties.filter((prop) => prop.id == id); 
     return (props.length) ? props[0] : null; 
    } 

    private createObservable(data: any): Observable<any> { 
     return Observable.create((observer: Observer<any>) => { 
      observer.next(data); 
      observer.complete(); 
     }); 
    } 

    private handleError(error: any) { 
     console.error(error); 
     return Observable.throw(error.json().error || 'Server error'); 
    } 

    private getProperties(): Observable<Property[]> { 
    if (!this.properties) { 
    return this.propertyService.getProperties().map((res: Property[]) => { 
     this.properties = res; 
     console.log('The properties: ' + JSON.stringify(this.properties)); 
     return this.properties; 
    }) 
     .catch(this.handleError); 
    } else { 
     return this.createObservable(this.properties); 
     } 
    } 
0

以下のサンプルで試してみてください:

ステップ1:作成サービス[DataServiceの]

import { Injectable } from '@angular/core'; 
import { BehaviorSubject } from 'rxjs/BehaviorSubject'; 
@Injectable() 
export class DataService { 
    private userIdSource = new BehaviorSubject<number>(0); 
    currentUser = this.userIdSource.asObservable(); 

    private orderNumSource = new BehaviorSubject<number>(0); 
    currentOrder = this.orderNumSource.asObservable(); 

    constructor() { } 

    setUser(userid: number) { 
    this.userIdSource.next(userid) 
    } 

    setOrderNumber(userid: number) { 
    this.orderNumSource.next(userid) 
    } 
} 

ステップ2:ログインコンポーネントに設定された値

import { Component } from '@angular/core'; 
import { DataService } from "../services/data.service"; 

@Component({ 
    selector: 'app-login', 
    templateUrl: './login.component.html', 
    styleUrls: ['./login.component.css'] 
}) 
export class LoginComponent { 
    constructor(private dataService:DataService) {  } 
    onSubmit() { 
     this.dataService.setUser(1); 
    } 
} 

ステップ3:の値を取得します。別の構成要素

import { Component, OnInit } from '@angular/core'; 
import { DataService } from "../services/data.service"; 

@Component({ 
    selector: 'app-shopping-cart', 
    templateUrl: './shopping-cart.component.html', 
    styleUrls: ['./shopping-cart.component.css'] 
}) 
export class ShoppingCartComponent implements OnInit { 
    userId: number = 0; 
    constructor(private dataService: DataService) { } 
    ngOnInit() { 
    this.getUser(); 
} 
    getUser() { 
    this.dataService.currentUser.subscribe(user => { 
     this.userId = user 
    }, err => { 
     console.log(err); 
    }); 
    } 
} 

:ページの更新時に値が失われます。代わりにthis.sharedPropertyService.getPropertyToDisplay()

this.sharedPropertyService.propertyToDisplay.subscribe((property) => { 
    this.property = property; 
    console.log('Detail Component: ' + property.description); 
}); 

this.sharedPropertyService.propertyToDisplayを購読し、以下のようにオブジェクトを送信するために

試し:あなたのコンソール出力がない

editPropertyDetails(property: Property) { 
    this.sharedPropertyService.setPropertyToDisplay(property); 
} 
0

はこのようにしてみてください?子コンポーネントにthis.propertyが設定されていますか?

私は)この機能

getPropertyToDisplay(を取り除くしようとするだろう:観察可能

とだけ直接propertyToDisplayにアクセスしてみてください。

また、.navigateは2番目のパラメータとしてデータを受け取ることができるため、ルート変更でデータを渡すことができます。

constructor(
    private route: ActivatedRoute, 
    private router: Router) {} 

    ngOnInit() { 
    this.property = this.route 
     .variableYouPassedIntoNavigator 
+0

まだ何も記録していません。 – DennisN

+0

@DennisNは、更新された回答を確認して試すことができます – Chandru

+0

どちらも機能していないようですが、詳細コンポーネントへのナビゲーションをトリガーするのに最適な場所は何ですか? – DennisN

0

+0

navigate関数でプロパティをどのように渡しますか? NavigationExtrasについてのドキュメントを見ようとしましたが、それを理解できませんでした。編集プロパティ(プロパティ:プロパティ){ this.router.navigate(['/ properties/detail']、property); } – DennisN

+0

ドキュメントにすべてのサンプルが含まれている必要があります。また、ngUnsubsribeが呼び出されている可能性がありますか? – Jesse

+0

残念ながら、navigateメソッドでは複雑なオブジェクトを渡すことはできません。私は下に自分のソリューションを掲載しました。 – DennisN

関連する問題