如何设置材料动态树视图每个节点彼此独立

时间:2019-11-13 12:02:52

标签: angular tree angular-material

我已经实现了动态树嵌套视图组件。可以添加或删除新的子节点。 在每个节点中都有mat-select,mat-input和mat-autocomplete。

我现在有一个问题,如果我通过mat-autocomplete在输入字段中选择一个属性,那么所有其他带有mat-autocomplete的输入字段也会被更改。 如果添加新节点,则输入字段的值始终为null或为空。 但这不是我所期望的。

我的问题是,如何设置动态添加的每个节点彼此独立?

现在我显示我的代码。

HTML如下所示:

<mat-tree [dataSource]="nestedDataSource" [treeControl]="nestedTreeControl" class="dynamic-filter-tree" #treeSelector>
  <mat-nested-tree-node *matTreeNodeDef="let node">
    <li>
      <div class="mat-tree-node">
        <button mat-icon-button
                matTreeNodeToggle
                [attr.aria-label]="'toggle ' + node.field"
                *ngIf="node.predicates.length>0">
          <mat-icon class="mat-icon-rtl-mirror">
            {{nestedTreeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
          </mat-icon>
        </button>
        <mat-form-field class="dynamic-filter-operator">

          <mat-select placeholder="Operator"
                      [(ngModel)]="node.op"
                      name="matSelect">
            <ng-container *ngFor="let operator of operators">
              <mat-option [value]="operator.key">
                {{operator.value}}
              </mat-option>
            </ng-container>
          </mat-select>

        </mat-form-field>
        <span style="padding-left: 10px"></span>
        <div *ngIf="node.op !== operatorConstants.AND && node.op !== operatorConstants.OR">
          <mat-form-field appearance="legacy">
            <input matInput type="text" [formControl]="locationField" [(ngModel)]="node.field" name="node" [matAutocomplete]="auto" placeholder="Field"/>
            <mat-autocomplete #auto="matAutocomplete">
              <mat-option *ngFor="let filteredFieldResult of locationFieldResults" [value]="filteredFieldResult">
                {{filteredFieldResult}}
              </mat-option>
            </mat-autocomplete>
          </mat-form-field>
        </div>
        <div class="dynamic-filter-add-delete-button">
          <button
            mat-icon-button
            (click)="addNewItem(node)">
            <mat-icon>add</mat-icon>
          </button>
          <button *ngIf="node.predicates.length ===0 && node.level!==0 "
                  mat-icon-button
                  (click)="remove(node)"
                  class="dynamic-filter-delete-button">
            <mat-icon>delete</mat-icon>
          </button>
        </div>
      </div>
      <ul [class.dynamic-filter-tree-invisible]="!nestedTreeControl.isExpanded(node)">
        <ng-container matTreeNodeOutlet></ng-container>
      </ul>
    </li>
  </mat-nested-tree-node>
</mat-tree>

在此HTML文件中,您可以看到一个输入字段,该字段将实现自动完成功能。

此HTML的.ts文件如下:

export class DynamicFilterComponent implements OnInit {
  @ViewChild('treeSelector') public tree: any;

  public nestedTreeControl: NestedTreeControl<LocationFilterUiModel>;
  public nestedDataSource: MatTreeNestedDataSource<LocationFilterUiModel>;
  public operators = [];
  public operatorConstants = LocationFilterOperator;
  public locationField: FormControl = new FormControl();
  public locationFieldResults = LOCATION_FILTER_FIELD;

  constructor(private database: DynamicFilterDataService,
              private dialogRef: MatDialogRef<DynamicFilterComponent>,
              private searchDataService: SearchDataService) {
    this.nestedTreeControl = new NestedTreeControl<LocationFilterUiModel>(this._getChildren);
    this.nestedDataSource = new MatTreeNestedDataSource();

    database.dynamicFilterRawData.subscribe(data => this.nestedDataSource.data = data);

    this.locationField.valueChanges.subscribe(inputField => {
        this.filterField(inputField);
      }
    );
  }

  public ngOnInit(): void {
    this.getOperators();
  }

  private _getChildren = (node: LocationFilterUiModel) => node.predicates;

  public addNewItem(node: LocationFilterUiModel): void {
    this.database.insertItem(node, '');
    this.nestedTreeControl.expand(node);
    this.renderChanges();
  }

  public remove(node: LocationFilterUiModel): void {
    this.database.removeItem(node, this.database.data[0]);
    this.renderChanges();
  }

  public renderChanges(): void {
    const data = this.nestedDataSource.data;
    this.nestedDataSource.data = null;
    this.nestedDataSource.data = data;
  }

  public closeDialog(): void {
    this.dialogRef.close();
  }

  private getOperators(): void {
    SUPPORTED_OPERATORS.forEach((operator) => {
      const operatorConstant: OperatorConstants = {
        key: operator.key,
        value: operator.value
      };
      this.operators.push(operatorConstant);
    });
  }

  private filterField(value: string): string[] {
    if (value) {
      this.locationFieldResults = LOCATION_FILTER_FIELD.filter((searchFieldResult) => {
        return searchFieldResult.indexOf(value) !== -1;

      });
    } else {
      this.locationFieldResults = LOCATION_FILTER_FIELD;
    }
    return this.locationFieldResults;
  }
}

enter image description here

从这张照片中您可以看到我已经动态创建了2个新节点(1和2),但是具有自动完成功能的输入字段取决于2.输入字段。

谁有解决方案?

0 个答案:

没有答案