2017-08-03 18 views
1

私の要件はフォームのツリーを持つことです。ボタンをクリックした親フォームでは、子フォームのみが作成されます。これはnレベルまでこのように進むことができます。角4:親と子の両方と同じコンポーネントを使用する方法?

私のアプローチ:

私は1つのコンポーネントを作成しました。これは、親と子の両方として使用されます。ボタンをクリックすると、ActivatedRouteのroute.routeConfig.childrenに項目を動的に追加しています。次に、現在のパスを基準にして追加されたパスにナビゲートします。この部分まですべてがうまくいく。 私はscrenのすべてのフォームを参照してください。アクティブなフォームだけを画面上に表示したい。次に、ボタン(戻るボタン)をクリックすると、私はその親の親に行き、そのフォームのみを表示したいと思います。テンプレートで* ngifを使用して子フォームを開くときに、親フォームを非表示にすることができます。しかし、frmの子に戻ってきて見えるようにすることはできません。以下は私のコードです。私が他のアプローチを取るべきか、それとも自分のやり方で働かせるために何を追加する必要があるか教えてください。

私のコンポーネント。

@Component({ 
    selector: 'app-test', 
    templateUrl: './test.component.html', 
    styleUrls: ['./test.component.css'], 
    providers: [ConfigService] 
}) 
export class TestComponent implements OnInit, OnDestroy { 
    name: string; 
    age: Number; 
    showParent: boolean = true; 
    childrenRoute: Routes; 
    message: any; 
    subscription: Subscription; 
    private sub: any; 

    constructor(private router: Router, private route: ActivatedRoute, private _configService: ConfigService) { 
    this.name = 'test data'; 
    this.age = 20; 
    this.router = router; 
    if(this._configService.getConfig('showParent') != null){ 
     this.showParent=false; 
    } 
    this.subscription = router.events.subscribe(event => { 
     if (event instanceof NavigationEnd) { 
     if (_configService.getConfig('showParent') != null) { 
      this.showParent = _configService.getConfig('showParent'); 
     } 
     } 

    }); 


    } 

    ngOnInit() { 

    } 

    ngOnDestroy() { 
    // unsubscribe to ensure no memory leaks 
    this.subscription.unsubscribe(); 
    } 

    showChildRecord() { 
    this.childrenRoute = [{ 
     path: 'child', 
     component: TestComponent 
    }]; 
    if (this.route.routeConfig != undefined) { 
     this.route.routeConfig.children = this.childrenRoute; 
    } 

    this._configService.setOption('showParent', false); 
    this.router.navigate(['./child'], { relativeTo: this.route }); 
    } 

    back() { 
    this._configService.setOption('showParent', true); 
    this.router.navigate(["../"], { relativeTo: this.route }); 

    } 

} 

サービスを使用して、同じコンポーネントの各インスタンス間でデータを共有しようとしました。

@Injectable() 
export class ConfigService { 
    private config = {}; 

    setOption(option, value) { 
     this.config[option] = value; 
    } 

    getConfig(option: string) { 
     if(option != undefined){ 
      return this.config[option] != undefined ? this.config[option]: null; 
     }else 
      return null; 
    } 

} 

テンプレートtest.component.html

<div *ngIf="showParent"> 
<p>Name: 
<input type="text" [(ngModel)]="name"> 
</p> 
<p>Age: 
<input type="text" [(ngModel)]="age"> 
</p> 
{{name}} : {{age}} 
<button (click)="showChildRecord();" > Go to Child Record</button> 
<button (click)="back();">Back</button> 
</div> 

<router-outlet></router-outlet> 

App.module.tsルート:

const appRoutes: Routes = [ 
    { 
    path: 'child', 
    component: TestComponent, 
    children: [ 
     { path: 'child', 
      component: TestComponent   
     } 
     ] 
    } 

]; 

は私がサービスとトグルで "showParent" の情報を保存しようとしていますそれは行動に依存する。ルーティングイベント "NavigationEnd"の下で、私はそれを読んで、showParent properyに割り当てています。しかし、動作しません。それでも私の親フォームは隠されています。そして、私は空白の画面が表示されます。私が気づいた1つの問題は、 "NavigationEnd"イベントが複数回起動され、同じコンポーネントを使用しているbecozであり、新しい子が作成されたときに別のイベントが追加されることです。

答えて

0

時間を費やして上記の問題の解決策を見つけることができました。ここで共有することを考えました。

だから、いくつかの間違いやいくつかの学習もあった。私のアプローチで

間違い:

  1. 私はtestComponent下serive ConfigServiceを追加しました。すべての子コンポーネント間で同じサービスを共有するには、ルートコンポーネントの下にサービスを追加する必要があります。それ以外の場合、各コンポーネントはサービスの独自のインスタンスを持ち、データは異なります。

手段

providers: [ConfigService] 

はAppModuleに追加されるべきです。

  1. 単なるサービスなので値の変化を聞きません。だから私は観察可能にする必要があります。

私の上記のサービスを使用する代わりに、以下のような別のサービスを作成しました。

import { Injectable } from '@angular/core'; 
import { Observable } from 'rxjs'; 
import { Subject } from 'rxjs/Subject'; 

@Injectable() 
export class MessageService { 
    private subject = new Subject<any>(); 

    sendMessage(message: any) {debugger 
     this.subject.next(message); 
    } 

    clearMessage() { 
     this.subject.next(); 
    } 

    getMessage(): Observable<any> { 
     return this.subject.asObservable(); 
    } 
} 

私はそれを購読しています。私は変更されたセクションのみを追加しています。だから親ルートに戻るとき子供のngOnDestroyが呼び出されます。ここでは、後で親のサブスクリプションコールバックで捕捉されるserivceを使用して値をチェーニングしています。

constructor(private router: Router, private route: ActivatedRoute, private _configService: ConfigService,private _msgService:MessageService) { 
    this.name = 'test data'; 
    this.age = 20; 
    this.router = router; 
    this.subscription = this._msgService.getMessage().subscribe(message => { 

     if(message['showParent']){ 
     this.showParent=true; 
     } 
    }); 
} 

    ngOnDestroy() { 
    // unsubscribe to ensure no memory leaks 
    this._msgService.sendMessage({ 'showParent':true }); 
    this.subscription.unsubscribe(); 
    } 

上記のことは、親から子供に通知される問題を解決しました。しかし、私の場合、私は複数のレベルに行くことができます。 戻る最後の子をクリックすると、各親コンポーネントのこのサブスクライブコールバックが最初の子コンポーネントまで呼び出されます。したがって、各親コンポーネントは、すぐ上の親の代わりに表示されます。それは私の目的を解決しませんでしたが、コンポーネント間でデータをやりとりするこの方法を学びました。私はルーティングパスのようなものを使用して、それが直系の親であるかどうかを決めることができます。私はまだそれを持っていない。

しかし、別の簡単な方法で問題を解決する必要があります。

アプローチ2:ためを無効に

テンプレートの下では、私は、イベントリスナーを追加しました。

<router-outlet (deactivate)='onDeactivateChild($event)' ></router-outlet> 

また、TestComponentの一部として、以下のメソッドを追加しました。

onDeactivateChild(){ 
    this.showParent=true; 
    } 

問題を解決しました。子供の戻るボタンをクリックするとが無効になりますイベントが発生し、親はそれについて知ります。この問題に直面している人に役立つことを願っています。

ありがとうございました。

関連する問題