简体   繁体   English

@孩子和父母之间的输出通信。 角度2(5)

[英]@Output communication between child and parent. Angular 2(5)

I'm trying to learn angular 2 and am trying to set a variable in a parent component with data from my child components. 我正在尝试学习angular 2,并尝试使用来自子组件的数据在父组件中设置变量。 Basically I have a subheader in my parent view and I want the title and some HTML to change based on what child is loaded. 基本上,我的父视图中有一个子标题,并且我希望标题和一些HTML可以根据加载的子项进行更改。

Parent component: 父组件:

import { Component, OnInit, ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'app-parent',
  templateUrl: './parent.component.html',
  styleUrls: ['./parent.component.scss'],
  encapsulation: ViewEncapsulation.None
})
export class ParentComponent {
  childDetails: {title: String, helperBar: String};

  onChildLoaded(childData: {
    childTitle: string,
    childHelperBar: string
  }) {
    this.childDetails ={
      title: childData.childTitle,
      helperBar: childData.childHelperBar
    };
    console.log (childDetails);
  }
}

Child Component : 子组件:

import { Component, OnInit, ViewEncapsulation, Output, EventEmitter } 
from '@angular/core';

@Component({
  selector: 'app-first-child',
  templateUrl: './first-child.component.html',
  styleUrls: ['./first-child.component.scss'],
  encapsulation: ViewEncapsulation.None
})
export class FirstChildComponent implements OnInit {
  @Output() childLoaded = new EventEmitter<{childTitle: string, 
childHelperBar: string}>();

  constructor() { }

  ngOnInit() {
    this.childLoaded.emit({
      childTitle: 'Dashboard',
      childHelperBar: '<div class="test"><button>Dash Button</button>
</div>'
    });
  }

}

And finally my parent HTML: 最后是我的父HTML:

<div class="subheader">
  <h1>{{ childDetails.title }}</h1>
  {{ childDetails.helperBar }}
</div>
<nav class="sidebar">

</nav>

<main role="main" class="">
  <router-outlet (childLoaded)="onChildLoaded($event)"></router-outlet>
</main>

For the life of me I can't get this approach to work and can't pinpoint where I'm going wrong. 对于我一生,我无法采用这种方法工作,也无法查明我要去哪里。 I could always just put the subheader in my children but I dont like the idea of repeating the code so many times and it will make my layout a bit harder to achieve. 我总是可以将子标题放在孩子们的头上,但我不喜欢重复代码很多次的想法,这会使我的布局难以实现。

The best way is making use of the service and observable so that whenever the child component changes, the new data will get immediately reflected in the parent component. 最好的方法是利用服务和observable的服务,以便每当子组件发生更改时,新数据将立即反映在父组件中。

in your service.ts, 在您的service.ts中,

import { Subject } from 'rxjs/Subject'
import { Observable } from 'rxjs/Rx';

@Injectable()
export class myService {

  private pageName = new Subject<string>();

  pageNameChange$ = this.pageName.asObservable();
  changedComponentName(option:string){
        this.pageName.next(option);
  }
}

In your child components, 在您的子组件中,

child component 1 子组件1

public ngOnInit() {
  this.myService.changedComponentName('child1');
}

child component 2 子组件2

public ngOnInit() {
   this.myService.changedComponentName('child2');
}

and so on.. 等等..

Now, to get the changed Component names in your parent component, 现在,要在父组件中获取更改后的组件名称,

parent component.ts 父component.ts

import { Subscription } from 'rxjs';

export class parentComponent {

    private subscription:Subscription;

    constructor(private myService:myService){

        this.myService.pageNameChange$.subscribe( /* get called on every child page changes*/
         newPageName => {

        console.log(newPageName); // you get your passed component name ( child1 / child2 /etc.. here in the 'newPageName' variable
    });
  }
}

Are you getting ? 你来了吗? $event in your parent method? 您的父方法中的$event

If YES then why are you using let childDetails ={} inside parent class method . 如果是,那么为什么在父类方法中使用let childDetails ={} Instead you should use this.childDetails={} 相反,您应该使用this.childDetails={}

onChildLoaded($event){
 this.childDetails ={ title: $event.childTitle, helperBar: $event.childHelperBar }; 
console.log (childDetails); 
}

and parent html shoul be 和父html应该是

<div class="subheader"> <h1>{{ childDetails.title }}</h1> {{ childDetails.helperBar }} </div> 
<nav class="sidebar"> </nav> 
<main role="main" class="">
 <app-first-child (childLoaded)="onChildLoaded($event)"></app-first-child> </main>

If you don't want to use <app-first-child/> then you should use shared service 如果您不想使用<app-first-child/> ,则应使用共享服务

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM