Выражение MatExpansionPanel изменилось после того, как была проверена ошибка 'mat-extended: true' - PullRequest
0 голосов
/ 22 февраля 2019

У меня есть список запросов панели расширения угловых материалов:

  @ViewChildren(MatExpansionPanel)
  matExpansionPanelQueryList: QueryList<MatExpansionPanel>;

и простой массив:

questions: [];

Панели расширения генерируются с *ngFor: упрощенно, например:

   <ng-container *ngFor="let question of questions>
            <mat-expansion-panel
               ...

Когда я расширяю массив вопросов, я хочу открыть последнюю панель расширения.

     extendQuestion() {
        this.matExpansionPanelQueryList.changes.subscribe(
          change => {
            change.last.open();
          }
        );

        this.questions.push('some-new-item');
      }

Это прекрасно работает - я вставляю элемент в массив,
панель ExpansionPanels перерисовывается, создается новая панель Panel, и она фактически открывается - моя проблема в том, что она генерирует в консоли следующую ошибку:

ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has 
changed after it was checked. Previous value: 'mat-expanded: false'. Current 
value: 'mat-expanded: true'.

Есть ли способ избежать этого?
Я пытался использовать changeDetectorRef и markForCheck() в подписке, но сообщение об ошибке не исчезло (и, честно говоря, я на 100% уверен, что именно здесь проблема).

Обновление : Пример проблемы с Stackblitz (нажмите кнопку "+")

Ответы [ 3 ]

0 голосов
/ 22 февраля 2019

Я нашел решение проблемы.

По ссылке, упомянутой @iLuvLogix, принудительное обнаружение изменений решило проблему:

    constructor(private cd: ChangeDetectorRef) {}

    this.matExpansionPanelQueryList.changes.subscribe(
      change => {
        change.last.open();
        this.cd.detectChanges();
      }
    );
0 голосов
/ 22 февраля 2019

Вы можете использовать javascript для достижения решения
Демонстрация Stackblitz только с javascript

После обновления массива вопросов вы можете использовать javascript,
и я использую setTimeout(()=>{}, 0), чтобы поместить эту задачу в конец event-loop
, чтобы она выполнялась после выполнения angular при выполнении DOM-манипуляции.

  this.questions.push('some-new-item');
        setTimeout(
          ()=>{
           const lastExpansionPanel:HTMLElement =   
           document.getElementsByTagName('mat-expansion-panel')
           [document.getElementsByTagName('mat-expansion-panel').length-1]
           .querySelector('mat-expansion-panel-header');

          lastExpansionPanel.click();
          }, 0
        );
0 голосов
/ 22 февраля 2019

С angularindepth :

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

Работающее приложение Angular представляет собой дерево компонентов.Во время обнаружения изменений Angular выполняет проверки для каждого компонента, который состоит из следующих операций, выполняемых в указанном порядке:

  • обновить привязанные свойства для всех дочерних компонентов / директив
  • , вызвать ngOnInit, OnChanges иngDoCheck перехватывает жизненный цикл всех дочерних компонентов / директив
  • обновляет DOM для текущего компонента
  • запускает обнаружение изменений для дочернего компонента
  • вызывает ngAfterViewInit hook жизненного цикла для всех дочерних компонентов / директив

После каждой операции Angular запоминает, какие значения он использовал для выполнения операции.Они хранятся в свойстве oldValues ​​представления компонента.

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

Это должно работать для вас:

Вы можете добавить constructor для определения изменений (cd) и вызвать его после change.last.open();

import {ChangeDetectorRef, Component, OnInit, QueryList, ViewChildren} from '@angular/core';

import {MatDialog, MatExpansionPanel} from '@angular/material';

@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})

export class AppComponent {
questions = ['first', 'second'];

constructor(private cd: ChangeDetectorRef) {
    }

@ViewChildren(MatExpansionPanel) matExpansionPanelQueryList: QueryList<MatExpansionPanel>;


extendQuestion() {
        this.matExpansionPanelQueryList.changes.subscribe(
        change => {
            change.last.open();
            this.cd.detectChanges();
        }
        );
        this.questions.push('some-new-item');
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...