@Output与EventEmitter从子级到父级,父级中的视图未更新 [英] @Output with EventEmitter from child to parent, view doesn't update in parent

查看:74
本文介绍了@Output与EventEmitter从子级到父级,父级中的视图未更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在map.component.ts中单击标记时,它将数据发送到home.component.ts.可以通过此行< x-map(change)="updateSelected($ event)"></x-map>

When a marker is clicked in map.component.ts, it emits the data to home.component.ts. This is detected by this line <x-map (change)="updateSelected($event)"></x-map>

因此,当运行 updateSelected 时,它会将 opened 更新为 true .

So when updateSelected is run it updates opened to true.

在检查控制台日志时,它会返回 true ,但工具栏中的 {{已打开}} sidenav 仍具有打开 false .

When checking the console log it returns with true but the {{ opened }} in the toolbar and the sidenav still have opened as false.

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

When I resize the window slightly the view of home.component.ts updates and {{ opened }} in the toolbar shows true and the sidenav opens.

我该如何克服这个问题?

How can I overcome this issue?

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);
      }   
    }

map.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
    });
  }
}

推荐答案

未更新您的媒体资源的原因是未按预期触发变更检测.之所以没有运行更改检测,是因为您的google maps方法的回调是在角度区域之外运行的.

The reason for your property not being updated is that change detection is not triggered as you expect it to. And the reason that change detection is not run is because the callback for your google maps method is run outside of the angular zone.

要强制该代码在角度区域内运行,可以用 NgZone 包裹它,如下所示:

To force that code to be run within the angular zone, you can wrap it with NgZone like this:

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));
            });    
        });
    }
}

这篇关于@Output与EventEmitter从子级到父级,父级中的视图未更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆