@WidgetComponent

nm-search-attributes

File

src/app/shared/widgets/buy/search-attributes/search-attributes.component.ts

Implements

OnDestroy

Metadata

providers EditAttributeService
selector nm-search-attributes
styleUrls search-attributes.component.scss
templateUrl ./search-attributes.component.html

Index

Widget inputs
Widget outputs
Properties
Methods

Constructor

constructor(_widgetframeService: WidgetframeService, _editAttributeService: EditAttributeService, _halService: HalService, localStorageService: LocalStorageService, _notificationService: CustomNotificationService, appStore: AppdataStore, dialogService: DialogService)
Parameters :
Name Type Optional
_widgetframeService WidgetframeService no
_editAttributeService EditAttributeService no
_halService HalService no
localStorageService LocalStorageService no
_notificationService CustomNotificationService no
appStore AppdataStore no
dialogService DialogService no

Methods

Private attributeSupportsRange
attributeSupportsRange(attribute: )
Parameters :
Name Optional
attribute no
Returns : boolean
Private checkIsAttributeEmpty
checkIsAttributeEmpty(attribute: Attribute)
Parameters :
Name Type Optional
attribute Attribute no
Returns : boolean
Protected configureWidget
configureWidget(configuration: WidgetConfig)
Decorators : WidgetConfigure
Parameters :
Name Type Optional
configuration WidgetConfig no
Returns : void
Public editShownAttributes
editShownAttributes()
Returns : void
Public getChangedAttributesForHeader
getChangedAttributesForHeader()
Returns : {}
ngOnDestroy
ngOnDestroy()
Returns : void
Public rangeChange
rangeChange(event: , attribute: Attribute)
Parameters :
Name Type Optional
event no
attribute Attribute no
Returns : void
Private recoverChangedAttributes
recoverChangedAttributes()
Returns : void
Private recoverFromData
recoverFromData(data: , attributes: Attribute[])
Parameters :
Name Type Optional
data no
attributes Attribute[] no
Returns : void
resetWidget
resetWidget()
Returns : any
showLabel
showLabel(attribute: )
Parameters :
Name Optional
attribute no
Returns : boolean
toogleContentVisibility
toogleContentVisibility()
Returns : void

Properties

Public _editAttributeService
_editAttributeService: EditAttributeService
Type : EditAttributeService
Public _halService
_halService: HalService
Type : HalService
Public _id
_id: string
Type : string
Decorators : WidgetId
Public _notificationService
_notificationService: CustomNotificationService
Type : CustomNotificationService
Public _widgetframeService
_widgetframeService: WidgetframeService
Type : WidgetframeService
Public allowRange
allowRange:
Public attributes
attributes: Attribute[]
Type : Attribute[]
Private attributesLocalstorageEntry
attributesLocalstorageEntry: LocalStorageEntry
Type : LocalStorageEntry
Public attributesorg
attributesorg: Attribute[]
Type : Attribute[]
Public attributeUrl
attributeUrl:
Default value : new Subject()
Decorators : WidgetInput

Input to set the uri that is used for the editShownAttributes.

Public canEditShownAttributes
canEditShownAttributes:
Default value : false
Public changedAttributes
changedAttributes:
Default value : <any>{}
Public changedAttributesOutput
changedAttributesOutput:
Default value : new ReplaySubject<any>()
Decorators : WidgetOutput

Emits an array of all edited attributes and their values.

Public changedValueByUser
changedValueByUser:
Default value : new Subject<any>()
Decorators : WidgetOutput

Emits the attribute that is being edited.

Public cols
cols: any[]
Type : any[]
Public configuration
configuration: WidgetConfig<SearchAttributesWidgetConfiguration>
Type : WidgetConfig<SearchAttributesWidgetConfiguration>
Decorators : WidgetConfiguration
Public contentVisible
contentVisible: boolean
Type : boolean
Default value : false
Public currentLocale
currentLocale: string
Type : string
Public data
data:
Default value : new Subject()
Decorators : WidgetInput

Input of preset array of attribute identifiers, used to get attributes.

Public inputLink
inputLink: string
Type : string
Public isCollapsible
isCollapsible: boolean
Type : boolean
Default value : false
Public localstorageAttributesEntry
localstorageAttributesEntry: LocalStorageEntry
Type : LocalStorageEntry
Public localStorageVisibiltyEntry
localStorageVisibiltyEntry: LocalStorageEntry
Type : LocalStorageEntry
Public multiLookupsAllowed
multiLookupsAllowed: boolean
Type : boolean

By default, attributes of type 'MULTI_LOOKUP' are converted to type 'LOOKUP', for compatibility with some search functions. Setting this value to true will allow multiple values to be selected for these attributes.

Public reload
reload:
Default value : new Subject<any>()
Decorators : WidgetInput

Reloads attributes for a given locale, and attributes url.

Public reset
reset:
Default value : new Subject<any>()
Decorators : WidgetInput

Resets attributes and local storage values.

Private selectAttributeUrl
selectAttributeUrl:
Public translateAttributeDescriptions
translateAttributeDescriptions:
Default value : false
Public unsubscribe
unsubscribe:
Default value : NgUnsubscribe.create()
Public uri
uri:
Default value : new ReplaySubject<any>(1)
Decorators : WidgetInput

Will call given uri and select the attributes from the address.

import {
  combineLatest as observableCombineLatest,
  Subject,
  ReplaySubject,
} from "rxjs";

import {
  onErrorResumeNext,
  takeUntil,
  mergeMap,
  distinctUntilChanged,
  map,
  flatMap,
} from "rxjs/operators";
import { Component, OnDestroy } from "@angular/core";
import { WidgetframeService } from "../../widgetframe/widgetframe.service";
import {
  getOrDefault,
  throwIfUndefined,
  WidgetConfig,
} from "../../widget.configuration";
import {
  WidgetComponent,
  WidgetConfiguration,
  WidgetConfigure,
  WidgetId,
  WidgetInput,
  WidgetOutput,
} from "../../widget.metadata";
import { NgUnsubscribe } from "../../../ng-unsubscribe";

import * as uriTemplates_ from "uri-templates";
import { Attribute } from "../../../components/edit-attribute/attribute";
import { EditAttributeService } from "../../../components/edit-attribute/edit-attribute.service";

import { HalService } from "../../../components/hal/index";
import { CustomNotificationService } from "../../../components/notification/customnotification.service";
import {
  DeletionMode,
  Scope,
} from "../../../components/local-storage/local-storage-constants";
import {
  LocalStorageEntry,
  LocalStorageService,
} from "../../../components/local-storage/local-storage.service";
import { SelectAttributesDialogComponent } from "../../../components/dialog/selectAttributesDialog.component";
import { AppdataStore } from "../../../components/appdata/appdata.store";
import { deepCopy } from "../../../components/util/util.service";
import { FormControl } from "@angular/forms";
import { DialogService } from "../../../components/dialog";

const uriTemplates = uriTemplates_;

export interface SearchAttributesWidgetConfiguration {
  /**
   * Enables/Disables selecting attributes SelectAttributesDialog. @default(false)
   */
  canEditShownAttributes?: boolean;
  /**
   * Local storage key for edited attributes and their values.
   */
  "localstorage-attribute-search"?: String;
  /**
   * Local storage key for search attributes visibility state.
   */
  "localstorage-content-visible"?: String;
  /**
   * Enables/disables attribute values range, from and to. @default(false)
   */
  allowRange?: boolean;
  /**
   * Enables/Disables showing attributes description. @default(false)
   */
  translateAttributeDescriptions?: boolean;
  /**
   * Enables/disables multilookup option. @default(false)
   */
  multiLookupsAllowed?: boolean;
  /**
   * used to get attributes in case of editShowAttributes enabled.
   */
  attributeUrl?: String;
}

declare var jQuery: any;

@WidgetComponent("nm-search-attributes")
@Component({
  selector: "nm-search-attributes",
  templateUrl: "./search-attributes.component.html",
  styleUrls: ["./search-attributes.component.scss"],
  providers: [EditAttributeService],
})
export class SearchAttributesWidgetComponent implements OnDestroy {
  public cols: any[];
  public attributes: Attribute[];
  public attributesorg: Attribute[];
  public changedAttributes = <any>{};
  public localstorageAttributesEntry: LocalStorageEntry;
  public localStorageVisibiltyEntry: LocalStorageEntry;

  public canEditShownAttributes = false;

  public contentVisible: boolean = false;
  public allowRange;
  public isCollapsible: boolean = false;

  public translateAttributeDescriptions = false;
  public currentLocale: string;
  public inputLink: string;

  /**
   *  By default, attributes of type 'MULTI_LOOKUP' are converted to type 'LOOKUP', for compatibility with some
   *  search functions. Setting this value to true will allow multiple values to be selected for these attributes.
   */
  public multiLookupsAllowed: boolean;

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

  /**
   * Reloads attributes for a given locale, and attributes url.
   */
  @WidgetInput()
  public reload = new Subject<any>();

  /**
   * Emits an array of all edited attributes and their values.
   */
  @WidgetOutput("changedAttributesOutput")
  public changedAttributesOutput = new ReplaySubject<any>();

  /**
   * Emits the attribute that is being edited.
   */
  @WidgetOutput("changedValueByUser")
  public changedValueByUser = new Subject<any>();

  /**
   * Resets attributes and local storage values.
   */
  @WidgetInput()
  public reset = new Subject<any>();

  /**
   * Will call given uri and select the attributes from the address.
   */
  @WidgetInput("uri")
  public uri = new ReplaySubject<any>(1);

  /**
   * Input to set the uri that is used for the editShownAttributes.
   */
  @WidgetInput("attributeUrl")
  public attributeUrl = new Subject();

  /**
   * Input of preset array of attribute identifiers, used to get attributes.
   */
  @WidgetInput()
  public data = new Subject();

  @WidgetId()
  public _id: string;

  public unsubscribe = NgUnsubscribe.create();
  private attributesLocalstorageEntry: LocalStorageEntry;

  constructor(
    public _widgetframeService: WidgetframeService,
    public _editAttributeService: EditAttributeService,
    public _halService: HalService,
    private localStorageService: LocalStorageService,
    public _notificationService: CustomNotificationService,
    private appStore: AppdataStore,
    private dialogService: DialogService
  ) {}

  private selectAttributeUrl;

  @WidgetConfigure()
  protected configureWidget(configuration: WidgetConfig) {
    this.changedAttributes = [];
    this.localStorageVisibiltyEntry = this.localStorageService.getLocalStorageEntry(
      configuration.configuration["localstorage-content-visible"],
      Scope.GLOBAL,
      DeletionMode.LOGIN
    );
    this.localstorageAttributesEntry = this.localStorageService.getLocalStorageEntry(
      configuration.configuration["localstorage-attribute-search"],
      Scope.GLOBAL,
      DeletionMode.LOGIN
    );
    this.selectAttributeUrl = configuration.configuration.attributeUrl;

    this.canEditShownAttributes = getOrDefault(
      configuration.configuration.editShownAttributes,
      false
    );
    if (this.canEditShownAttributes) {
      this.attributesLocalstorageEntry = this.localStorageService.getLocalStorageEntry(
        this._id,
        Scope.GLOBAL,
        DeletionMode.RESET
      );
      if (this.attributesLocalstorageEntry.exists()) {
        this.attributes = JSON.parse(this.attributesLocalstorageEntry.value);
        this.recoverChangedAttributes();
      }
    }
    this.allowRange = getOrDefault(
      configuration.configuration["allowRange"],
      false
    );

    this.translateAttributeDescriptions =
      configuration.configuration.translateAttributeDescriptions || false;
    if (this.localStorageVisibiltyEntry.exists()) {
      this.contentVisible = this.localStorageVisibiltyEntry.value === "true";
    }

    this.multiLookupsAllowed = getOrDefault(
      configuration.configuration.multiLookupsAllowed,
      false
    );

    this.data.pipe(takeUntil(this.unsubscribe)).subscribe((data) => {
      const missingAttributes = [];
      let foundAttributes = [];
      Object.keys(data).forEach((key) => {
        const attribute = this.attributes.find((att) => att.identifier == key);
        if (attribute) {
          if (attribute.source && attribute.source[0]) {
            attribute.source[0] = {};
          }
          foundAttributes.push(attribute);
        } else {
          missingAttributes.push(key);
        }
      });
      if (missingAttributes.length !== 0) {
        this.appStore
          .getAppdata()
          .pipe(
            map((data) => data.ipim._links.attributes.href),
            map(
              (data) =>
                data +
                '?filter=identifier:in:"' +
                missingAttributes.join(",") +
                '"'
            ),
            flatMap((data) => this._widgetframeService.getData(data)),
            map((data) => data._embedded.attributes)
          )
          .subscribe((entries) => {
            foundAttributes = foundAttributes.concat(entries);
            this.recoverFromData(data, foundAttributes);
          });
      } else {
        this.recoverFromData(data, foundAttributes);
      }
    });

    this.reset.pipe(takeUntil(this.unsubscribe)).subscribe((data) => {
      this.changedAttributes = [];
      this.changedAttributesOutput.next(this.changedAttributes);

      if (this.localstorageAttributesEntry.exists()) {
        this.localstorageAttributesEntry.clear();
      }

      if (this.attributesorg) {
        this.attributes = jQuery.extend(true, [], this.attributesorg);
      } else {
        if (this.attributes) {
          this.attributes.forEach((attribute) => {
            if (attribute.source && attribute.source[0]) {
              attribute.source[0] = {};
            }
          });
          this.attributes = jQuery.extend(true, [], this.attributes);
        }
      }
    });

    this._editAttributeService
      .getAttributeChangedEvent()
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((attribute) => {
        const dashIdx = attribute.identifier.indexOf("-");
        // The original attribute that was changed, needed to save the from / to
        let originalAttribute;
        let from;
        if (dashIdx !== -1) {
          const rootAttributeName =
            dashIdx === -1 ? null : attribute.identifier.substring(0, dashIdx);
          const att = this.attributes.find(
            (att) => att.identifier === rootAttributeName
          );
          const sub = attribute.identifier.substring(dashIdx + 1);
          originalAttribute = attribute;
          attribute = att;

          from = sub === "from";
        }

        let dublicateIndex = this.changedAttributes.findIndex(
          (item) => item.identifier == attribute.identifier
        );
        if (dublicateIndex !== -1) {
          this.changedAttributes.splice(dublicateIndex, 1);
          const isEmpty = this.checkIsAttributeEmpty(attribute);
          // The attribute and all of its fake range child attributes are not empty, we can readd it to the changed attributes
          if (!isEmpty) {
            this.changedAttributes.push(attribute);
          }
        } else {
          // THere is no duplicate, we are save to add this to the changed attributes
          this.changedAttributes.push(attribute);
        }

        this.localstorageAttributesEntry.value = JSON.stringify(
          this.changedAttributes
        );
        this.changedAttributesOutput.next(this.changedAttributes);
        this.changedValueByUser.next(attribute);
      });

    this.attributeUrl
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((data) => (this.selectAttributeUrl = data));

    let source = observableCombineLatest(
      this.uri.asObservable(),
      this.reload.asObservable().pipe(distinctUntilChanged()),
      function (uri, reloadEvent) {
        let template = uriTemplates(uri);
        let uriParams = {};
        // uriParams["context"] = configuration.configuration["context"];
        uriParams["locale"] = reloadEvent;
        this.currentLocale = reloadEvent;
        return template.fill(uriParams);
      }
    ).pipe(
      takeUntil(this.unsubscribe),
      mergeMap((href) =>
        this._widgetframeService
          .getData(href)
          .pipe(onErrorResumeNext(this.resetWidget()))
      )
    );

    source.subscribe(
      (data) => {
        for (const attribute of <any>data["_embedded"]["attributes"]) {
          if (!this.multiLookupsAllowed && attribute.type === "MULTI_LOOKUP") {
            attribute.type = "LOOKUP";
          }
        }
        this.attributes = jQuery.extend(
          true,
          [],
          data["_embedded"]["attributes"]
        );
        this.attributesorg = jQuery.extend(
          true,
          [],
          data["_embedded"]["attributes"]
        );

        this.recoverChangedAttributes();
      },
      (error) => {
        console.log(error);
        this.attributes = null;
      }
    );

    this.reload.asObservable().subscribe((data) => {
      this.currentLocale = data;
    });
  }

  private recoverFromData(data, attributes: Attribute[]) {
    this.attributes = [];
    this.changedAttributes = [];

    Object.keys(data).forEach((key) => {
      // We need to deep copy the object, so that the angular change detection will still work while in OnPush (we need to replace the reference)
      const attribute = deepCopy(
        attributes.find((attribute) => attribute.identifier == key)
      );
      attribute.source = [{ value: data[key] }];
      this.attributes.push(attribute);
      this.changedAttributes.push(attribute);
    });
    this.changedAttributesOutput.next(this.changedAttributes);
    if (this.attributesLocalstorageEntry) {
      this.attributesLocalstorageEntry.value = JSON.stringify(this.attributes);
    }
    this.localstorageAttributesEntry.value = JSON.stringify(
      this.changedAttributes
    );
  }

  private checkIsAttributeEmpty(attribute: Attribute): boolean {
    const isRootEmpty =
      !attribute.source[0].value ||
      attribute.source[0].value === "" ||
      attribute.source.length === 0;
    // The root is not empty, it cant be empty
    if (!isRootEmpty) {
      return false;
    }
    // The root is empty and it has no range attributes, it must be empty
    if (!attribute.from) {
      return true;
    }
    //Check if the children are empty
    else
      return (
        this.checkIsAttributeEmpty(attribute.from) &&
        this.checkIsAttributeEmpty(attribute.to)
      );
  }

  private recoverChangedAttributes() {
    if (this.localstorageAttributesEntry.exists()) {
      this.changedAttributes = JSON.parse(
        this.localstorageAttributesEntry.value
      );
      for (const changedAttribute of this.changedAttributes) {
        let dublicate = this.attributes.filter(
          (item) => item.identifier == changedAttribute.identifier
        );
        if (dublicate.length === 1) {
          dublicate[0].source = changedAttribute.source;
          if (changedAttribute.from) {
            dublicate[0].from = changedAttribute.from;
            dublicate[0].to = changedAttribute.to;
            dublicate[0].displayRange = changedAttribute.displayRange;
          }
        }
      }
      this.changedAttributesOutput.next(this.changedAttributes);
    }
  }

  resetWidget() {
    return null;
  }

  ngOnDestroy() {
    this.unsubscribe.destroy();
  }

  toogleContentVisibility() {
    this.contentVisible = !this.contentVisible;

    this.localStorageVisibiltyEntry.value = this.contentVisible.toString();
  }

  public editShownAttributes() {
    let dialogRef = this.dialogService.open(SelectAttributesDialogComponent, {
      minWidth: "900px",
      maxWidth: "900px",
      height: "755px",
    });
    dialogRef.componentInstance.preselectedAttributes = this.attributes || [];
    dialogRef.componentInstance.currentLocale = this.currentLocale;
    dialogRef.componentInstance.attributeUrl = throwIfUndefined(
      this.selectAttributeUrl
    );
    dialogRef.componentInstance.infoText = "infoText.select.attributes";
    dialogRef.afterClosed().subscribe((data) => {
      if (data) {
        let changedAttributesChanged = false;
        var i = this.changedAttributes.length;
        // If we have a changed attribute that is no longer editable we need to remove it from the list of changedattributes and output the changed attributes
        while (i--) {
          const entry = this.changedAttributes[i];
          const attribute = data.find(
            (val) => val.identifier === entry.identifier
          );
          if (!attribute) {
            this.changedAttributes.splice(i, 1);
            changedAttributesChanged = true;
          }
        }
        if (changedAttributesChanged) {
          this.changedAttributesOutput.next(this.changedAttributes);
        }

        if (this.attributes) {
          data.forEach((entry) => {
            if (!this.multiLookupsAllowed && entry.type === "MULTI_LOOKUP") {
              entry.type = "LOOKUP";
            }
            const value = this.attributes.find(
              (att) => att.identifier === entry.identifier
            );
            if (value) {
              entry.source = value.source;
            }
          });
        }
        this.attributes = data;
        this.attributesLocalstorageEntry.value = JSON.stringify(data);
      }
    });
  }

  showLabel(attribute) {
    return !(this.allowRange && this.attributeSupportsRange(attribute));
  }

  private attributeSupportsRange(attribute) {
    return attribute.type !== "BOOLEAN";
  }

  public rangeChange(event, attribute: Attribute) {
    attribute.displayRange = event.checked;
    if (attribute.from) {
      //Make sure that the attribute and the change attribute instance are === so that changes to displayRange will be copied to the changed attribute (needed for tooltip)
    } else if (event.checked) {
      // This will deep copy the source of the root to from and to! If this is a problem we need to cleanse the source before / while copping
      const fromClone: Attribute = JSON.parse(JSON.stringify(attribute));
      const toClone = JSON.parse(JSON.stringify(attribute));
      fromClone.identifier = fromClone.identifier + "-from";
      toClone.identifier = toClone.identifier + "-to";
      attribute.from = fromClone;
      attribute.to = toClone;
    }
    // Emit change, since changing the slider changes the search
    this.changedAttributesOutput.next(this.changedAttributes);
  }

  public getChangedAttributesForHeader() {
    const result = [];
    this.changedAttributes.forEach((value) => {
      if (value.displayRange) {
        let from;
        let to;
        if (value.from.source[0] && value.from.source[0].value) {
          from = value.from.source[0].value;
        }
        if (value.to.source[0] && value.to.source[0].value) {
          to = value.to.source[0].value;
        }
        let description = from ? from : "?";
        if (to) {
          description += " - " + to;
        }
        const fakeValue = {
          description: value.description,
          source: [
            {
              description,
            },
          ],
        };
        result.push(fakeValue);
      } else {
        result.push(value);
      }
    });
    return result;
  }
}
<ng-template #popTemplateChangedAttributes>
  <div class="nm-attribute-list-tooltip">
    <div
      class="nm-attribute-list-elements"
      *ngFor="let attribute of getChangedAttributesForHeader()"
    >
      <div class="nm-attribute-list-description">
        <nm-ellipsis [content]="attribute.description"></nm-ellipsis>
      </div>
      <div class="nm-attribute-list-value">
        {{
          attribute.source[0].description
            ? attribute.source[0].description
            : attribute.source[0].value
        }}
      </div>
    </div>
  </div>
</ng-template>

<div
  slot="title"
  class="nm-widgetframe__title"
  *ngIf="canEditShownAttributes || (attributes && attributes.length > 0)"
>
  <mat-checkbox
    class="nm-widgetframe__title-inline-container"
    [checked]="contentVisible"
    color="primary"
    (change)="toogleContentVisibility()"
    >{{ "label.advanced.search" | translate }}</mat-checkbox
  >

  <mat-icon
    color="primary"
    [hidden]="!(this.changedAttributes.length > 0)"
    class="nm-widgetframe__title-icon nm-widgetframe__title-toggle"
    [popover]="popTemplateChangedAttributes"
    popoverTitle="{{ 'active.attribute.filters' | translate }}"
    placement="bottom"
    container="body"
    triggers="mouseenter:mouseleave"
    >filter_list</mat-icon
  >
</div>

<div
  slot="content"
  class="nm-widgetframe__content"
  [class.hidden]="!contentVisible"
>
  <button
    mat-mini-fab
    color="primary"
    class="nm-edit-shown-attributes"
    (click)="editShownAttributes()"
    *ngIf="canEditShownAttributes"
  >
    <mat-icon>add</mat-icon>
  </button>

  <p-dataGrid
    [value]="attributes"
    [rows]="1000"
    [paginator]="false"
    emptyMessage=" "
  >
    <ng-template let-attribute pTemplate="body">
      <div class="nm-attribute-list-elements">
        <ng-container *ngIf="showLabel(attribute); else noLabel">
          <div
            class="nm-attribute-list-description"
            *ngIf="showLabel(attribute)"
          >
            <nm-ellipsis
              [content]="
                translateAttributeDescriptions
                  ? (attribute.description | translate)
                  : attribute.description
              "
            ></nm-ellipsis>
          </div>
          <div class="nm-attribute-list-value">
            <nm-edit-attribute
              [attribute]="attribute"
              [copyContentButton]="false"
              [onlyInputsForTexts]="true"
              [editAttributeService]="_editAttributeService"
              [floatingLabel]="false"
            >
            </nm-edit-attribute>
          </div>
        </ng-container>
        <ng-template #noLabel>
          <div class="range-wrapper">
            <ng-container *ngIf="attribute.displayRange; else noRange">
              <div class="range-wrapper-left">
                <nm-edit-attribute
                  [attribute]="attribute.from"
                  [copyContentButton]="false"
                  [onlyInputsForTexts]="true"
                  [loadOptionsLazy]="true"
                  [displayValueAssets]="true"
                  [editAttributeService]="_editAttributeService"
                  [floatingLabel]="
                    ('from' | translate) +
                    ' ' +
                    (translateAttributeDescriptions
                      ? (attribute.description | translate)
                      : attribute.description)
                  "
                >
                </nm-edit-attribute>
              </div>
              <div class="range-wrapper-right">
                <nm-edit-attribute
                  [attribute]="attribute.to"
                  [copyContentButton]="false"
                  [onlyInputsForTexts]="true"
                  [loadOptionsLazy]="true"
                  [displayValueAssets]="true"
                  [editAttributeService]="_editAttributeService"
                  [floatingLabel]="
                    ('to' | translate) +
                    ' ' +
                    (translateAttributeDescriptions
                      ? (attribute.description | translate)
                      : attribute.description)
                  "
                >
                </nm-edit-attribute>
              </div>
            </ng-container>
            <ng-template #noRange>
              <nm-edit-attribute
                [attribute]="attribute"
                [copyContentButton]="false"
                [onlyInputsForTexts]="true"
                [loadOptionsLazy]="true"
                [displayValueAssets]="true"
                [editAttributeService]="_editAttributeService"
                [floatingLabel]="
                  translateAttributeDescriptions
                    ? (attribute.description | translate)
                    : attribute.description
                "
              >
              </nm-edit-attribute>
            </ng-template>
          </div>
          <mat-slide-toggle
            [checked]="attribute.displayRange"
            (change)="rangeChange($event, attribute)"
          ></mat-slide-toggle>
        </ng-template>
      </div>
    </ng-template>
  </p-dataGrid>
</div>
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""