【问题标题】:@Output with EventEmitter from child to parent, view doesn't update in parent@Output with EventEmitter 从子级到父级,视图不会在父级中更新
【发布时间】:2018-01-28 18:11:48
【问题描述】:

当在 map.component.ts 中单击标记时,它会将数据发送到 home.component.ts。这是通过这一行检测到的<x-map (change)="updateSelected($event)"></x-map>

所以当updateSelected 运行时,它会将opened 更新为true

当检查控制台日志时,它返回true,但工具栏中的{{ opened }}sidenav 仍然有opened 作为false

当我稍微调整窗口大小时,home.component.ts 的视图会更新,工具栏中的{{ opened }} 会显示true,并且sidenav 会打开。

我该如何解决这个问题?

home.component.html

<mat-toolbar color="primary" class="mat-elevation-z6">
  <mat-toolbar-row>
    <span fxLayoutAlign="start center">
      <button mat-icon-button (click)="toggleSidenav()">
        <mat-icon aria-label="Example icon-button with a heart icon">menu</mat-icon>
      </button>
      {{ opened }}
    </span>
  </mat-toolbar-row>
</mat-toolbar>

<mat-sidenav-container fullscreen class="sidenav-container">
  <mat-sidenav #sidenav mode="side" [opened]="opened" class="mat-elevation-z6">
    Sidenav content
  </mat-sidenav>
  <mat-sidenav-content>
    <x-map (change)="updateSelected($event)"></x-map>
  </mat-sidenav-content>
</mat-sidenav-container>

home.component.ts

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

    @Component({
      selector: 'x-home',
      templateUrl: './home.component.html',
      styleUrls: ['./home.component.scss']
    })
    export class HomeComponent implements OnInit {

      constructor() { }
      opened = false;

      updateSelected($event) {
        console.log($event);
        this.opened = true;
        console.log(this.opened);
      }   
    }

ma​​p.component.ts

import { Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core';
import { ApiService } from '../api.service';
import { } from '@types/googlemaps';

@Component({
  selector: 'x-map',
  templateUrl: './map.component.html',
  styleUrls: ['./map.component.scss']
})
export class MapComponent implements OnChanges, OnInit {
  constructor(private apiService: ApiService) { }
  map: any;
  markersArray: any[] = [];
  devices: any;    
  @Output() change: EventEmitter<any> = new EventEmitter();

  markerClick(marker) {
    google.maps.event.addListener(marker, 'click', () => {
      this.change.emit(this.devices.find(d => d.ChargeDeviceId === marker.title));
    });
  }

  plot() {
    for (let i = 0; i < this.devices.length; i++) {
      const marker = new google.maps.Marker({
        map: this.map,
        position: new google.maps.LatLng(this.devices[i].ChargeDeviceLocation.Latitude, this.devices[i].ChargeDeviceLocation.Longitude),
        title: this.devices[i].ChargeDeviceId,
      });
      this.markerClick(marker);
      this.markersArray.push(marker);
    }
  }

  ngOnChanges() {
    console.log(this.resize);
    if (this.resize) {
      this.onResize();
    }
  }

  ngOnInit() {
    this.apiService.get().subscribe(
      (res) => {
        this.devices = res['ChargeDevice'];
        this.plot();
      },
      (err) => {
        console.log(err);
      }
    );

    this.map = new google.maps.Map(document.getElementById('map'), {
      center: {lat: 54.797753, lng: -2.871329},
      zoom: 8
    });
  }
}

【问题讨论】:

    标签: javascript angular angular5 eventemitter


    【解决方案1】:

    我可以通过导入ApplicationRef 然后将this.app.tick(); 添加到我的updateSelected() 函数的末尾来解决此问题。

    import { ApplicationRef, Component, Input, OnInit, SimpleChanges } from '@angular/core';
    
    @Component({
      selector: 'x-home',
      templateUrl: './home.component.html',
      styleUrls: ['./home.component.scss']
    })
    export class HomeComponent implements OnInit {
    
      constructor(private app: ApplicationRef) { }
      opened = false;
    
      toggleSidenav() {
        this.opened = !this.opened;
      }
    
      setSidenav(val: boolean) {
        this.opened = val;
      }
    
      updateSelected($event) {
        console.log($event);
        this.opened = true;
        console.log(this.opened);
        this.app.tick();
      }
    
      ngOnInit() {
      }
    }
    

    【讨论】:

      【解决方案2】:

      您的属性未更新的原因是未按预期触发更改检测。未运行更改检测的原因是您的谷歌地图方法的回调在角度区域之外运行

      要强制该代码在角度区域内运行,您可以使用NgZone 将其包装起来,如下所示:

      import { ..., ..., NgZone } from '@angular/core';  // <= IMPORT
      
      //...
      
      export class MapComponent implements OnChanges, OnInit {
          constructor(private zone: NgZone, ...) { }   // <= INJECT
      
          // ....
      
          markerClick(marker) {
              google.maps.event.addListener(marker, 'click', () => {
                  this.zone.run(() => {   // <= USE
                      this.change.emit(this.devices.find(d => d.ChargeDeviceId === marker.title));
                  });    
              });
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-04-04
        • 2020-06-22
        • 2021-05-26
        • 1970-01-01
        • 2015-08-14
        • 2018-09-26
        • 2019-10-11
        • 1970-01-01
        相关资源
        最近更新 更多