将检测从子级更改为父级

时间:2018-08-06 22:21:09

标签: html angular typescript data-binding angular5

我正在尝试在我的UI中启用功能,该功能将在选择/取消选择时动态显示选择。

import { Wizard } from './report-common';
import { Router } from '@angular/router';
import { DataService } from './../shared/service/data.service';
import { TreeNode } from './../shared/dto/TreeNode';
import { Component, OnInit } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import 'rxjs/Rx';
import * as STEPS from '../shared/constants';

import html from './report-builder.component.html';
import css from './report-builder.component.css';

@Component({
  selector: 'report-builder',
  template: html,
  providers: [DataService],
  styles: [css]
})

export class ReportBuilderComponent implements OnInit {
  selectedProductLine:    TreeNode<string>[];
  rightside:              Wizard  = new Wizard([STEPS.PRODUCT_LINE]);
  productLineSubject              = new Subject<TreeNode<string>[]>();
  //this allows the html to access the constants
  HTML_STEPS                      = STEPS;

  constructor (private dataService: DataService, private router: Router) {}

  ngOnInit() {
    this.productLineSubject.subscribe((productline) => this.productLineChange(productline));
  }

  public productLineChange(productLine: TreeNode<string>[]):void {
    this.selectedProductLine = productLine;
    this.rightside.setSelection(this.extractDisplayNames(productLine), STEPS.PRODUCT_LINE);
  }

  private extractDisplayNames <T>(nodes: TreeNode<T>[]): string[] {
    return nodes.map(node => node.displayName);
  }

}

html相关代码:

<div *ngFor="let step of rightside.steps">
  <li *ngIf="!step.hidden">
    <rightside-component class="side-button" [selectionSubject]="step.selections">
    </rightside-component>
  </li>
</div>

“向导”的结构如下:(report-common.ts)

import { DataService } from './../shared/service/data.service';
import { TreeNode } from './../shared/dto/TreeNode';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

export class WizardStep {
  selections: BehaviorSubject<any[]> = new BehaviorSubject<any[]>([]);

}

export class Wizard {
  currentComponent:WizardStep;
  steps:WizardStep[];

  public setSelection(selections:any[], component:string) {
    let componentStep = this.steps.find(step => step.component === component);
    if(!componentStep) { return; }
    componentStep.selections.next(selections);
  }

}

Rightside-component.ts:

export class RightSideComponent implements OnInit {
  selections: string[];
  @Input() selectionSubject: BehaviorSubject<string[]>;

  constructor(private cd: ChangeDetectorRef) {}

  ngOnInit() {
    this.selectionSubject.subscribe((selections) => {
        this.selections = selections;
        this.cd.detectChanges();
      });
  }
}

Rightside.component.html:

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">

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

在这里,我在列表中每个项目的前面添加了一个删除图标。每当单击该按钮时,不仅该项目应从列表中消失,而且应从更改它的原始结构中取消选择。

我在这里尝试使用changedetection,但是没有按预期工作。

我基本上想使用Angular 5和我的数据结构执行与此http://next.plnkr.co/edit/1Fr83XHkY0bWd9IzOwuT?p=preview&utm_source=legacy&utm_medium=worker&utm_campaign=next&preview类似的操作。从这一点上如何前进的任何想法将不胜感激。如果需要任何其他代码,请告诉我。

2 个答案:

答案 0 :(得分:0)

这很容易做到。仅使用Pipe即可。

首先,在显示列表(如Rightside.component.html)中,您没有创建指定的选择。使用筛选出取消选择项。最后,您可以设置所选内容,它会动态显示。

Rightside.component.html

<div>
  <ul class="selection-list">
    <li *ngFor="let item of STEP | unselect_filter">
     <!-- I couldn't found your data list , so let STEP instead. -->
      <button class="btn">
        <i class="fa fa-close">
          {{item}}
        </i>
      </button>
    </li>
  </ul>
</div>

filter.pipe.ts

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
    name: 'unselect_filter'
})
export class MyFilterPipe implements PipeTransform {
    transform(items: any[], filter: Object): any {
        return items.filter(item => !item.select);
    }
}

答案 1 :(得分:0)

I think your object structure of **rightside.steps** is like this

[{
'selections':['xyz','abc'],
....
},
{
'selections':['shm','bsm'],
....
}];

by changing the object structure to the following

[{
'selections':[{
'isSelected': true,
'name':'xyz'
},{
'isSelected': true,
'name':'abc'
}],
....
},
{
'selections':[{
'isSelected': true,
'name':'shm'
},{
'isSelected': true,
'name':'bsm'
}],
....
}]

you can show/hide on the list

<div>
  <ul class="selection-list">
    <li *ngFor="let item of selections" [hidden]="!item.isSelected">
      <button class="btn" (click)="removeItem(item)">
        <i class="fa fa-close">
          {{item}}
        </i>
      </button>
    </li>
  </ul>
</div>

export class RightSideComponent implements OnInit {
  selections: string[];
  @Input() selectionSubject: BehaviorSubject<string[]>;

  constructor(private cd: ChangeDetectorRef) {}
   @Output() unSelectItem= new EventEmitter<any>();

    removeItem(item) {
      item.isSelected = false;
      this.unSelectItem.emit(item);
    }
}

*ReportBuilderComponent html*

<div *ngFor="let step of rightside.steps">
  <li *ngIf="!step.hidden">
    <rightside-component (unSelectItem)="unSelectItem(item)" class="side-button" [selectionSubject]="step.selections">
    </rightside-component>
  </li>
</div>

export class ReportBuilderComponent implements OnInit {
  // Your existing code

  unSelectItem(item){
   for(var step of rightside.steps){
      for(var selectionItem of step.selections){
        if(selectionItem === item){
           selectionItem.isSelected = false;
        }
    }
   }
  }


}