Угловой 7 UI не обновляется после того, как подписка возвращает значения - PullRequest
0 голосов
/ 08 марта 2019

В отношении следующего кода может показаться, что пользовательский интерфейс не обновляется со значением, но я вижу, что значение установлено в правильное поле.

Я пробовал 2 различных подхода,bar не пробовал подход обнаружения изменений, так как, я полагаю, что в приведенном ниже коде должно работать.

В моем сервисе я слушаю событие окончания маршрута, причина этого в том, чточто что-то в сервисе нужно изменить в зависимости от наличия параметра в моем маршруте, например: '/page/:id'.

В одном сценарии URL может быть / page, вдругой, / page / 12, поэтому, основываясь на этом факте, мне нужно вернуть значение из двух разных сервисов, если идентификатор не существует, использовать SERVICE1, в противном случае использовать SERVICE2.

У меня в основном есть подписка, котораявозвращает значение из другой подписки.Для этого я полагаюсь на Subscribe для выдачи значения из внутренней подписки, что работает (см. Примеры ниже).Моя боль здесь в том, что пользовательский интерфейс не отображает значения.

ГЛАВНЫЙ СЕРВИС

Примечание: для краткости опущен полный класс, просто чтобы показать рассматриваемый метод:

  get getCourse(): Observable<CoursesDTO> {
    let subject = new Subject<CoursesDTO>();

    this.router.events.pipe(filter(e => e instanceof NavigationEnd))
      .subscribe(x => {       

        let course: CoursesDTO = {
          courseName: '',
          courseId: ''
        };

        const route = this.router.routerState.snapshot.root;

        let courseId: string = '';

        if (route.children.length >= 1) {
          const obj = route.children[route.children.length - 1];
          const value = (obj.params as any).value;

          // we have a courseID, interact with the course workflow
          if (!_.isEmpty(value)) {
            this.courseWorkflowProxy.interact(value.courseId, 'CourseMaterial', null)
              .subscribe((b: InteractionResponseDTO) => {

                const x: CourseDTO = <any>b.workflowResult;

                course = {
                  courseName: x.courseName,
                  courseId: x.courseId
                };

                subject.next(course);
                subject.complete();

                return course; // I don't feel this is necessary
              });
          }          
        }

        // we don't have the courseID, so assume there is a JWT token
        // for example, that authenticated the user + courseID
        // and we can get this in the code behind
        this.coursesProxy
          .getCourseInfo()
          .subscribe(b => {

            course = {
              courseName: b.courseName,
              courseId: b.courseid
            };

            subject.next(course);
            subject.complete();

            return course; // I don't feel this is necessary
          }); 
      });

    return subject;
  }

Обратите внимание, , этот код был изменен для представления кода, а не «фактический» сценарий, если он кажется неправильным, предназначен для демонстрации кода.

Реализация этого метода в компоненте под названием WatchBlock.ts, показывающая одно из возможных исправлений, которые я пробовал, через ngZone:

this.whatBlockService.getCourse.subscribe((r: CourseDTO) => {
  this._ngZone.run(() => {
    this.title = r.courseName;
    this.id = r.courseId;

    console.dir({ title: this.title, id: this.id }); // this prints the values to the console
  });
});

Следующие блоки кода «работают» в том смысле, чтоон возвращает искомые значения, однако, как указано, он не отображается в отображаемом HTML.

Файл HTML:

  <div fxLayout="row" fxLayoutAlign="start center">
    <div class="ml-16">
      <label class="identi">{{id}}</label>
    </div>
  </div>

  <div class="px-8 px-mat-16">
    <span class="mat-title">{{title}}</span>
  </div>

data_returned

Я также попробовал подход BehaviorSubject, и он мне тоже не помог.

Я не пробовал маршрут детектора изменений, так как чувствую, что ngZone должен делать изменениясамо обнаружение, если я понимаю, как работает зонирование.

Я не могу понять это, и был бы признателен за любую помощь от гуру там.

1 Ответ

0 голосов
/ 08 марта 2019

На самом деле, нет, выполнение кода в NgZone не гарантирует, что детектор изменений обнаружит изменения.Если для компонента или любого родительского компонента установлено значение ChangeDetectionStrategy.OnPush, он будет проверять только входные данные.Если вы не вызываете zone.runOutsideAngular, то (обычно) нет необходимости запускать ngZone.run.

Но вы можете попробовать ввести private _changeDetectorRef: ChangeDetectorRef и вызвать this._changeDetectorRef.markForCheck() в компонентном обратном вызове subscribe.markForCheck помечает компонент как измененный вручную при использовании стратегии OnPush. Docs

...