Угловая двусторонняя привязка передает неполные данные из-за ChangeDetectionStrategy - PullRequest
0 голосов
/ 28 августа 2018

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

slice.component.ts:

import { Component, Input, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
import * as API from '../../shared/api-routes';
import { BasestepComponent } from '../basestep-component/basestep.component';
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 extends BasestepComponent<string> implements OnInit {
  selections: string[] = [];
  newList: string[];

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

  ngOnInit() {

  }

  public onSliceChange(event:string):void {
    this.newList = [];
    this.selections.push(event);
    this.newList = this.selections;
    console.log(this.selections); //this has all the items selected
  }

}

slice.component.html:

  <fortune-select
 (sliceSelected)="onSliceChange($event)">
  </fortune-select>
  <rightside-component
      [sliceNodes]="newList">
  </rightside-component>

rightside.component.ts:

import { Component, Input, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
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 implements OnInit {
  @Input() sliceNodes: string[];

  constructor(private cd: ChangeDetectorRef) {}

  ngOnInit() {

  }


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

}

rightside.component.html:

<ul class="selection-list">
    <li *ngFor="let item of sliceNodes">
      <button class="btn" >
        <i class="fa fa-close"> {{ item }} </i>
      </button> 
    </li>
</ul>

В правостороннем компоненте присутствует только первый выбранный элемент, который отображается справа. Я вижу, что все выбранные элементы присутствуют в "this.newList" в slice.component.ts

Однако весь список не передается компоненту правых сторон. sliceNodes получает только первый элемент. Я хочу, чтобы все элементы в списке были перенесены.

Я использую ChangeDetectionStrategy.OnPush, поэтому он не распознает изменения, которых нет в @ Input.

Как мне это исправить? Любая помощь приветствуется!

1 Ответ

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

Вы можете преобразовать источник данных правого компонента в BehaviorSubject и затем использовать асинхронный канал, чтобы использовать его в разметке. Я создал примитив StackBlitz здесь .

Компонент:

import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';
import { BehaviorSubject } from 'rxjs';

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

export class AppComponent  {
  list1 = ['item 1', 'item 2', 'item 3'];
  list2 = [];

  listSubject = new BehaviorSubject<string[]>([]);

  onItemClick(item: string){
  this.list2.push(item);
  this.listSubject.next(this.list2);
    }
}

При щелчке элемента в списке он добавляется в массив list2. Затем вызовите метод next () в listSubject, чтобы уведомить подписчиков о необходимости действовать.

Markup:

<label>Click item to select:</label>
<div style="border: 1px solid">
  <ul *ngFor="let item of list1" style="list-style: none;">
    <li (click)="onItemClick(item)">{{ item }}</li>
  </ul>
</div>
<label>Selected items:</label>
<div style="border: 1px solid">
  <ul *ngFor="let item of listSubject | async" style="list-style: none;">
    <li>{{ item }}</li>
  </ul>
</div>

Разметка использует «асинхронный» канал, чтобы использовать тему списка и будет обновляться всякий раз, когда будут выдвинуты новые изменения. Я думаю, что это приведет вас в правильном направлении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...