File

projects/i-components/src/lib/components/mat-menu/mat-menu.component.ts

Description

This component represents material menu calls recursively in case of deeper node levels

Implements

AfterViewInit

Metadata

selector wm-mat-menu
styleUrls ./mat-menu.component.scss
templateUrl ./mat-menu.component.html

Index

Properties
Methods
Inputs

Constructor

constructor(injector: Injector)

Creates an instance of MatMenuComponent.

Parameters :
Name Type Optional
injector Injector No

Inputs

items
Type : any[]

Items RadMenuItemComponents array

itemsToRender
Type : any

Set of dynamic items to render

Methods

childMenuDynamicModels
childMenuDynamicModels(child: any)

Returns set of sub dynamic components if applies.

Parameters :
Name Type Optional
child any No
Returns : any
ngAfterViewInit
ngAfterViewInit()

AfterViewInit

Returns : void
processItemsToRender
processItemsToRender(child)

Process dynamic items.

Parameters :
Name Optional
child No
Returns : any

{*}

trackByFn
trackByFn(index: any, item: any)

Function used by Angular to track elements in the ngFor directive. We use the GUID property to compare elements.

Parameters :
Name Type Optional Description
index any No
  • index of the array
item any No
  • item of the array
Returns : any

{*} -return the model or object itself

validateRendering
validateRendering()

Validate internal mat menu view child to be ready.

Returns : boolean

{boolean}

Properties

Public childMenu
Type : any
Decorators :
@ViewChild('childMenu', {static: true})

Child menu material menu

items
Type : any[]
Decorators :
@Input()

Items RadMenuItemComponents array

itemsToRender
Decorators :
@Input()

Set of dynamic items to render

Public menu
Type : any
Decorators :
@ViewChild('menu')

Sub material menu

renderingFlag
Default value : false

RenderingFlag

import {
  AfterViewInit,
  Component,
  Injector,
  Input,
  ViewChild,
} from '@angular/core';
import { Utils } from '../../utils/utilities';

/**
 * This component represents material menu  calls recursively in case of deeper node levels
 *
 * @export
 * @class MatMenuComponent
 * @implements {OnInit}
 * @implements {AfterViewInit}
 */
@Component({
  selector: 'wm-mat-menu',
  templateUrl: './mat-menu.component.html',
  styleUrls: ['./mat-menu.component.scss'],
})
export class MatMenuComponent implements AfterViewInit {
  /**
   * Items RadMenuItemComponents array
   *
   * @type {any[]}
   * @memberof MatMenuComponent
   */
  @Input() items: any[];

  /**
   * Set of dynamic items to render
   *
   * @memberof MatMenuComponent
   */
  @Input() itemsToRender;

  /**
   * Child menu material menu
   *
   * @memberof MatMenuComponent
   */
  @ViewChild('childMenu', { static: true }) public childMenu: any;

  /**
   * Sub material menu
   *
   * @memberof MatMenuComponent
   */
  @ViewChild('menu') public menu: any;

  /**
   * RenderingFlag
   *
   * @memberof MatMenuComponent
   */
  renderingFlag = false;

  /**
   * Creates an instance of MatMenuComponent.
   *
   * @memberof MatMenuComponent
   */
  constructor(private injector: Injector) {}

  /**
   * AfterViewInit
   *
   * @memberof MatMenuComponent
   */
  ngAfterViewInit(): void {
    setTimeout(() => {
      this.renderingFlag = true;
    }, 0);
  }

  /**
   * Validate internal mat menu  view child to be ready.
   *
   * @return {*}  {boolean}
   * @memberof MatMenuComponent
   */
  validateRendering(): boolean {
    return this.menu?.renderingFlag === true;
  }

  /**
   * Returns set of sub dynamic components if applies.
   *
   * @param {*} child
   * @return {*}
   * @memberof MatMenuComponent
   */
  childMenuDynamicModels(child: any) {
    return child.itemsToRender;
  }

  /**
   * Process dynamic items.
   *
   * @param {*} child
   * @return {*}  {*}
   * @memberof MatMenuComponent
   */
  processItemsToRender(child): any {
    return Utils.getDynamicUIElements(
      child.item.items.internalArray,
      [],
      true,
      this.injector
    );
  }

  /**
   * Function used by Angular to track elements in the ngFor directive.
   * We use the GUID property to compare elements.
   *
   * @param {*} index - index of the array
   * @param {*} item - item of the array
   * @return {*}  {*} -return the model or object itself
   * @memberof BaseComponent
   */
  trackByFn(index: any, item: any): any {
    return item.model ?? item.item ?? item;
  }
}
<mat-menu #childMenu="matMenu" [overlapTrigger]="false">
  <!-- Static Rendering -->
  <ng-container *ngIf="items && items.length > 0">
    <span *ngFor="let child of items; let i = index; trackBy: trackByFn">
      <!-- Handle branch node menu items -->
      <span
        *ngIf="
          child.menuItems &&
          child.renderingFlag &&
          child.menuItems.toArray().length > 0 &&
          child.visibility
        "
      >
        <wm-mat-menu
          #menu
          [items]="child.menuItems"
          [itemsToRender]="child.itemsToRender"
        ></wm-mat-menu>
        <ng-container *ngIf="validateRendering()">
          <button
            mat-menu-item
            color="primary"
            [matMenuTriggerFor]="menu.childMenu"
          >
            <ng-container *ngIf="child.renderingFlag">
              <ng-container
                [ngTemplateOutlet]="child.itemTemplate"
                [ngTemplateOutletContext]="{ context: { child: child } }"
              >
              </ng-container>
            </ng-container>
          </button>
        </ng-container>
      </span>
      <!-- Handle leaf node menu items -->
      <span
        *ngIf="
          child.menuItems &&
          child.renderingFlag &&
          child.menuItems.toArray().length === 0 &&
          child.visibility
        "
      >
        <ng-container *ngIf="child.renderingFlag">
          <button mat-menu-item>
            <ng-container
              [ngTemplateOutlet]="child.itemTemplate"
              [ngTemplateOutletContext]="{ context: { child: child } }"
            >
            </ng-container>
          </button>
        </ng-container>
      </span>
    </span>
  </ng-container>

  <ng-container
    *ngIf="itemsToRender && itemsToRender.length > 0 && renderingFlag"
  >
    <span *ngFor="let child of itemsToRender; trackBy: trackByFn">
      <!-- Handle branch node menu items -->
      <span
        *ngIf="
          child.item && child.item.items.count > 0 && child.item.Visibility
        "
      >
        <wm-mat-menu
          #menu
          [itemsToRender]="processItemsToRender(child)"
        ></wm-mat-menu>
        <ng-container *ngIf="validateRendering() && menu.childMenu">
          <button
            mat-menu-item
            color="primary"
            [matMenuTriggerFor]="menu.childMenu"
          >
            <ng-container *ngIf="child.customInjector && child.component">
              <ng-container
                *ngComponentOutlet="
                  child.component;
                  injector: child.customInjector
                "
              ></ng-container>
            </ng-container>
          </button>
        </ng-container>
      </span>
      <!-- Handle leaf node menu items -->
      <span
        *ngIf="
          child.item && child.item.items.count === 0 && child.item.Visibility
        "
      >
        <button mat-menu-item>
          <ng-container *ngIf="child.customInjector && child.component">
            <ng-container
              *ngComponentOutlet="
                child.component;
                injector: child.customInjector
              "
            ></ng-container>
          </ng-container>
        </button>
      </span>
    </span>
  </ng-container>
</mat-menu>

./mat-menu.component.scss

.mat-menu-item {
  height: auto;
  padding: 0px;
  line-height: 1;
  border: 1px solid transparent;
  border-radius: 2px;
  cursor: default;
  &:hover {
    background: rgb(255, 251, 218);
    background: linear-gradient(
      180deg,
      rgba(255, 251, 218, 1) 0%,
      rgba(255, 251, 163, 1) 100%
    );
    border-color: #ffc92b;
  }
}
Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""