Angular 2:无法阅读财产'关闭'未定义的

时间:2017-02-19 13:29:25

标签: angular events binding scope eventemitter

我是Angular 2的新手,我正试图绑定一个" onclick"事件到父组件/模板中的#sitenav对象。

menu.html(子模板)

<md-list-item *ngFor="let entry of entries">
    <button md-menu-item  (click)="sidenav.close()">
      <md-icon>{{entry.icon}}</md-icon>
      <span><a routerLink="{{entry.route}}">{{entry.link}}</a></span>
    </button>
</md-list-item>

menu.ts(子模板组件文件)

import { Component } from '@angular/core';

@Component({
    moduleId:module.id,
    selector: 'navlinks',
    templateUrl: 'menubtn.component.html'
})
export class MenuBtnComponent {
    entries = [];

@Output() buttonClicked : EventEmitter<any> = new EventEmitter();

   close(value:any){
    this.buttonClicked.emit("close");
   }

  constructor() {}

    ngOnInit() {
    this.entries = [
        {
            icon: 'home',
            route: '/',
            link:  'Home'
        },
        {
            icon: 'sentiment_satisfied',
            route: '/about',
            link:  'About Us'
        },
        {
            icon: 'content_paste',
            route: '/work',
            link:  'Out Work'
        },
        {
            icon: 'mail',
            route: '/contact',
            link:  'Get In Touch'
        },
    ];

   }
}

sitenav.ts(父模板组件)

import {Component, ViewChild, ViewEncapsulation, Directive} from '@angular/core';
import { MdMenuModule, MdMenuTrigger} from '@angular/material';

import { MenuBtnComponent } from './menubtn.component';


@Component({
  moduleId:module.id,
  encapsulation: ViewEncapsulation.Emulated,
  selector: 'sitenav',
  templateUrl: './sitenav.component.html',
  styleUrls: [ './sitenav.component.css']
})
export class SitenavComponent {
 clickedButton(val){
    console.log(val);
 }
}

sitenav.html(父模板)

 <!--sidenav-->
  <md-sidenav  
    #sidenav 
    class="app-sidenav md2 md-sidenav md-sidenav-side md-sidenav-closed"
    mode="side">
    <md-list flex="" role="list" class="flex">
      <navlinks (buttonClicked)="close($event)"></navlinks>
    </md-list>
  </md-sidenav>
 <!--//sidenav-->

点击后(click)="sidenav.close()"关闭#sitenav,但是从menu.html模板看似不可见,所以我收到错误:

Cannot read property 'close' of undefined

如何靠近#sidenav?

2 个答案:

答案 0 :(得分:1)

您无法直接从子级访问父组件方法。 Output()参数是达到您要求的最佳方式。

您的代码必须修改为

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

@Component({
    moduleId:module.id,
    selector: 'navlinks',
    templateUrl: 'menubtn.component.html'
})
export class MenuBtnComponent {
    @Output() buttonClicked : EventEmitter<string> = new EventEmitter<string>();
    entries = [];

  constructor() {}

    ngOnInit() {
        ....

   }
   close(value:any){
    this.buttonClicked.emit("close");
   }
}

您的HTML标记应为

 <md-list-item *ngFor="let entry of entries">
        <button md-menu-item  (buttonClicked)="close($event)">
      <md-icon>{{entry.icon}}</md-icon>
      <span><a routerLink="{{entry.route}}">{{entry.link}}</a></span>
    </button>
</md-list-item>

您的父组件应为

<md-list-item *ngFor="let entry of entries">
        <button md-menu-item  (buttonClicked)="close($event)">
          <md-icon>{{entry.icon}}</md-icon>
          <span><a routerLink="{{entry.route}}">{{entry.link}}</a></span>
        </button>
</md-list-item>

父组件ts文件应具有以下方法

 clickedButton(val){
    console.log(val);
 }

注意:访问close()方法的方式对于相反的情况是有效的。来自 ParentComponent ChildComponent 方法 很明显,#sideNav与子组件无关,以及如何访问close()方法?

答案 1 :(得分:0)

另一种可能的方法是通过事件总线服务

<强> eventbusservice.ts

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

export class EventBusService
{
    bus:Subject<Event> = new Subject<Event>();

    dispatch(data:Event){
        this.bus.next(data);
    }

    listen(type:string):Observable<Event> {
       return this.bus.filter(event=>event.type === type);
    }
}

<强> menu.ts

  import { Component, Output, EventEmitter } from '@angular/core';
  import { EventBusService } from './eventbusservice'
@Component({
    moduleId:module.id,
    selector: 'navlinks',
    templateUrl: 'menubtn.component.html'
})
export class MenuBtnComponent {
    entries = [];

  constructor(private eventbus:EventBusService) {}

    ngOnInit() {
        ....

   }
   close(){
    this.eventbus.dispatch("close");
   }
}

<强> sitenav.ts

import { Component, OnInit } from '@angular/core';
import {EventBusService} from './eventbusservice'

@Component({
    moduleId: module.id,
    selector: 'site-nav',
    templateUrl: 'sitenav.html'
})
export class SiteNavComponent implements OnInit {
    constructor(private eventbus:EventBusService) {
this.eventbus.listen("close").subscribe((e)=>{this.closeSomething()})

     }
closeSomething(){

}
    ngOnInit() { }
}

<强> menu.html

<md-list-item *ngFor="let entry of entries">
    <button md-menu-item  (click)="close()">
      <md-icon>{{entry.icon}}</md-icon>
      <span><a routerLink="{{entry.route}}">{{entry.link}}</a></span>
    </button>
</md-list-item>

当一个组件中的更改对许多组件产生影响时,此过程会有所帮助 其他组件(不只是父组件)。