Ссылка на угловой список не обновляется при удалении элемента - PullRequest
0 голосов
/ 31 августа 2018

Я реализую функцию, которая отображает выбранные элементы из иерархической структуры, справа.

slice.component.ts:

 import { Component, Input, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
    import * as API from '../../shared/api-routes';
    import { DataService } from '../../shared/service/data.service';
    import { TreeNode } from '../../shared/dto/TreeNode';
    import { Subject } from 'rxjs/Subject';

    import html from './slice.component.html';
    import css from './slice.component.css';

    @Component({
      selector: 'slice-component',
      template: html,
      providers: [DataService],
      styles: [css],
      changeDetection: ChangeDetectionStrategy.OnPush
    })

    export class SliceComponent {
      selections: TreeNode<string>[] = [];
      newList: TreeNode<string>[];

      constructor(dataService:DataService, cd:ChangeDetectorRef) {
        super(dataService, cd);
      }

      public onSliceChange(event:TreeNode<string>):void {
        if(event.selected) {
          this.selections.push(event);
        }
        else {
          var index = this.selections.indexOf(event);
          if(index > -1) {
            this.selections.splice(index, 1);
          }
        }
        this.newList = this.selections.slice();
      }

    }

slice.component.html:

<p>Slices</p>
<mat-input-container>
  <input #searchInput matInput placeholder="Search for Slices">
</mat-input-container>
<div class="flex-container">
<div class="SliceCheck" *ngIf="isDataLoaded">
  <fortune-select
     (sliceSelected)="onSliceChange($event)">
  </fortune-select>
</div>
<div class="sendToRight">
    <rightside-component
      [sliceTreeNode]="newList">
    </rightside-component>
</div>
</div>

rightside.component.ts:

import { Component, Input, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
import { TreeNode } from '../../shared/dto/TreeNode';

import html from './rightside.component.html';
import css from './rightside.component.css';

@Component({
  selector: 'rightside-component',
  template: html,
  providers: [DataService],
  styles: [css],
  changeDetection: ChangeDetectionStrategy.OnPush
})

export class RightSideComponent {
  @Input() sliceTreeNode: TreeNode<string>[];

  constructor(private cd: ChangeDetectorRef) {}

  getSlices() : TreeNode<string>[] {
    if (typeof(this.sliceTreeNode) == "undefined" || (this.sliceTreeNode) === null) {
      return [];
    }
    return this.sliceTreeNode;
  }

  deselect(item: TreeNode<string>): void {
    if((item.children) !== null) {
      item.children.forEach(element => {
        this.deselect(element);
      });
    }
    var index = this.sliceTreeNode.indexOf(item);
    if(index > -1) {
      this.sliceTreeNode.splice(index, 1);
    }
    item.selected = false;
  }

}

rightside.component.html:

  <ul class="selection-list" >
    <li *ngFor="let item of getSlices()">
      <button class="btn" (click)="deselect(item)" *ngIf="item.selected">
        <i class="fa fa-close"> {{ item.displayName }} </i>
      </button> 
    </li>
  </ul>

В моей реализации все работает как положено, пока не произойдет следующее:

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

Каким-то образом экземпляр списка в правом компоненте не обновляется при повторном выборе узла, который был ранее отменен.

Есть какие-нибудь отзывы о том, как это исправить? Это что-то похожее на этот plunkr я нашел в Интернете: http://next.plnkr.co/edit/1Fr83XHkY0bWd9IzOwuT?p=preview&utm_source=legacy&utm_medium=worker&utm_campaign=next&preview

1 Ответ

0 голосов
/ 31 августа 2018

Наиболее вероятная проблема заключается в том, что вы используете ChangeDetectionStrategy.OnPush и выполняете мутации в пределах onSliceChange SliceComponent без явного вызова cd.markForCheck().

Либо удалите changeDetection: ChangeDetectionStrategy.OnPush из SliceComponent, либо добавьте cd.markForCheck() в конец onSliceChange

Когда вы устанавливаете обнаружение изменений на OnPush, Angular гарантирует, что компонент будет обновляться только при изменении ссылок, переданных на его входы. onSliceChange не заменяет входные данные, поэтому компонент среза не будет обновлен.

Вам также следует рассмотреть возможность замены deselect в RightSideComponent на Output и обработки изменений в SliceComponent. Соглашение об одностороннем потоке данных состоит в том, чтобы изменять только общее состояние в общем родителе. Это предотвращает конфликты, когда два компонента хотят изменить какое-либо общее состояние.

...