简体   繁体   English

@Output与EventEmitter从子级到父级,父级中的视图未更新

[英]@Output with EventEmitter from child to parent, view doesn't update in parent

When a marker is clicked in map.component.ts, it emits the data to home.component.ts. 在map.component.ts中单击标记时,它将数据发送到home.component.ts。 This is detected by this line <x-map (change)="updateSelected($event)"></x-map> 此行<x-map (change)="updateSelected($event)"></x-map>

So when updateSelected is run it updates opened to true . 因此,当运行updateSelected时,它将更新openedtrue

When checking the console log it returns with true but the {{ opened }} in the toolbar and the sidenav still have opened as false . 当检查控制台日志时,它返回true但是工具栏中的{{ opened }}sidenav仍为false opened

When I resize the window slightly the view of home.component.ts updates and {{ opened }} in the toolbar shows true and the sidenav opens. 当我稍微调整窗口大小时, home.component.ts的视图将更新,并且工具栏中的{{ opened }}显示为true ,并且sidenav打开。

How can I overcome this issue? 我该如何克服这个问题?

home.component.html 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 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 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
    });
  }
}

I was able to fix this by importing ApplicationRef and then adding this.app.tick(); 我能够通过导入ApplicationRef然后添加this.app.tick();来解决此问题this.app.tick(); to the end of my updateSelected() function. 到我的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() {
  }
}

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 . 而未运行更改检测的原因是,您的google maps方法的回调是在角度区域之外运行的

To force that code to be run within the angular zone, you can wrap it with NgZone like this: 要强制该代码在角度区域内运行,可以使用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));
            });    
        });
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM