2017-08-03 82 views
1

我的要求是有形式樹。在父窗體上點擊按鈕只會創建子窗體。它可以繼續這樣的n級。Angular 4:如何使用同一個組件作爲父母和孩子?

我的方法:

我已經創建了一個組件。這用作父母和孩子。點擊按鈕,我動態地將項目添加到ActivatedRoute的route.routeConfig.children。然後導航到相對於當前路徑的添加路徑。直到這一部分一切順利。 所以我在scren中看到所有的形式。我只想在屏幕上顯示活動窗體。然後點擊一個按鈕(後退按鈕),我想轉到它的父母並僅顯示該表單。在模板中使用* ngif打開子窗體時,我可以隱藏父窗體。但是回到孩子身後卻無法看清楚。以下是我的代碼。請讓我知道,如果有其他方法,我應該採取什麼額外的我需要添加,使其按我的方式工作。

我的組件。

@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.But但它不起作用。我的父母表單仍然隱藏我只是看到空白的屏幕。我注意到的一個問題是「NavigationEnd」事件被多次觸發,可能是因爲我使用相同的組件,並且當創建新的子組件時,它會添加另一個事件。

回答

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(); 
    } 
} 

在testComponent中,我訂閱了它。我只是添加更改的部分。所以當我們回到父母路線ngOnDestroy的孩子被調用。在這裏我們正在使用後來在父母的訂閱回調中捕獲的serivce chaning值。

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; 
    } 

問題已解決。點擊小孩的後退按鈕停用事情被解僱了的時候,父母知道了。希望它能幫助解決這個問題的人。

謝謝。

相關問題