File

projects/congarevenuecloud/elements/src/lib/output-field/output-field.component.ts

Description

Output field component is used to create a label value paired output that can be displayed as an editable field with an optional popover that shows related information about the field.

Preview

1.) Output field

2.) Output field displayed as an editable field with popover

Usage

Example :
import { OutputFieldModule } from '@congarevenuecloud/elements';

@ngModule({
imports: [OutputFieldModule, ...]
})
Example :
```typescript
<apt-output-field
             [record]="quote"
             [field]="CreatedDate"
             layout="inline"
             [editable]="false"
></apt-output-field>
Example :

Implements

OnChanges OnDestroy

Metadata

Index

Inputs
Outputs

Constructor

constructor(aobjectService: AObjectService, elRef: ElementRef, metadataService: MetadataService, apiService: ApiService)
Parameters :
Name Type Optional
aobjectService AObjectService No
elRef ElementRef No
metadataService MetadataService No
apiService ApiService No

Inputs

dateFormat
Type : string

Date format option passed into the date pipe used by date fields

displayValue
Type : string

The field property to use to render the value for lookup datatype

editable
Type : boolean
Default value : true

Flag to set this field as editable.

field
Type : string

Field property of the AObject

label
Type : string

The field to override the string value of label.

labelClass
Type : string

String of bootstrap classes for additional styling on output field label

labelOnly
Type : boolean
Default value : false

Flag to display only field label

layout
Type : "stacked" | "inline"
Default value : 'stacked'

The layout for the displayed label and value. By default the layout is 'stacked'.

lookupOptions
Type : LookupOptions

Object to set primary text field, secondary text field, thumbnail field, conditions, filters etc.

maxCharacterLength
Type : number

Maximum number of characters to show on string type fields.

record
Type : AObject

An instance of a AObject

required
Type : boolean

Flag to set this input as required.

showQuickView
Type : boolean
Default value : false

Flag to show the quick view lookup popover for this field.

showQuickViewFormat
Type : "normal" | "popover"
Default value : 'popover'

The property defines the way lookup information is shown. By default it shows as a popover.

valueClass
Type : string

String of bootstrap classes for additional styling on output field value

valueOnly
Type : boolean
Default value : false

Flag to show only value for this field without any label.

Outputs

onChange
Type : EventEmitter<any>

Event emitter is fired upon field value changes.

<span [class.align-items-baseline]="layout === 'inline'" [class.inline]="layout === 'inline'"
  [class.d-flex]="layout === 'inline'" [class.label-only]="labelOnly" *ngIf="view$ | async as view">
  <dt [ngClass]="labelClass" class="mutedLabels" id="label" *ngIf="!valueOnly" [class.mt-1]="layout === 'stacked'">
    {{view?.label | translate}}
  </dt>
  <dd *ngIf="!labelOnly" class="m-0 position-relative" [class.px-1]="layout === 'inline'"
    [class.py-0]="layout === 'inline'" [class.empty]="!view.value" [ngClass]="valueClass" [ngSwitch]="true">
    <ng-container *ngSwitchCase="view.recordMetadata?.DataType.toLowerCase() === 'datetime'">
      <span *ngIf="!dateFormat">{{view.value | dateFormat:'DateTimeFormat' | async}}</span>
      <span *ngIf="dateFormat">{{view.value | date:getDateFormat(view.metadata)}}</span>
    </ng-container>
    <ng-container *ngSwitchCase="view.recordMetadata?.DataType.toLowerCase() === 'date'">
      <span *ngIf="!dateFormat">{{view.value | dateFormat:'DateFormat' | async}}</span>
      <span *ngIf="dateFormat">{{view.value | date:getDateFormat(view.metadata)}}</span>
    </ng-container>

    <ng-container *ngSwitchCase="view?.recordMetadata?.DataType.toLowerCase() === 'currency'">
      <span *ngIf="view?.value; else noData">{{view?.value | localCurrency | async}}
      </span>
    </ng-container>

    <ng-container *ngSwitchCase="view?.recordMetadata?.DataType.toLowerCase() === 'address'">
      <apt-address [value]="view?.value" [readonly]="true"></apt-address>
    </ng-container>

    <ng-container *ngSwitchCase="view?.recordMetadata?.DataType.toLowerCase() === 'double'">
      <span>{{view?.value | number:'1.0-' + view.metadata.Scale}}</span>
    </ng-container>

    <ng-container *ngSwitchCase="view?.recordMetadata?.DataType.toLowerCase() === 'boolean'">
      <span [innerHTML]="view?.value ? ('COMMON.YES' | translate) : ('COMMON.NO' | translate)"></span>
    </ng-container>

    <ng-container
      *ngSwitchCase="view?.recordMetadata?.DataType.toLowerCase() === 'lookup' || view?.recordMetadata?.DataType.toLowerCase() === 'string'">
      <ng-container *ngIf="view?.recordMetadata?.DataType.toLowerCase() === 'string' && !showQuickView;">
        <ng-container [ngTemplateOutlet]="view?.nonTruncatedValue ? popOverTemplate : simple"
          [ngTemplateOutletContext]="{view:view}">
        </ng-container>
      </ng-container>

      <ng-container *ngIf="view?.recordMetadata?.DataType.toLowerCase() === 'lookup' && !showQuickView">
        <a href="javascript:void(0)" *ngIf="view?.referenceFieldInstance?.Id && view?.titleIsLink; else noLinkReference"
          [routerLink]="['/' + view?.route, view?.referenceFieldInstance?.Id]" [innerHTML]="view?.value"
          target="_blank"></a>
      </ng-container>
      <ng-template #noLinkReference>
        <span [innerHTML]="view?.value ? view?.value : ('COMMON.NO_DATA' | translate)"></span>
      </ng-template>

      <ng-container *ngIf="showQuickView">
        <ng-container *ngIf="showQuickViewFormat ==='popover'; else normalQuickViewTemplate">
          <a [ngClass]="showQuickView ? 'btn-link popoverLink' : ''" #lookupPop="bs-popover"
            [popover]="lookupPopTemplate" (click)="handleLookupPopClick()" triggers="" container="body"
            containerClass="lookupPopover" [outsideClick]="true" [placement]="onShown()" [innerHTML]="view?.value"></a>
        </ng-container>
      </ng-container>
    </ng-container>

    <ng-container *ngSwitchCase="view?.recordMetadata?.DataType.toLowerCase() === 'textarea'">
      <ng-container [ngTemplateOutlet]="view?.nonTruncatedValue ? popOverTemplate : simple">
      </ng-container>
    </ng-container>

    <ng-container *ngSwitchDefault>
      <ng-container [ngTemplateOutlet]="simple">
      </ng-container>
    </ng-container>

    <i *ngIf="editable && showQuickViewFormat ==='popover'" #pop="bs-popover"
      class="fa fa-pencil d-inline-block edit-icon ml-3" [popover]="editable ? popTemplate : null" container="body"
      containerClass="editPopover" [outsideClick]="false" (onShown)="hidePopover()"></i>
  </dd>

  <ng-template #lookupPopTemplate>
    <div class="popHeader position-relative p-3 mb-1"
      [ngClass]="expanded ? 'bg-dark text-white' : 'bg-white text-dark'">
      <div class="titleSection d-flex justify-content-between align-items-baseline">
        <ng-container>
          <a class="h5 btn-link" href="javascript:void(0)"
            *ngIf="view?.referenceFieldInstance?.Id && view?.titleIsLink; else noLinkPopoverTitle"
            [routerLink]="['/' + view?.route, view?.referenceFieldInstance?.Id]" [innerHTML]="view?.value"
            target="_blank"></a>
        </ng-container>
        <ng-template #noLinkPopoverTitle>
          <h5 [innerHTML]="view?.value"></h5>
        </ng-template>
        <button aria-label="Close" [ngClass]="{'text-white': expanded}" class="close pull-right" type="button"
          (click)="hidePopover()">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="fieldSection container-fluid">
        <div class="row">
          <div *ngFor="let field of view?.popoverFields | slice:0:6" class="col-6 pl-0 d-flex flex-column">
            <ng-container
              *ngIf="field?.field == 'ShippingAddress' || field?.field == 'BillingAddress'; else popoverFieldData">
              <apt-address [value]="view.referenceFieldInstance"
                [type]="field.field == 'ShippingAddress'? 'Shipping' : 'Billing'" [label]="field.label"
                [readonly]="true"></apt-address>
            </ng-container>
            <ng-template #popoverFieldData>
              <apt-output-field [record]="view?.referenceFieldInstance" [field]="field.field" [label]="field.label"
                layout="stacked" [editable]="false" [showQuickView]="false" [displayValue]="field.field">
              </apt-output-field>
            </ng-template>
          </div>
        </div>
      </div>
      <div *ngIf="!expanded"></div>
      <div *ngIf="view?.popoverFields?.length > 6"
        class="toggleButton position-absolute justify-content-center align-items-center border d-flex"
        [ngClass]="hovering ? 'bg-primary' : 'bg-white'" (mouseover)="hovering = true" (mouseout)="hovering = false"
        (click)="expanded = !expanded">
        <i class="fa"
          [ngClass]="{'fa-chevron-up': expanded, 'fa-chevron-down': !expanded, 'text-white': hovering, 'text-primary': !hovering}"
          aria-hidden="true"></i>
      </div>
    </div>
    <div *ngIf="expanded" class="expandSection p-3">
      <div class="container-fluid">
        <div class="row">
          <div *ngFor="let field of view?.popoverFields | slice:6" class="col-6 pl-0 d-flex flex-column">
            <apt-output-field [record]="view?.referenceFieldInstance" [field]="field.field" [label]="field.label"
              layout="stacked" [editable]="false" [showQuickView]="false"></apt-output-field>
          </div>
        </div>
      </div>
    </div>
  </ng-template>

  <ng-template #normalQuickViewTemplate>
    <div class="popHeader normal-quick-view mb-1 position-relative">
      <div class="fieldSection container-fluid">
        <div class="row">
          <div *ngFor="let field of view?.popoverFields" class="col-6 pl-0 d-flex flex-column quick-view-label pb-1">
            <ng-container
              *ngIf="field?.field == 'ShippingAddress' || field?.field == 'BillingAddress'; else popoverFieldData">
              <apt-address [value]="view.referenceFieldInstance"
                [type]="field.field == 'ShippingAddress'? 'Shipping' : 'Billing'" [label]="field.label"
                [readonly]="true"></apt-address>
            </ng-container>
            <ng-template #popoverFieldData>
              <apt-output-field [record]="view?.referenceFieldInstance" [field]="field.field" [label]="field.label"
                layout="stacked" [editable]="false" [showQuickView]="false" [displayValue]="field.field">
              </apt-output-field>
            </ng-template>
          </div>
        </div>
      </div>
    </div>
  </ng-template>

  <ng-template #popTemplate>
    <button aria-label="Close" [ngClass]="{'text-white': expanded}" class="close pull-right mr-1" type="button"
      (click)="handleHidePop(view)">
      <span aria-hidden="true">&times;</span>
    </button>
    <form class="p-3" (ngSubmit)="update(view)">
      <apt-input-field [(ngModel)]="view.recordInstance[view.field]" [field]="view.field" [entity]="view.recordInstance"
        [name]="view.field" [lookupOptions]="lookupOptions"></apt-input-field>
      <div class="d-flex justify-content-end">
        <button class="btn-link btn" (click)="handleHidePop(view)">{{'COMMON.CANCEL' | translate}}</button>
        <button class="btn btn-primary btn-raised" type="submit" [ladda]="loading"
          [disabled]="!view.recordInstance[view.field]">{{'COMMON.UPDATE' |
          translate}}</button>
      </div>
    </form>
  </ng-template>

  <ng-template #popOverTemplate>
    <span [popover]="view?.nonTruncatedValue" triggers="mouseenter:mouseleave" container="body">{{view?.value |
      safeHtml}}</span>
  </ng-template>

  <ng-template #simple>
    <span
      *ngIf="(!!view?.value || ((view?.recordMetadata?.DataType.toLowerCase() === 'int' || view?.recordMetadata?.DataType.toLowerCase() === 'decimal') && view?.value >= 0)); else noData">{{view?.value
      | safeHtml}}</span>
  </ng-template>

  <ng-template #noData>
    <span>{{'COMMON.NO_DATA' | translate}}</span>
  </ng-template>

  <ng-content></ng-content>
</span>

./output-field.component.scss

apt-output-field {
    .edit-icon {
        cursor: pointer;
        opacity: .5;

        &:hover {
            opacity: 1;
        }
    }

    .popoverLink {
        cursor: pointer;
    }

    .hover:hover {
        background-color: lightgray;
        cursor: pointer;
        position: relative;

        i.edit-icon {
            display: block;
            position: absolute;
            right: 2%;
            top: 22%;
        }
    }

    apt-input-field {
        min-width: 300px;
    }


    .inline:not(.label-only) {
        dt {
            white-space: nowrap;

            &::after {
                content: ":";
                margin: 0 2px 0 -2px;
            }
        }
    }

    dd.empty::after {
        content: "\200b"; // unicode zero width space character
    }

    dd {
        padding-top: 0.469rem;
        width: initial;
    }

    dd {
        span {
            line-height: 1.25rem;
        }
    }

}

.lookupPopover {
    max-width: unset;
    width: 322px;
    border-radius: 4px;


    .popHeader {
        border-top-left-radius: 4px;
        border-top-right-radius: 4px;
    }

    .toggleButton {
        right: 20px;
        bottom: -17px;
        width: 34px;
        height: 34px;
        border-radius: 50%;
        cursor: pointer;
        z-index: 5;

        i {
            font-size: 18px;
        }
    }

    .expandSection {
        border-bottom-left-radius: 4px;
        border-bottom-right-radius: 4px;
        max-height: 300px;
        overflow-y: auto;
    }
}

.editPopover {
    min-width: 322px;
}

.quick-view-label {
    dt {
        margin-top: 1em;
        line-height: 1.5;
        font-size: 0.75rem;
    }

    dd {
        padding: 0px;
        font-size: 0.75rem;
    }
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""