Angular 4:如何使用与parent和child相同的组件?

Angular 4: How to use same component as both parent and child?

我的要求是拥有 forms.In 树 parent 表单,单击按钮时仅会创建 child 表单。它可以继续这样直到 n-levels。

我的做法:

我创建了一个组件。这被用作 parent 和 child。单击按钮,我将项目动态添加到 ActivatedRoute 的 route.routeConfig.children。然后导航到相对于当前路径的添加路径。直到这一部分一切顺利。 所以我在屏幕上看到了所有表格。我只想让活动表单在屏幕上可见。然后单击一个按钮(后退按钮)我想转到它的 relaive parent 并仅显示该表单。通过在模板中使用 *ngif,我可以在打开 child 表单时隐藏 parent 表单。但是从 rm child 返回时无法使其可见。下面是我的代码。请让我知道我是否应该采取任何其他方法,或者我需要添加什么才能使其按我的方式工作。

我的组件。

@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 它不起作用。我的 parent 表单仍然被隐藏。我只看到空白屏幕。我注意到的一个问题是 "NavigationEnd" 事件被多次触发,可能是因为我使用的是同一组件,当创建新的 child 时,它会添加另一个事件。

我花了一些时间找到了上述问题的解决方案。于是想到这里分享。

所以有一些错误,也有一些学习。

我的方法有误:

  1. 我在 testComponent 下添加了 serive ConfigService。要在所有 child 组件之间共享相同的服务,我应该在根组件下添加该服务。否则每个组件都有自己的服务实例,数据也会不同。

表示

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 中。我只添加更改的部分。因此,当我们导航回 parent 路由 ngOnDestroy of child 获取 called.Here 时,我们正在使用稍后在订阅中捕获的服务更改值parent 的回调。

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

以上内容解决了 child 通知 parent 的问题。但就我而言,因为我可以进入多个级别。 单击最后一个 children 的后退 按钮会触发每个 parent 组件的订阅回调,直到第一个组件。所以每个 parent 组件都变得可见,而不仅仅是直接的 parent。虽然它没有解决我的目的,但我学会了这种跨 components.May 传输数据的方式,因为我可以使用路由路径之类的东西来决定它是否是即时的 parent。我还没搞定。

但我必须使用另一种简单的方法来解决我的问题。

方法二:

在模板下,我为 deactivate 添加了事件侦听器。

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

作为 TestComponent 的一部分,我添加了以下方法。

onDeactivateChild(){
    this.showParent=true;
  }

问题已解决。单击 child 的后退按钮 deactivate 事件被触发,parent 开始了解它。希望它能帮助面临这个问题的人。

谢谢。