Тема поведения показывает только начальное значение / Тема воспроизведения не показывает обновленное значение - PullRequest
0 голосов
/ 07 апреля 2020

Фон:

У меня есть сервис, где у меня есть открытая карта слоев. Компонент карты имеет собственный сервис.

При нажатии значка появляется всплывающее окно. В этом всплывающем окне находится кнопка, которая при нажатии извлекает некоторые данные из объекта, отображаемого во всплывающем окне, а затем перемещается к другому компоненту.

Я пытаюсь опубликовать / добавить эти данные в тему поведения, а затем подписаться на них в новом компоненте. Данные добавляются в тему поведения при нажатии на значок. У всплывающего компонента есть свой сервис.

В целевом компоненте я пытаюсь подписаться на тему поведения всплывающих сервисов в шаблоне с помощью асинхронной c трубы.

Проблема:

Наблюдаемое на субъекте поведения возвращает только начальное значение. Следующая функция объекта поведения, похоже, не добавляет к нему новые данные. Это всегда дает новое значение.

Когда используется тема воспроизведения, ничего не отображается. Следующая функция просто не имеет никакого эффекта.

Код:

Всплывающая служба

_analysisBehaviourSubject: BehaviorSubject<any> = new BehaviorSubject();


// other code

addElement(element: any) {
    console.log('adding new element to behaviour subject', element);
    this._analysisBehaviourSubject.next(element);
}

getElement$(): Observable<any> {
    return this._analysisBehaviourSubject.asObservable();
}

Служба карт

getAnalysisBehaviourSubject(): Observable<any> {
    return this.clusPopupService.getElement$();
}

Служба назначения

getAnalysisBehaviourSubject(): Observable<any> {
    return this.mapService.getAnalysisBehaviourSubject();
}

Тогда в компоненте назначения есть просто асинхронный c канал.

То, что я уже пробовал:

  1. импорт субъекта поведения непосредственно из всплывающего сервиса без его перемещения по структуре моего проекта.

  2. с использованием субъекта поведения вместо субъекта воспроизведения, как показано в примере кода.

  3. Добавление всех трех сервисов в массив провайдеров в app.module.ts. Субъект поведения по-прежнему излучает исходное значение, а субъект воспроизведения - вообще ничего.

Обновление: Всплывающая служба

import { DataPreparationService } from './data-preparation.service';
import { GeneralService } from '../../general.service';
import { Injectable } from '@angular/core';
import OlMap from 'ol/Map';
import OlView from 'ol/View';
import { fromLonLat } from 'ol/proj';
import Overlay from 'ol/Overlay';
import Point from 'ol/geom/Point.js';
import { SourceDataObject } from '../../Models/sourceDataObj';
import { Select } from 'ol/interaction';
import { CookieService } from 'ngx-cookie-service';
import { StoreService } from 'src/app/store.service';

@Injectable({
  providedIn: 'root'
})
export class ClusterPopupService {
  // analysis variables
  deltaEX = 1;
  deltaEy = 3;
  overlayCoords: object = {};
  sourceDataObj: SourceDataObject = { element: '', coordinates: null };
  detectedPoints: Point[] = [];

  // pop up variables
  foundIcon: SourceDataObject;
  newPoint: Point;
  generalSelect: Select;
  num = 0;
  // analysis page Behaviour Subjects
  constructor(
    private genService: GeneralService,
    private dataPrepService: DataPreparationService,
    private cookies: CookieService,
    private store: StoreService
  ) {}

  // behaviour subject m1ethods

  //cluster methods
  filterPoints(newPoint: Point) {
    const newPointCoords: number[] = newPoint.getCoordinates();

    if (this.detectedPoints.length >= 1) {
      for (let i = 0; i <= this.detectedPoints.length - 1; i++) {
        const savedPointCoords = this.detectedPoints[i].getCoordinates();
        if (
          savedPointCoords[0] === newPointCoords[0] &&
          savedPointCoords[1] === newPointCoords[1]
        ) {
          break;
        } else if (i === this.detectedPoints.length - 1) {
          this.detectedPoints.push(newPoint);
        }
      }
    } else {
      this.detectedPoints.push(newPoint);
    }
  }
  async clearFeatureCache() {
    this.foundIcon = undefined;
    this.generalSelect.getFeatures().clear();
    this.detectedPoints = null;
  }
  pushToCookies(currView: OlView) {
    this.cookies.deleteAll();
    const currCoordinates: number[] = currView.getCenter();
    const longitudeString: string = currCoordinates[0].toString();
    const latitudeString: string = currCoordinates[1].toString();
    const zoomLevelString: string = currView.getZoom().toString();
    this.cookies.set('longitude', longitudeString, 1 / 48);
    this.cookies.set('latitude', latitudeString, 1 / 48);
    this.cookies.set('zoom', zoomLevelString, 1 / 48);
    console.log(
      this.cookies.get('longitude'),
      this.cookies.get('latitude'),
      this.cookies.get('zoom')
    );
  }

  async preparePopup(
    fishCoords: SourceDataObject[],
    munitCoords: SourceDataObject[],
    wrackCoords: SourceDataObject[],
    sedimentCoords: SourceDataObject[],
    generalSelect: Select,
    view: OlView,
    globalMap: OlMap,
    localDoc?: Document
  ) {
    const extent: number[] = view.calculateExtent(globalMap.getSize());
    const container = localDoc.getElementById('popup');
    const content = localDoc.getElementById('popup-content');
    const closer = localDoc.getElementById('popup-closer');
    const analyseButton = localDoc.getElementById('analyseButton');

    const popUpOverlay: Overlay = new Overlay({
      element: container,
      autoPan: true
    });
    this.generalSelect = generalSelect;
    closer.onclick = () => {
      popUpOverlay.setPosition(undefined);
      this.foundIcon = undefined;
      generalSelect.getFeatures().clear();
      this.detectedPoints = null;

      this.newPoint = null;

      closer.blur();
      return false;
    };

    globalMap.addOverlay(popUpOverlay);
    generalSelect.on('select', event => {
      this.newPoint = event.selected[0].getGeometry() as Point;

      this.foundIcon = this.dataPrepService.binSearch(
        wrackCoords,
        this.newPoint.getCoordinates(),
        'wrack Array'
      );

      if (this.foundIcon === undefined) {
        this.foundIcon = this.dataPrepService.binSearch(
          sedimentCoords,
          this.newPoint.getCoordinates(),
          'sediment array'
        );
      }
      if (this.foundIcon === undefined) {
        this.foundIcon = this.dataPrepService.binSearch(
          fishCoords,
          this.newPoint.getCoordinates(),
          'fish array'
        );
      }

      if (this.foundIcon === undefined) {
        this.foundIcon = this.dataPrepService.binSearch(
          munitCoords,
          this.newPoint.getCoordinates(),
          'munition array'
        );
      }
      if (this.foundIcon !== undefined) {
        this.sourceDataObj = this.foundIcon;
        popUpOverlay.setPosition(fromLonLat(this.foundIcon.coordinates));
      } else {
        if (this.sourceDataObj === null) {
          this.sourceDataObj = { element: '', coordinates: null };
          this.sourceDataObj.element = 'not found';
          console.log(this.genService.backEndUri);
        }
        this.sourceDataObj.element = 'not found';
        popUpOverlay.setPosition(this.newPoint.getCoordinates());
      }
      console.log('the icon found is:', this.foundIcon);
      switch (this.sourceDataObj.element) {
        case 'sediment':
          content.innerHTML =
            '<p>You clicked on a <code>' +
            this.sourceDataObj.element +
            '</code> with coordinates <code>' +
            this.sourceDataObj.coordinates +
            '</code>, and  ID <code>' +
            this.sourceDataObj.sampleId +
            '</code>. Analyse this element?</p><p><button onclick="window.location.href=\'' +
            this.genService.localUri +
            '/analyseSediment' +
            '\'"' +
            'id="analyseButton">Analyse</button></p>';
          this.sourceDataObj = null;
          this.pushToCookies(view);
          break;
        case 'fish':
          this.store.addElement(this.sourceDataObj.miscData);

          content.innerHTML =
            '<p>You clicked on a <code>' +
            this.sourceDataObj.element +
            '</code> with coordinates <code>' +
            this.sourceDataObj.coordinates +
            '</code>,  cruise ID <code>' +
            this.sourceDataObj.miscData.cruiseId +
            '</code> and target ID <code>' +
            this.sourceDataObj.miscData.sampleId +
            '</code>. Analyse this element?</p><p><button onclick="window.location.href=\'' +
            this.genService.localUri +
            '/analyseFish' +
            '\'"' +
            ' id="analyseButton">Analyse</button></p>';

          this.sourceDataObj = null;
          this.pushToCookies(view);

          break;
        case 'Munition':
          content.innerHTML =
            '<p>You clicked on a <code>' +
            this.sourceDataObj.element +
            '</code> with coordinates <code>' +
            this.sourceDataObj.coordinates +
            '</code>,  cruise ID <code>' +
            this.sourceDataObj.miscData.cruiseId +
            '</code> and target ID <code>' +
            this.sourceDataObj.miscData.targetId +
            '</code>. Analyse this element?</p><p><button onclick="window.location.href=\'' +
            this.genService.localUri +
            '/analyseMunition' +
            '\'"' +
            'id="analyseButton">Analyse</button></p>';
          this.sourceDataObj = null;
          this.pushToCookies(view);
          break;
        case 'wrack':
          content.innerHTML =
            '<p>You clicked on a <code>' +
            this.sourceDataObj.element +
            '</code> with coordinates <code>' +
            this.sourceDataObj.coordinates +
            '</code>, and  target ID <code>' +
            this.sourceDataObj.miscData.targetId +
            '</code>. Analyse this element?</p><p><button onclick="window.location.href=\'' +
            this.genService.localUri +
            '/analyseWrack' +
            '\'"' +
            ' id="analyseButton">Analyse</button></p>';
          this.sourceDataObj = null;
          this.pushToCookies(view);
          break;
        case 'not found':
          content.innerHTML =
            '<p>You selected more than one Icon. Please Zoom in and select only one for analysis</p>';
          break;
        default:
          content.innerHTML =
            '<p>The map feature wasn"t quite selected. Please close the pop up and retry</p>';
          break;
      }
    });
  }
}

Служба хранилища

import { Injectable } from '@angular/core';
import { BehaviorSubject, ReplaySubject } from 'rxjs';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class StoreService {
  _analysisBehaviourSubject: BehaviorSubject<any> = new BehaviorSubject();
  analysis$: Observable<any> = this._analysisBehaviourSubject.asObservable();
  constructor() {
    console.log('I AM THE STORE');
  }

  addElement(element: any) {
    console.log('adding new element to behaviour subject', element);
    this._analysisBehaviourSubject.next(element);
  }
  getElement$(): Observable<any> {
    return this.analysis$;
  }
}

Ответы [ 2 ]

1 голос
/ 07 апреля 2020

Я понял это. Шаблон объекта и его оттенки работают нормально.

В моем всплывающем сервисе выше я перехожу к компоненту через href. Мое лучшее предположение состоит в том, что это разрушает дерево компонентов, и экземпляр службы, которая содержит значения, также уничтожается.

Хотя я не могу доказать это, я попытался реализовать тему воспроизведения, которая будет обновляться при переходе от одного компонента к другому, а затем подписываться на него, когда я был на новом компоненте в моем проекте, и это сработало просто хорошо. Так что я прикалываю это к использованию href.

Нужно найти другой способ маршрутизации к моему компоненту после нажатия кнопки во внутреннем html для открытых слоев.

Спасибо всем, кто нашел время, чтобы прочитать или ответить на это.

0 голосов
/ 07 апреля 2020

Я думаю, что происходит то, что вы создаете новую наблюдаемую при каждом вызове getElement $ () с помощью функции asObservable (). Я чувствую, документы не ясны на 100%.

Я предлагаю создать наблюдаемое на уровне класса, а не на уровне метода.

в вашей всплывающей службе вы можете сделать это:

_analysisBehaviourSubject: ReplaySubject<any> = new ReplaySubject();
_analysis$: Observable<any> = this._analysisBehaviourSubject.asObservable();

В качестве альтернативы, вы можете подписаться на тему напрямую, поскольку она расширяет Observable.

...