Angular Tree Component Checkboxes 多选框用法

咸弘雅
2023-12-01

1、terminal.module.ts

......

// Angular Tree Component
import { TreeModule } from 'angular-tree-component';
import {DepartmentTreeComponent} from "app/entities/terminal/department-tree.component";
......

@NgModule({
  imports: [TreeModule.forRoot()],
  exports: [DepartmentTreeComponent],
  declarations: [
    DepartmentTreeComponent
  ],
  entryComponents: [DepartmentTreeComponent],
  providers: [],
  schemas: []
})
export class FaceMachineTerminalModule {
  constructor() {
  }
}

2、terminal-update.component.ts

import { Component, OnInit } from '@angular/core';
import { HttpResponse, HttpErrorResponse } from '@angular/common/http';
import { FormBuilder, Validators } from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import { Observable } from 'rxjs';
import { filter, map } from 'rxjs/operators';
import * as moment from 'moment';
import { DATE_TIME_FORMAT } from 'app/shared/constants/input.constants';
import { JhiAlertService } from 'ng-jhipster';
import { ITerminal, Terminal } from 'app/shared/model/terminal.model';
import { TerminalService } from './terminal.service';
import { IDepartment } from 'app/shared/model/department.model';
import { DepartmentService } from 'app/entities/department';
import {NgbModal} from "@ng-bootstrap/ng-bootstrap";
import {DepartmentTreeComponent} from "app/entities/terminal/department-tree.component";

@Component({
  selector: 'jhi-terminal-update',
  templateUrl: './terminal-update.component.html'
})
export class TerminalUpdateComponent implements OnInit {
  isSaving: boolean;

  departments: IDepartment[];

  nodes = [];

  selected_node_id: number;

  selected_node_name: string;

  editForm = this.fb.group({
    id: [],
    terminalNumber: [null, [Validators.required, Validators.maxLength(100)]],
    terminalName: [null, [Validators.required, Validators.maxLength(100)]],
    softwareVersion: [null, [Validators.maxLength(100)]],
    terminalDescribe: [null, [Validators.maxLength(100)]],
    terminalStatus: [],
    createdTime: [],
    updateTime: [],
    remarks: [null, [Validators.maxLength(100)]],
    departments: []
  });

  constructor(
    protected jhiAlertService: JhiAlertService,
    protected terminalService: TerminalService,
    protected departmentService: DepartmentService,
    protected activatedRoute: ActivatedRoute,
    private fb: FormBuilder,
    private modalService: NgbModal
  ) {}

  ngOnInit() {
    this.isSaving = false;
    this.activatedRoute.data.subscribe(({ terminal }) => {
      this.updateForm(terminal);
    });
    this.departmentService
      .query()
      .pipe(
        filter((mayBeOk: HttpResponse<IDepartment[]>) => mayBeOk.ok),
        map((response: HttpResponse<IDepartment[]>) => response.body)
      )
      .subscribe((res: IDepartment[]) => (this.departments = res), (res: HttpErrorResponse) => this.onError(res.message));
  }

  updateForm(terminal: ITerminal) {
    this.editForm.patchValue({
      id: terminal.id,
      terminalNumber: terminal.terminalNumber,
      terminalName: terminal.terminalName,
      softwareVersion: terminal.softwareVersion,
      terminalDescribe: terminal.terminalDescribe,
      terminalStatus: terminal.terminalStatus,
      createdTime: terminal.createdTime != null ? terminal.createdTime.format(DATE_TIME_FORMAT) : null,
      updateTime: terminal.updateTime != null ? terminal.updateTime.format(DATE_TIME_FORMAT) : null,
      remarks: terminal.remarks,
      departments: terminal.departments
    });
  }

  previousState() {
    window.history.back();
  }

  save() {
    this.isSaving = true;
    const terminal = this.createFromForm();
    if (terminal.id !== undefined) {
      this.subscribeToSaveResponse(this.terminalService.update(terminal));
    } else {
      this.subscribeToSaveResponse(this.terminalService.create(terminal));
    }
  }

  private createFromForm(): ITerminal {
    const entity = {
      ...new Terminal(),
      id: this.editForm.get(['id']).value,
      terminalNumber: this.editForm.get(['terminalNumber']).value,
      terminalName: this.editForm.get(['terminalName']).value,
      softwareVersion: this.editForm.get(['softwareVersion']).value,
      terminalDescribe: this.editForm.get(['terminalDescribe']).value,
      terminalStatus: this.editForm.get(['terminalStatus']).value,
      createdTime:
        this.editForm.get(['createdTime']).value != null ? moment(this.editForm.get(['createdTime']).value, DATE_TIME_FORMAT) : undefined,
      updateTime:
        this.editForm.get(['updateTime']).value != null ? moment(this.editForm.get(['updateTime']).value, DATE_TIME_FORMAT) : undefined,
      remarks: this.editForm.get(['remarks']).value,
      departments: this.editForm.get(['departments']).value
    };
    return entity;
  }

  protected subscribeToSaveResponse(result: Observable<HttpResponse<ITerminal>>) {
    result.subscribe((res: HttpResponse<ITerminal>) => this.onSaveSuccess(), (res: HttpErrorResponse) => this.onSaveError());
  }

  protected onSaveSuccess() {
    this.isSaving = false;
    this.previousState();
  }

  protected onSaveError() {
    this.isSaving = false;
  }
  protected onError(errorMessage: string) {
    this.jhiAlertService.error(errorMessage, null, null);
  }

  trackDepartmentById(index: number, item: IDepartment) {
    return item.id;
  }

  getSelected(selectedVals: Array<any>, option: any) {
    if (selectedVals) {
      for (let i = 0; i < selectedVals.length; i++) {
        if (option.id === selectedVals[i].id) {
          return selectedVals[i];
        }
      }
    }
    return option;
  }

  open() {
    const modalRef = this.modalService.open(DepartmentTreeComponent);
    modalRef.componentInstance.allDepartments = this.departments;
    modalRef.result.then(result => {
      var selected_node = result.toString().split(',');
      this.selected_node_id = selected_node[0];
      this.selected_node_name = selected_node[1];
    });
  }

}

3、terminal-update.component.html

......
<input type="text" class="form-control" name="departments" id="field_departments"
                           formControlName="departments" (click)="open()" [(ngModel)]="selected_node_name" />
......

4、department-tree.component.ts

import {NgbActiveModal} from '@ng-bootstrap/ng-bootstrap';
import {Component, Input, OnInit} from "@angular/core";
import {FormBuilder} from "@angular/forms";
import {IDepartment} from "app/shared/model/department.model";
import {ITreeOptions} from "angular-tree-component";
import {IActionMapping} from "angular-tree-component/dist/models/tree-options.model";

@Component({
  selector: 'department-tree',
  templateUrl: './department-tree.component.html'
})
export class DepartmentTreeComponent implements OnInit {

  @Input() allDepartments;

  departmentTreeForm = this.fb.group({
    id: [''],
    name: [''],
  });

  departments: IDepartment[];

  actionMapping: IActionMapping = {
    mouse: {
      click: (tree, node) => this.check(node, !node.data.checked)
    }
  };

  options: ITreeOptions = {
    actionMapping: this.actionMapping
  };

  nodes = [];

  tree(data) {
    // 删除所有children,以防止多次调用。
    data.forEach(function (item) {
      delete item.children;
    });
    // 将数据存储为以ID为KEY的map索引数据列
    var map = {};
    data.forEach(function (item) {
      map[item.id] = item;
    });
    var val = [];
    data.forEach(function (item) {
      // 以当前遍历项的pid,去map对象中找到索引的ID。
      var parent = map[item.pid];
      // 如果找到索引,那么说明此项不在顶级当中,那么需要把此项添加到,他对应的父级中。
      if (parent) {
        (parent.children || (parent.children = [])).push(item);
      } else {
        // 如果没有在map中找到对应的索引ID,那么直接把当前的item添加到val结果集中,作为顶级。
        val.push(item);
      }
    });
    return val;
  }

  selected_node_id = '';
  selected_node_name = '';

  constructor(
    public activeModal: NgbActiveModal,
    private fb: FormBuilder) {
  }

  loadAll() {
    if (this.allDepartments.length > 0) {
      for (let i = 0; i < this.allDepartments.length; i++) {
        this.nodes.push({
          id: this.allDepartments[i].id,
          name: this.allDepartments[i].departmentName,
          pid: this.allDepartments[i].departmentParent
        });
      }
      this.nodes = this.tree(this.nodes);
    }
  }

  ngOnInit() {
    this.loadAll();
  }

  public check(node, checked) {
    this.updateChildNodeCheckbox(node, checked);
    //this.updateParentNodeCheckbox(node.realParent);
  }

  public updateChildNodeCheckbox(node, checked) {
    node.data.checked = checked;
    if (checked) {
      alert(node.data.name);
    }
    if (node.children) {
      node.children.forEach((child) => this.updateChildNodeCheckbox(child, checked));
    }
  }

  public updateParentNodeCheckbox(node) {
    if (!node) {
      return;
    }

    let allChildrenChecked = true;
    let noChildChecked = true;

    for (const child of node.children) {
      if (!child.data.checked || child.data.indeterminate) {
        allChildrenChecked = false;
      }
      if (child.data.checked) {
        noChildChecked = false;
      }
    }

    if (allChildrenChecked) {
      node.data.checked = true;
      node.data.indeterminate = false;
    } else if (noChildChecked) {
      node.data.checked = false;
      node.data.indeterminate = false;
    } else {
      node.data.checked = true;
      node.data.indeterminate = true;
    }
    this.updateParentNodeCheckbox(node.parent);
  }

  departmentTree() {
    this.activeModal.close(this.selected_node_id + "," + this.selected_node_name);
  }

}

5、department-tree.component.html

<form class="form" role="form" (ngSubmit)="departmentTree()" [formGroup]="departmentTreeForm">
    <div class="modal-header">
        <h4 class="modal-title">
            <label class="form-control-label" jhiTranslate="faceMachineApp.department.departmentParent">Department
                Parent</label>
        </h4>
        <button type="button" class="close" aria-label="Close" (click)="activeModal.dismiss('Cross click')">
            <span aria-hidden="true">&times;</span>
        </button>
    </div>
    <div class="modal-body">
        <p>
            <tree-root [options]="options" [nodes]="nodes">
                <ng-template #treeNodeTemplate let-node="node" let-index="index">
                    <input
                        (change)="check(node, !node.data.checked)"
                        type="checkbox"
                        [indeterminate]="node.data.indeterminate"
                        [checked]="node.data.checked">
                    {{ node.data.name }}
                </ng-template>
            </tree-root>
        </p>
    </div>
    <div class="modal-footer">
        <div>
            <button type="button" id="cancel-save" class="btn btn-secondary"
                    (click)="activeModal.dismiss('Cross click')">
                <fa-icon [icon]="'ban'"></fa-icon>&nbsp;<span jhiTranslate="entity.action.cancel">Cancel</span>
            </button>
            <button type="submit" id="save-entity" class="btn btn-primary">
                <fa-icon [icon]="'save'"></fa-icon>&nbsp;<span jhiTranslate="entity.action.save">Save</span>
            </button>
        </div>
    </div>
</form>

参考:https://github.com/500tech/angular-tree-component/blob/a44013417043c3544906d436b28bafe3a56a1d75/example/cli4/src/app/checkboxes/checkboxes.component.ts

 类似资料: