简体   繁体   English

Angular4 ngOnInit rxjs /主题不起作用

[英]Angular4 ngOnInit rxjs/Subject not working

I have Directive which has Subscription for resize chart 我有Directive ,其中包含用于尺寸调整图的Subscription

import {Directive, ElementRef, HostListener, Input, OnDestroy, OnInit} from '@angular/core';
import {Subscription} from 'rxjs/Subscription';
import echarts from 'echarts';
import 'echarts/theme/macarons';
import {ChartService} from '../service/chart/chart.service';

@Directive({selector: '[appECharts]'})
export class EChartsDirective implements OnInit, OnDestroy {
  element: ElementRef;
  subscription: Subscription;
  @Input() eChartsOptions: any;
  @Input() theme = 'macarons';
  private chart;

  constructor(element: ElementRef, private chartsService: ChartService) {
    this.element = element;
  }

  ngOnInit() {
    this.subscription = this.chartsService.chartChange.subscribe((str) => {
      this.resizeChart(str);
    });
    this.chart = echarts.init(this.element.nativeElement, this.theme);
    if (this.eChartsOptions) {
      this.chart.setOption(this.eChartsOptions);
    }
  }

  ngOnDestroy() {
    if (this.chart) {
      this.chart = null;
    }
    this.subscription.unsubscribe();
  }

  resizeChart(str: string) {
    console.log('resize from=' + str);
    setTimeout(() => {
      if (this.chart) {
        console.log('resize');
        this.chart.resize();
      }
    }, 500);
  }

  @HostListener('window:resize')
  onResize() {
    this.resizeChart('window');
  }
}

ChartService: 的ChartService:

import {Injectable} from '@angular/core';
import {Subject} from 'rxjs/Subject';

@Injectable()
export class ChartService {
  chartChange = new Subject<string>();
  orderChartChanged = new Subject<any[]>();
  private orderCharts: any[];

  setChartData(orderCharts) {
    this.orderCharts = orderCharts;
    this.orderChartChanged.next(this.orderCharts);
  }

  updateCharts(srt: string) {
    console.log('from=' + srt);
    this.chartChange.next(srt);
  }
}

And Component where I calling updateCharts method 还有我调用updateCharts方法的组件

import {Component, ElementRef, OnDestroy, OnInit, ViewChild} from '@angular/core';
import {ChartHttpService} from '../../shared/service/chart/chart-http.service';
import {MdSnackBar} from '@angular/material';
import {Subscription} from 'rxjs/Subscription';
import {ChartService} from '../../shared/service/chart/chart.service';
import echarts from 'echarts';
import 'echarts/theme/macarons';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnDestroy, OnInit {
  chartSubscription: Subscription;
  @ViewChild('chart1') element: ElementRef;
  chart2;

  constructor(private chartService: ChartService,
              private chartHttpService: ChartHttpService,
              public snackBar: MdSnackBar) {
  }

  ngOnInit() {
    const chart = echarts.init(this.element.nativeElement, 'macarons');
    this.chartSubscription = this.chartService.orderChartChanged
      .subscribe(
        (response: any) => {
          const option = response.orderAmount;
          chart.setOption(option);
          setTimeout(() => {
            chart.resize();
          }, 500);
          this.chart2 = option;
          this.chartService.updateCharts('home');
        }
      );
    this.chartHttpService.orderCharts(this.snackBar);
  }

  ngOnDestroy() {
    this.chartSubscription.unsubscribe();
    this.chart2 = null;
  }

  onResize() {
    this.chartService.updateCharts('btn');
  }

}

ChartHttpService: ChartHttpService:

import {Injectable} from '@angular/core';
import {MdSnackBar} from '@angular/material';
import {HttpClient} from '@angular/common/http';

import {TranslateService} from '@ngx-translate/core';
import {Observable} from 'rxjs/Observable';
import 'rxjs/Rx';
import {SnackBarUtils} from '../snack-bar-utils';
import {environment} from '../../../../environments/environment';
import {ChartService} from './chart.service';

@Injectable()
export class ChartHttpService {
  private static orderCharts = 'json/chart/ordersChart';

  constructor(private http: HttpClient,
              private chartService: ChartService,
              private translate: TranslateService) {
  }

  orderCharts(snackBar: MdSnackBar) {
    const url = environment.apiUrl + ChartHttpService.orderCharts;
    this.http.get(url)
      .catch(error => {
        return Observable.throw(error);
      })
      .subscribe(
        response => this.chartService.setChartData(response),
        error => SnackBarUtils.showLocalizedSnackBar(this.translate, snackBar, 'msg.error')
      );
  }
}

And html component: 和html组件:

<div class="row">
  <div class="col-lg-6 col-md-6 col-xs-12 col-sm-6">
    <md-card>
      <div class="box-header">Base Line</div>
      <div #chart1 style="height: 300px;"></div>
    </md-card>
  </div>
  <div class="col-lg-6 col-md-6 col-xs-12 col-sm-6">
    <md-card>
      <div class="box-header">Stacked Line</div>
      <ng-container *ngIf="chart2">
        <div appECharts [eChartsOptions]="chart2" style="height: 300px;"></div>
      </ng-container>
    </md-card>
  </div>
  <button (click)="onResize()">Resize</button>
</div>

So the problem is when I press refresh in browser or f5 , updateCharts method invokes in HomeComponent but chartChange Subject didn't work I guess, because in EChartsDirective subscription didn't invoke method resizeChart , and this problem is ONLY after refresh or f5 . 所以,当我按下问题是refresh在浏览器或f5updateCharts方法调用中HomeComponentchartChange主题没有工作我猜的,因为在EChartsDirective认购不调用方法resizeChart ,之后只有这个问题是refreshf5 If i click on Resize btn, everything works fine. 如果我单击“调整btn大小”,一切正常。

So i don't know why, but subscription in EChartsDirective didn't invoke resizeChart after refresh or f5 . 所以我不知道为什么,但是在refreshf5之后, EChartsDirective subscription未调用resizeChart

Any ideas why its happens? 任何想法为什么会发生?

UPDATE: And problem only with chart2 , I add chart1, which i init manually(without Directive) in HomeComponent -> ngOnInit , and when i'm calling 更新:而且只有chart2问题,我添加了chart2 ,我在HomeComponent -> ngOnInit手动init (没有指令),并且在调用时

setTimeout(() => {
            chart.resize();
          }, 500);

It works, but of course, problem only with Subscription, but still) 它有效,但当然仅订阅有问题,但仍然)

UPDATE2: Change to: UPDATE2:更改为:

   ngOnInit() {
   this.chart = echarts.init(this.element.nativeElement, this.theme);
   if (this.eChartsOptions) {
     this.chart.setOption(this.eChartsOptions);
   }
   this.subscription = this.chartsService.chartChange.subscribe((str) => {
     this.resizeChart(str);
   });
 }

nothing changed 没有改变

Log after browser refresh or F5 browser refreshF5后登录

from=home-123

Log after click to Resize btn 单击以调整btn大小后登录

from=xxx        chart.service.ts:16
resize from=xxx echarts.directive.ts:37 
resize          echarts.directive.ts:40 
 ngOnInit() {
    this.subscription = this.chartsService.chartChange.subscribe((str) => {
      this.resizeChart(str);
    });
    this.chart = echarts.init(this.element.nativeElement, this.theme);
    if (this.eChartsOptions) {
      this.chart.setOption(this.eChartsOptions);
    }
  }

Here you set this.chart after you subscribe to Subject , while in resizeChart you check if this.chart is defined. 在这里,您订阅Subject 之后设置了this.chart ,而在resizeChart您检查了this.chart是否已定义。 It might fail just because it is still null at that point. 它可能仅因为此时仍为空而失败。 Try to set this.chart before subscribing to Subject . 订阅Subject之前,请尝试设置this.chart

ok so i add this.resizeChart(str); 好的,所以我添加this.resizeChart(str); in ngOnInit method in EChartsDirective, and after each chart init, i have resize effect, so it's works for me 在EChartsDirective的ngOnInit方法中,并且在每次图表初始化之后,我都有调整大小的效果,所以它对我有用

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

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