首页 文章

子组件到父组件通信没有子项嵌套在角度模板中(Angular 2)

提问于
浏览
2

每个回答的帖子,每个教程都会显示 EventEmitter() 可以用于子组件,如果父母正在监听,它可以与父组件通话;但是,只有在子组件是父模板的一部分时才有效;否则,只有应用程序的根组件才能获取emit .

这是一个简单的结构(在 radio-group 上使用 <ng-content></ng-content> 来转换孩子们):

<radio-group>
  <radio></radio>
  <radio></radio>
  <radio></radio>
</radio-group>

当检查自定义无线电组件时,它应该发出一个事件 - 效果很好 . 但是自定义无线电组即使正在收听也不会听到这个事件,因为在这个实现中,它的子节点不是它的模板的一部分 .

我不明白Angular Material 2 Radios是怎么回事的;但对于那些了解Angular 2的人来说,它们是一个很好的参考 .

单击Angular's Material 2 Radio Demo的"Examples"选项卡,查看我想要复制的内容 .

同样,我不是要复制和粘贴它们的实现,我试图让子组件在子组件不是父模板的一部分时将事件传递给父组件 .

3 回答

  • 1

    如果你去that plunker,你会发现它们具有以下结构:

    <radio-ng-model-example>
        <md-radio-group class="example-radio-group" [(ngModel)]="favoriteSeason">
            <md-radio-button class="example-radio-button" *ngFor="let season of seasons" [value]="season">
                {{season}}
            </md-radio-button>
        </md-radio-group>
        <div class="example-selected-value">Your favorite season is: {{favoriteSeason}}</div>
    </radio-ng-model-example>
    

    radio-ng-model-example 是根组件 . 因此,他们使用 EventEmittermd-radio-buttonmd-radio-group 之间进行通信,并使用 ngModelmd-radio-groupradio-ng-model-example 之间进行通信 .

  • 1

    当子组件不是父模板的一部分时,它们基本上是内容子组件 . 它们的范围在Parent组件中 .

    例如,如果您有一个名为 my-component 的组件,并且在其模板中有类似下面的内容,

    <parent [input]='somevar1' (output)='somemethod1()' >
       <child [input]='somevar2' (output)='somemethod2()' ></child>
    </parent>
    

    somevar1somevar2somemethod1somemethod2 来自 my-component 的范围 .

    基于这种理解,可以非常安全地说 parentchild 可以被视为 my-component 范围内的兄弟姐妹 . 因此,您可以使用 my-component 范围在这两者之间进行通信 .

    例,

    @Component({
      selector: 'parent',
      template: `<h1>Parent</h1>
      {{awesomeInput}}
      <hr />
      <ng-content></ng-content>
      `
    })
    export class ParentComponent { 
       @Input() awesomeInput: string;
    }
    

    子组件,

    @Component({
      selector: 'child',
      template: `<h1>Child</h1>
      <button (click)='sendAwesomeOutput()'>Click me!!</button>
      `
    })
    export class ChildComponent {
      @Output() awesomeOutput =  new EventEmitter();
    
      sendAwesomeOutput(){
        this.awesomeOutput.next('awesome output from child!!');
      }
    }
    

    在模板中使用上述组件的组件 .

    @Component({
      selector: 'my-app',
      template: `<h1>Hello {{name}}</h1>
      <hr />
      <parent [awesomeInput]="defaultInput" >
         <child (awesomeOutput)="getOutputFromChild($event)" ></child>
      </parent>
      `
    })
    export class AppComponent { 
      name = 'Angular';
      defaultInput = 'default value for parent';
    
      getOutputFromChild(val){
        this.defaultInput = val;
      }
    }
    

    Update

    如果你在parent-Child之间传递值,你可能没什么创意,并且可以在模板本身中完全做到 . 更新了Plunker !!

    <parent awesomeInput="{{child1.awesomeOutput | async }}" >
         <child #child1 ></child>
    </parent>
    

    如果你必须处理任何事情,上面的那个考虑场景 .

    看看这个Plunker !!

    希望这可以帮助!!

  • 1

    回答 Headers 问题而不使用ngModel,bindings或EventEmitter(因为它不能在模板之外工作),并且足够灵活,可以在每个子组件中包含任何类型的内容,在Angular 2.4中,这是其他实现的另一种方法:

    Example:
    "Presenters"在Odin议会("Organizer") . 只有一位演示者可以一次说话(出现) . 接下来的人,向组织者发出他们意图的信号,组织者阻止其他主持人说话,这样新的主持人就可以恢复他们的演讲 .

    (演示截图减去额外的嵌套内容:)

    Demo screenshot minus additional nested content
    单击任何按钮会导致所有演示者隐藏,但您只是单击了该演示者 .

    Usage:

    <organizer>
        <presenter>
            <h2>Thor</h2>
            <summary>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Incidunt ea nisi impedit aspernatur sint voluptatum odit aperiam, soluta, explicabo, nesciunt earum quo. Vel quod, ratione ullam deserunt commodi quaerat fugiat!</summary>
            <asgardian-power-point></asgardian-power-point>
        </presenter>
        <presenter>
            <h2>Loki</h2>
            <summary>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Incidunt ea nisi impedit aspernatur sint voluptatum odit aperiam, soluta, explicabo, nesciunt earum quo. Vel quod, ratione ullam deserunt commodi quaerat fugiat!</summary>
            <interjection></interjection>
            <lies></lies>
        </presenter>
        <presenter>
            <h2>Sif</h2>
            <summary>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Incidunt ea nisi impedit aspernatur sint voluptatum odit aperiam, soluta, explicabo, nesciunt earum quo. Vel quod, ratione ullam deserunt commodi quaerat fugiat!</summary>
            <asgardian-power-point></asgardian-power-point>
        </presenter>
    </organizer>
    

    organizer.component.html:

    <ng-content></ng-content>
    

    organizer.component.ts:

    import {
        Component,
        ContentChildren,
        QueryList
    } from '@angular/core';
    
    import { PresenterComponent } from '../presenter/presenter.component';
    
    @Component({
        selector: 'organizer',
        templateUrl: './organizer.component.html',
        styleUrls: ['./organizer.component.scss']
    })
    
    export class OrganizerComponent {
    
        @ContentChildren(PresenterComponent) presenters: QueryList<PresenterComponent>;
    
        stopPresenters() {
            this.presenters.forEach(function(item) {
                item.conclude();
            });
        }
    
    }
    

    presenter.component.html:

    <div style="overflow:hidden;" [style.height]="expand ? 'auto' : '30px'">
        <button (click)="present()">Present</button>
        <ng-content></ng-content>
    </div>
    

    presenter.component.ts:

    import {
        Component,
        Input,
        Inject,
        forwardRef
    } from '@angular/core';
    
    import { OrganizerComponent } from '../organizer/organizer.component';
    
    @Component({
        selector: 'presenter',
        templateUrl: './presenter.component.html',
        styleUrls: ['./presenter.component.scss']
    })
    
    export class PresenterComponent {
    
        constructor(@Inject(forwardRef(() => OrganizerComponent)) private organizer:OrganizerComponent) {}
    
        @Input() expand: boolean = false;
    
        present() {
            this.organizer.stopPresenters();
            this.expand = true;
        }
    
        conclude() {
            this.expand = false;
        }
    
    }
    

相关问题