【问题标题】:Angular 2 : Cannot read property 'close' of undefinedAngular 2:无法读取未定义的属性“关闭”
【发布时间】:2017-07-08 17:48:57
【问题描述】:

我是 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 附近装箱?

【问题讨论】:

    标签: angular events binding scope eventemitter


    【解决方案1】:

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

    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>
    

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

    【讨论】:

    • 有趣。有理由不使用巴士服务吗?我刚开始使用 Angular 2 并希望尽可能接近标准,是否可以在每次需要侦听任何组件上的事件时导入 eventbusservice.ts?
    • 谢谢 Sai,但是你能告诉我上面使用 EventEmitter 选项的方法有什么问题吗?
    【解决方案2】:

    您不能直接从子组件访问父组件方法。 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() 方法?

    【讨论】:

    • HTML 标记和父组件在您的代码中是否相同?
    • 我已经更新了上面的代码,但没有任何反应。没有错误。 &lt;md-sidenav(父母)不应该在监听事件吗>
    • 它是如何特别针对#sidenav 元素来关闭它的?
    • 没用过,有什么替代品吗?
    • 谷歌远程桌面。我可以远程解决您的问题
    猜你喜欢
    • 2019-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-23
    • 2017-03-31
    • 2017-06-26
    • 1970-01-01
    相关资源
    最近更新 更多