Обнаружение изменений углового массива - PullRequest
0 голосов
/ 14 ноября 2018

Я новичок в Angular, и я не могу найти правильное решение для моей проблемы.

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

Я отправляю логический массив состояний флажков из filterComponent через itemsListComponent в singleItemComponent, и он работает нормально. Моя проблема - обнаружение изменений. Когда я использовал NgDoCheck с отличиями, он работает всегда, когда я нажимаю на кнопку-флажок и кнопку фильтра, а не только кнопку фильтра.

Я попробовал NgOnChanges, но он работал только один раз, а затем не увидел изменений значений в массиве.

Это мой SingleItemsComponent (я думаю, вам не нужны другие, чтобы помочь мне решить эту проблему). Посмотрите на это и покажите мне, пожалуйста, любой пример решения этой проблемы.

import { Component, OnInit, OnChanges,ViewChild, AfterViewInit, Inject,     Input, DoCheck, KeyValueDiffer, KeyValueDiffers, SimpleChanges, SimpleChange,     ChangeDetectionStrategy, ChangeDetectorRef, IterableDiffers } from     '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { animate, state, style, transition, trigger } from     '@angular/animations';
import { MatTableDataSource, MatPaginator, MatSort,     throwToolbarMixedModesError } from '@angular/material';
import { IPOLine } from 'src/app/models/po-line';
import { POLineService } from 'src/app/services/po-line.service';
@Component({
  selector: 'app-po-lines-list',
  templateUrl: './po-lines-list.component.html',
  styleUrls: ['./po-lines-list.component.css'],
  animations: [
    trigger('detailExpand', [
      state('collapsed', style({ height: '0px', minHeight: '0', display:     'none' })),
      state('expanded', style({ height: '*' })),
      transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4,     0.0, 0.2, 1)')),
    ]),
  ],
})
export class POLinesListComponent implements OnInit, DoCheck{
  isLogged = false;
  login: string;
  dataSource = new MatTableDataSource<IPOLine>();
  expandedElement: IPOLine;
  errorMessage: string;
  response: any;
  today = new Date(); // (1990, 0, 1);
  isLoadingList = true;

  differ: any;

  @Input() sentData: boolean[];
  _sentData = this.sentData;
  ngDoCheck(){

    var changes = this.differ.diff(this._sentData);
    if (changes){
      console.log('changes detected changes detected changes detected     changes detected changes detected ');
    }
    else
    console.log('changes not detected changes not detected changes not     detected changes not detected ');
  }


  @ViewChild(MatPaginator) paginator: MatPaginator;
  @ViewChild(MatSort) sort: MatSort;

  constructor(
    //private cd: ChangeDetectorRef,
    private differs: KeyValueDiffers,
    private _POLineService: POLineService,
    private activatedRoute: ActivatedRoute) {
      this.differ = differs.find({}).create();
  }

  ngOnInit() {
    // Assign the data to the data source for the table to render
    this.login = this.activatedRoute.snapshot.paramMap.get('login');
    this._POLineService.getUserPOLines(this.login)
      .subscribe(data => {
        this.dataSource.data = data;
          },
        error => {
          this.errorMessage = <any>error;
          this.isLoadingList = false;
        }
        ,
        () => {
          // console.log('eee' + this.dataSource.data);
          this.isLoadingList = false;
          this.dataSource.data.forEach(x => x.isExpired = new     Date(x.PromisedDate) < new Date() ? true : false);
        }
      );

    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
  }
}

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

FilterComponent.ts:

import { Component, OnInit, Output, EventEmitter, Input } from '@angular/core';

@Component({
  selector: 'app-filters',
  templateUrl: './filters.component.html',
  styleUrls: ['./filters.component.css']
})
export class FiltersComponent implements OnInit {

  @Output() filterByClass = new EventEmitter();
  filterByTTR = false;
  filterByTBR = false;
  filters:boolean[] = [];
  constructor() { }

  ngOnInit() {
  }

log() {
  if(!this.filterByTTR)
   console.log('TTR not checked');
   else
   console.log('TTR checked');
  if (!this.filterByTBR)
   console.log('TBR not checked');
   else
   console.log('TBR checked');
   this.filters[0] = this.filterByTTR;
   this.filters[1] = this.filterByTBR;

   this.filterByClass.emit(this.filters);
}

Часть FilterComponent.html:

<mat-card-content class="col">
<mat-checkbox [checked]="filterByTTR" (change)="filterByTTR = !filterByTTR">TTR</mat-checkbox>
<mat-checkbox [checked]="filterByTBR" (change)="filterByTBR = !filterByTBR">TBR</mat-checkbox>
<!-- <mat-checkbox [(ngModel)]="filterByTBR"ref-TBR>TBR</mat-checkbox> -->
<div class="d-flex justify-content-between">
  <button mat-raised-button  color="primary">Clear</button>
  <button mat-raised-button (click)="log()" color="primary">Apply</button>
</div>

PoLinesCompoenent.ts:

import { Component, OnInit, NgModule, ViewChild, Input } from 
'@angular/core';

@Component({
  selector: 'app-po-lines',
  templateUrl: './po-lines.component.html',
  styleUrls: ['./po-lines.component.css']
})    
export class POLinesComponent implements OnInit {
  count: boolean[];
  constructor() { }    
  ngOnInit(){}      
  displayCounter(count) {
    console.log('first value is: ' + count[0] + ' second value is: ' +     count[1]);
    this.count = count;
  }

PoLinesComponent.html:

<div class="container">
  <div class="row">
    <div class="side-bar col">
      <app-filters (data)='displayCounter($event)'></app-filters>
    </div>
    <div class="content col">
      <app-po-lines-list [sentData]="count"></app-po-lines-list>
    </div>
  </div>
</div>

Ответы [ 2 ]

0 голосов
/ 14 ноября 2018

Вы можете использовать сеттер со входом, чтобы обнаружить изменения, если родительский элемент изменил вход «sentData».Функция установки будет вызываться каждый раз, когда вход изменяется снаружи.Например, вы можете сделать что-то вроде:

  @Input('sentData') 
  set sentData(value:any){
     //this function will be called whenever value of input changes. the value parameter will contain the new changed 
      this._sentData=value;
      //things to perform on change go here
  }
  _sentData;

См. Эту ссылку для получения дополнительной информации об обнаружении изменения ввода: Перехватить изменение свойства @Input в Angular Надеюсь, это поможет.

Если значение, переданное во входные данные через parent, не является примитивным типом, тогда angular не будет обнаруживать изменения в этом объекте, и метод set не будет вызываться в потомке, то есть POLinesListComponent.Для исправления этой проблемы и обнаружения вашего изменения вы можете использовать функцию Object.assign javascript, которая изменит ссылку на this.count, тем самым запустив обнаружение изменения угла.Вы можете сделать что-то вроде следующего в вашей функции displayCounter:

displayCounter(count) {
    console.log('first value is: ' + count[0] + ' second value is: ' +     count[1]);
    //if count is changed, then only trigger change.
    if(JSON.stringify(this.count)!=JSON.stringify(count))
    {

      this.count= []; 
      Object.assign(this.count, count);
    }

  }

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

0 голосов
/ 14 ноября 2018

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

...