@WidgetComponent

nm-tree-grid

File

src/app/shared/widgets/tree-grid/tree-grid.component.ts

Implements

OnDestroy

Metadata

providers DataListService
selector nm-tree-grid
styleUrls tree-grid.component.scss
templateUrl ./tree-grid.component.html

Index

Widget inputs
Widget outputs
Properties
Methods

Constructor

constructor(authHttp: HttpClient, scrollService: ScrollService)
Parameters :
Name Type Optional
authHttp HttpClient no
scrollService ScrollService no

Methods

Public clearColumnFilter
clearColumnFilter(input: any, column: any)
Parameters :
Name Type Optional
input any no
column any no
Returns : void
Protected configureWidget
configureWidget(configuration: WidgetConfig)
Decorators : WidgetConfigure
Parameters :
Name Type Optional
configuration WidgetConfig no
Returns : void
Protected doReset
doReset()
Returns : void
Public formatIncomingData
formatIncomingData(treeData: )
Parameters :
Name Optional
treeData no
Returns : {}
handleRowSelection
handleRowSelection(event: )
Parameters :
Name Optional
event no
Returns : void
ngOnDestroy
ngOnDestroy()
Returns : void
Public onColumnFilterInput
onColumnFilterInput(input: any, column: IgxColumnComponent)
Parameters :
Name Type Optional
input any no
column IgxColumnComponent no
Returns : void
onRowSelection
onRowSelection(event: )
Parameters :
Name Optional
event no
Returns : void
Public stopPropagation
stopPropagation(event: , field: )
Parameters :
Name Optional
event no
field no
Returns : boolean

Properties

Public _id
_id:
Decorators : WidgetId
Public allowFiltering
allowFiltering: boolean
Type : boolean
Public authHttp
authHttp: HttpClient
Type : HttpClient
Private clearFiltersAndSortingChannel
clearFiltersAndSortingChannel: ReplaySubject<any>
Type : ReplaySubject<any>
Default value : new ReplaySubject<any>()
Decorators : WidgetInput
Public columnFilterInputs
columnFilterInputs: any
Type : any
Default value : {}
Public columns
columns: Column[]
Type : Column[]
Default value : []
Public configuration
configuration: WidgetConfig<DataListConfiguration>
Type : WidgetConfig<DataListConfiguration>
Decorators : WidgetConfiguration
Public data
data: any[]
Type : any[]
Default value : []
Public dataType
dataType: string
Type : string
Public disableSelection
disableSelection: boolean
Type : boolean
Public fallback
fallback: string
Type : string
Default value : contextPath + "/assets/placeholder_281x202.jpg"
Public filterMode
filterMode: string
Type : string
Public foreignKey
foreignKey: string
Type : string
Public header
header:
Public hideOnEmpty
hideOnEmpty: boolean
Type : boolean
Default value : false
Public hideTable
hideTable: Subject<boolean>
Type : Subject<boolean>
Default value : new ReplaySubject<boolean>()
Decorators : WidgetInput

The hide that should be used to hide tree grid

Public infoText
infoText: string
Type : string
Default value : "list.results"
Public inputBoxes
inputBoxes: QueryList<ElementRef>
Type : QueryList<ElementRef>
Decorators : ViewChildren
Private inputChannel
inputChannel: ReplaySubject<any>
Type : ReplaySubject<any>
Default value : new ReplaySubject<any>()
Decorators : WidgetInput

The uri that should be used to fetch the data

Private inputData
inputData: Subject<any>
Type : Subject<any>
Default value : new Subject<any>()
Decorators : WidgetInput

Display already fetched data

Public isCollapsible
isCollapsible:
Public multiSelection
multiSelection: boolean
Type : boolean
Default value : true
Public primaryKey
primaryKey: string
Type : string
Private resetChannel
resetChannel: ReplaySubject<any>
Type : ReplaySubject<any>
Default value : new ReplaySubject<any>()
Decorators : WidgetInput
Public results
results: Subject<any[]>
Type : Subject<any[]>
Default value : new BehaviorSubject([])
Decorators : WidgetOutput
Public selectedItem
selectedItem: Subject<any>
Type : Subject<any>
Default value : new Subject<any>()
Decorators : WidgetOutput
Public selectedItems
selectedItems: Subject<any>
Type : Subject<any>
Default value : new Subject<any>()
Decorators : WidgetOutput

Emits all selected items whenever they change

Public selectedUiLocale
selectedUiLocale:
Default value : new ReplaySubject<any>(1)
Decorators : WidgetInput
Public selection
selection: boolean
Type : boolean
Default value : false
Public tableHeight
tableHeight: string
Type : string
Public title
title:
Public total
total: number
Type : number
Public treeGrid
treeGrid: IgxTreeGridComponent
Type : IgxTreeGridComponent
Decorators : ViewChild
Public treeHeight
treeHeight: string
Type : string
Private unsubscribe
unsubscribe:
Default value : NgUnsubscribe.create()
Public wikiLink
wikiLink: string
Type : string
Public withHeader
withHeader: boolean
Type : boolean
Default value : true
import {
  Component,
  ElementRef,
  OnInit,
  QueryList,
  ViewChild,
  ViewChildren,
  HostListener,
  OnDestroy,
} from "@angular/core";
import {
  WidgetComponent,
  WidgetId,
  WidgetConfiguration,
  WidgetConfigure,
  WidgetInput,
  WidgetOutput,
} from "../widget.metadata";
import {
  WidgetConfig,
  getOrDefault,
  throwIfUndefined,
} from "../widget.configuration";
import {
  empty as observableEmpty,
  of as observableOf,
  timer as observableTimer,
  Observable,
  Subject,
  BehaviorSubject,
  ReplaySubject,
} from "rxjs";
import {
  distinctUntilChanged,
  withLatestFrom,
  map,
  takeUntil,
  debounceTime,
  switchMap,
  mergeMap,
  catchError,
} from "rxjs/operators";
import { NgUnsubscribe } from "../../ng-unsubscribe";
import { DataListService } from "../data-list/data-list.service";
import { HttpClient } from "@angular/common/http";
import { Link, MultiSelectAction, Resource } from "../../components/hal/hal";
import {
  IgxColumnComponent,
  IgxStringFilteringOperand,
  IgxTreeGridComponent,
} from "@infragistics/igniteui-angular";
import { ScrollService } from "../../components/scroll/scroll.service";

declare var contextPath: string;

interface Column {
  field: string;
  header: string;
  width: number;
  filter?: boolean;
  sort?: boolean;
  sortable?: boolean;
  type?: string;
  linkTemplate?: string;
  linkType?: string;
  pinned?: boolean;
  "filter-type"?: "contains" | undefined;
}

interface DataListConfiguration {
  title: string;
  columns: Column[];
  defaultPageSize: number;
  debounceTime: number;
  dataType: string;
  header: string;
  infoText: string;
  wikiLink: string;
  isCollapsible: boolean;
  attributeUrl: string;
  localStorageShownAttributes: string;
  withHeader: boolean;
  allowFiltering: boolean;
}
export interface Result extends Resource {
  description?: string;
  identifier?: string;
}

export interface ResultResource extends Resource {
  total?: number;
  _embedded?: {
    products: Result[];
  };
  _actions?: {
    multiSelect: MultiSelectAction;
  };
  _links?: {
    custom: Link;
  };
}

@WidgetComponent("nm-tree-grid")
@Component({
  providers: [DataListService],
  selector: "nm-tree-grid",
  styleUrls: ["./tree-grid.component.scss"],
  templateUrl: "./tree-grid.component.html",
})
export class TreeGridComponent implements OnDestroy {
  public data: any[] = [];
  public dataType: string;
  public total: number;
  public columns: Column[] = [];
  public multiSelection: boolean = true;
  public disableSelection: boolean;

  public title;
  public header;
  public isCollapsible;
  public filterMode: string;
  public columnFilterInputs: any = {};

  public infoText: string = "list.results";
  public wikiLink: string;
  public withHeader: boolean = true;
  public tableHeight: string;
  public allowFiltering: boolean;
  public treeHeight: string;
  public fallback: string = contextPath + "/assets/placeholder_281x202.jpg";
  public primaryKey: string;
  public foreignKey: string;

  /**
   *Emits all selected items whenever they change
   */
  @WidgetOutput("selectedItems")
  public selectedItems: Subject<any> = new Subject<any>();

  /**
   * The hide that should be used to hide tree grid
   */
  @WidgetInput("hide")
  public hideTable: Subject<boolean> = new ReplaySubject<boolean>();

  /**
   * The uri that should be used to fetch the data
   */
  @WidgetInput("uri")
  private inputChannel: ReplaySubject<any> = new ReplaySubject<any>();

  /**
   * Display already fetched data
   */
  @WidgetInput("inputData")
  private inputData: Subject<any> = new Subject<any>();

  //Emits currently visible data
  @WidgetOutput("results")
  public results: Subject<any[]> = new BehaviorSubject([]);

  @WidgetId()
  public _id;

  @WidgetConfiguration()
  public configuration: WidgetConfig<DataListConfiguration>;

  @WidgetInput("reset")
  private resetChannel: ReplaySubject<any> = new ReplaySubject<any>();

  @WidgetInput("clearFiltersAndSorting")
  private clearFiltersAndSortingChannel: ReplaySubject<any> = new ReplaySubject<any>();

  @WidgetInput()
  public selectedUiLocale = new ReplaySubject<any>(1);

  @ViewChild("treeGrid")
  public treeGrid: IgxTreeGridComponent;

  @WidgetOutput("selectedItem")
  public selectedItem: Subject<any> = new Subject<any>();

  @ViewChildren("inputBox")
  public inputBoxes: QueryList<ElementRef>;

  public selection: boolean = false;

  private unsubscribe = NgUnsubscribe.create();

  public hideOnEmpty: boolean = false;

  constructor(
    public authHttp: HttpClient,
    private scrollService: ScrollService
  ) {}

  @WidgetConfigure()
  protected configureWidget(configuration: WidgetConfig) {
    this.header = getOrDefault(
      this.configuration.configuration.header,
      "primary"
    );
    this.infoText = configuration.configuration.infoText;
    this.title = this.configuration.configuration.title;
    this.isCollapsible = getOrDefault(
      this.configuration.configuration.isCollapsible,
      false
    );
    this.wikiLink = this.configuration.configuration.wikiLink;
    this.withHeader = getOrDefault(
      this.configuration.configuration.withHeader,
      true
    );
    this.columns = this.configuration.configuration.columns["data"];
    this.hideOnEmpty = configuration.configuration["hideOnEmpty"] || false;
    this.dataType = configuration.configuration["dataType"];
    if (!configuration.configuration.unlimitedHeight) {
      this.tableHeight = getOrDefault(
        String(configuration.configuration.tableHeight) + "px",
        "100%"
      );
    }
    //quickFilter || excelStyleFilter || inlineFilter
    this.filterMode = getOrDefault(
      this.configuration.configuration["filterMode"],
      "inlineFilter"
    );
    this.disableSelection = getOrDefault(
      configuration.configuration["disableSelection"],
      false
    );
    this.allowFiltering = getOrDefault(
      configuration.configuration["allowFilter"],
      true
    );
    this.treeHeight = getOrDefault(
      configuration.configuration["height"],
      "451px"
    );
    this.primaryKey = getOrDefault(
      configuration.configuration["primaryKey"],
      "pimRef"
    );
    this.foreignKey = getOrDefault(
      configuration.configuration["foreignKey"],
      "parentPimRef"
    );

    if (this.disableSelection) {
      this.multiSelection = false;
    } else {
      this.multiSelection = getOrDefault(
        configuration.configuration["multiSelection"],
        true
      );
    }

    this.clearFiltersAndSortingChannel
      .asObservable()
      .pipe(takeUntil(this.unsubscribe))
      .subscribe(() => {
        if (this.treeGrid) {
          this.treeGrid.clearFilter();
          this.treeGrid.clearSort();
          this.columnFilterInputs = [];
          this.treeGrid.cdr.detectChanges();
        }
      });

    this.resetChannel
      .asObservable()
      .pipe(takeUntil(this.unsubscribe))
      .subscribe(() => {
        this.data = [];
      });

    this.hideTable
      .asObservable()
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((hide) => {
        this.hideOnEmpty = hide;
      });

    this.scrollService
      .getChangeViewPortSize()
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((status) => {
        // Waiting for animation to finish
        setTimeout(() => {
          if (this.treeGrid) {
            this.treeGrid.reflow();
          }
        }, 200);
      });

    this.inputData
      .asObservable()
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((data) => {
        this.data = this.formatIncomingData(data);
        this.results.next(this.data);
        this.hideOnEmpty = false;
      });

    this.inputChannel
      .asObservable()
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((link) => {
        if (link !== null && link !== undefined) {
          this.authHttp
            .get(link, {})
            .pipe(
              debounceTime(400),
              distinctUntilChanged(),
              map((res) => {
                return <ResultResource>res;
              })
            )
            .subscribe((data: any) => {
              this.data = this.formatIncomingData(
                data._embedded[this.dataType]
              );
              this.results.next(this.data);
              this.hideOnEmpty = false;
            });
        }
      });

    this.resetChannel
      .asObservable()
      .pipe(takeUntil(this.unsubscribe))
      .subscribe(() => {
        this.doReset();
      });
  }

  protected doReset() {
    this.data = [];
    this.results.next(this.data);
    this.hideOnEmpty = true;
  }

  public formatIncomingData(treeData) {
    let data = [];
    if (treeData) {
      for (let row of treeData) {
        if (!row["id"]) {
          row["id"] = row[this.primaryKey];
        }
        if (
          row[this.foreignKey] &&
          row[this.foreignKey] === row[this.primaryKey]
        ) {
          row["parentId"] = -1;
        } else if (!row["parentId"]) {
          row["parentId"] = row[this.foreignKey];
        }
        data.push(row);
      }
    }
    return data;
  }

  public stopPropagation(event, field) {
    event.stopImmediatePropagation();
    event.preventDefault();

    this.inputBoxes.forEach((input) => {
      if (input.nativeElement.classList.contains(field)) {
        input.nativeElement.focus();
      }
    });
    return false;
  }

  public onColumnFilterInput(input: any, column: IgxColumnComponent) {
    let operand = IgxStringFilteringOperand.instance().condition("contains");
    this.treeGrid.filter(
      column.field,
      input,
      operand,
      column.filteringIgnoreCase
    );
  }

  public clearColumnFilter(input: any, column: any) {
    this.columnFilterInputs[column.field] = null;
    this.treeGrid.clearFilter(column.field);
  }

  handleRowSelection(event) {
    let selectedRows = event;
    if (this.multiSelection == false && !this.disableSelection) {
      if (event.cell) {
        this.treeGrid.deselectAllRows();
        if (event.cell.row.isSelected) {
          this.treeGrid.deselectRows([event.cell.row.rowID]);
          selectedRows = null;
        } else {
          this.treeGrid.selectRows([event.cell.row.rowID]);
        }
      }
      this.selectedItem.next(selectedRows);
    }
  }

  onRowSelection(event) {
    let result = {
      count: event.newSelection ? event.newSelection.length : 1,
      rows: event.newSelection,
      rowData: [],
    };

    result.rowData = result.rows.map((key) => {
      return this.treeGrid.getRowByKey(key)
        ? this.treeGrid.getRowByKey(key).rowData
        : {};
    });
  }

  ngOnDestroy() {
    this.unsubscribe.destroy();
  }
}
<nm-widgetframe
  [header]="header"
  [configuration]="configuration"
  [infoTitle]="title"
  [infoText]="infoText"
  [infoPlacement]="'bottom'"
  [wikiLink]="wikiLink"
  [isCollapsible]="isCollapsible"
  [toolbarInvisible]="!withHeader"
  *ngIf="!hideOnEmpty"
>
  <div slot="title" class="nm-widgetframe__title">
    <span>{{ title | translate }} <span *ngIf="total">( {{total} )</span></span>
  </div>

  <div slot="content" class="nm-widgetframe__content" [ngClass]="filterMode">
    <igx-tree-grid
      #treeGrid
      [data]="data"
      [allowFiltering]="true"
      primaryKey="id"
      foreignKey="parentId"
      [hideRowSelectors]="multiSelection"
      (cellClick)="handleRowSelection($event)"
      (rowSelected)="onRowSelection($event)"
      [autoGenerate]="false"
      [filterMode]="filterMode"
      expansionDepth="1"
      [height]="tableHeight"
    >
      <igx-column
        *ngFor="let nmColumn of columns"
        [field]="nmColumn.field"
        [sortable]="nmColumn.sortable"
        [filterable]="nmColumn.filter"
        [header]="nmColumn.header | translate"
        [pinned]="nmColumn.pinned"
        [hidden]="nmColumn.hidden"
        [movable]="true"
        [resizable]="true"
        [width]="nmColumn.width"
        [dataType]="nmColumn.type"
      >
        <ng-template igxHeader let-column *ngIf="filterMode === 'inlineFilter'">
          <div
            class="title-inner"
            [attr.draggable]="false"
            [ngClass]="{ widthSorting: nmColumn.sortable }"
          >
            <span *ngIf="!nmColumn.filter" class="nm-title-container">{{
              nmColumn.header | translate
            }}</span>

            <mat-form-field
              *ngIf="nmColumn.filter"
              class="nm-list-column-search"
              [attr.draggable]="false"
            >
              <input
                [attr.draggable]="false"
                #inputBox
                [ngClass]="column.field"
                matInput
                type="text"
                (click)="stopPropagation($event, column.field)"
                [placeholder]="nmColumn.header | translate"
                [(ngModel)]="columnFilterInputs[column.field]"
                (input)="
                  onColumnFilterInput(columnFilterInputs[column.field], column)
                "
              />

              <button
                (click)="$event.stopPropagation()"
                [attr.draggable]="false"
                mat-button
                *ngIf="columnFilterInputs[column.field]"
                matSuffix
                mat-icon-button
                aria-label="Clear"
                (click)="
                  clearColumnFilter(columnFilterInputs[column.field], column)
                "
              >
                <mat-icon [attr.draggable]="false">close</mat-icon>
              </button>
            </mat-form-field>

            <mat-icon
              class="
                nm-table-head-icon nm-table-pin
                fa fa fa-thumb-tack
                fade-in
              "
              [class.pinned]="column.pinned"
              [attr.draggable]="false"
              (click)="column.pinned = !column.pinned"
            ></mat-icon>
          </div>
        </ng-template>

        <ng-template igxCell let-val let-cell="cell">
          <ng-container [ngSwitch]="nmColumn.type">
            <div *ngSwitchCase="'hal-actions'">
              <div class="hal-actions">
                <span
                  *ngFor="let act of cell.row.rowData._actions | iterable"
                  id="{{ act.key }}"
                >
                  <ng-container *ngIf="act.value.hidden !== true">
                    <nm-action-icon
                      *ngIf="act.key != 'download'"
                      [action]="act.value"
                      [name]="act.key"
                    >
                    </nm-action-icon>
                  </ng-container>
                </span>
              </div>
            </div>
            <div *ngSwitchDefault style="width: 100%">
              <nm-ellipsis
                [content]="cell.row.rowData[nmColumn.field]"
              ></nm-ellipsis>
            </div>
          </ng-container>
        </ng-template>
      </igx-column>
    </igx-tree-grid>
  </div>
</nm-widgetframe>
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""