nm-data-list-tile-view
src/app/shared/widgets/data-list/data-list-tile-view-component/data-list-tile-view.component.ts
selector | nm-data-list-tile-view |
styleUrls | data-list-tile-view.component.scss |
templateUrl | ./data-list-tile-view.component.html |
Widget inputs |
Widget outputs |
Properties |
|
Methods |
Inputs |
Outputs |
constructor(scrollService: ScrollService, router: Router)
|
|||||||||
Parameters :
|
columns
|
Sets data-list columns.
Type:
Default value: |
data
|
Sets data-list data.
Type:
Default value: |
dataType
|
Sets data type.
Type:
Default value: |
frameHeight
|
Sets frame height.
Type:
Default value: |
grid
|
Sets data-list grid (IgxGridComponent).
Type: |
identifierField
|
Sets identifier fields.
Type:
Default value: |
listService
|
Allows lazyLoading to work opn tileview.
Type: |
overrideTileClickEvent
|
Overrides data-list tile click event.
Type: |
slideChange
|
Sets zoom level when zoom slider is changed.
Type:
Default value: |
tileRedirectLink
|
Sets Tile title redirect link template.
Type: |
click
|
Emits when data-list tile is clicked, works when overrideTileClickEvent = true, otherwise the link in tileRedirectLink is opened. $event type: EventEmitter
|
detectItemsChanged |
detectItemsChanged()
|
Returns :
void
|
Public getLink | ||||
getLink(entry: )
|
||||
Parameters :
Returns :
string
|
getNumberofItemsInView |
getNumberofItemsInView()
|
Returns :
any
|
ngAfterViewInit |
ngAfterViewInit()
|
Returns :
void
|
ngOnDestroy |
ngOnDestroy()
|
Returns :
void
|
Public ngOnInit |
ngOnInit()
|
Returns :
void
|
onSelectionChange | ||||||
onSelectionChange(event: , item: )
|
||||||
Parameters :
Returns :
void
|
openLink | ||||||
openLink(event: , entry: )
|
||||||
Parameters :
Returns :
boolean
|
processTileData | ||||||
processTileData(resetStartIndex: boolean)
|
||||||
Parameters :
Returns :
void
|
updateBoxSizes | ||||
updateBoxSizes(slideChange: )
|
||||
Parameters :
Returns :
void
|
Public boxHeight |
boxHeight:
|
Type : string
|
Default value : "220px"
|
Public boxWidth |
boxWidth:
|
Type : string
|
Default value : "33%"
|
Public imageinRow |
imageinRow:
|
Type : number
|
Default value : 3
|
Public listHeight |
listHeight:
|
Type : string
|
Default value : "676px"
|
Public rows |
rows:
|
Type : ReplaySubject<any>
|
Default value : new ReplaySubject<any>(1)
|
Public selectors |
selectors:
|
Type : Selectors
|
unsubscribe |
unsubscribe:
|
Default value : NgUnsubscribe.create()
|
Public viewPortHeight |
viewPortHeight:
|
Type : number
|
Public virtDirRemote |
virtDirRemote:
|
Type : IgxForOfDirective<any>
|
Decorators : ViewChild
|
import {
Component,
Input,
Output,
ViewChild,
EventEmitter,
AfterViewInit,
} from "@angular/core";
import { filter, startWith, takeUntil } from "rxjs/operators";
import { NgUnsubscribe } from "../../../ng-unsubscribe";
import {
combineLatest as observableCombineLatest,
ReplaySubject,
timer as observableTimer,
} from "rxjs";
import { Selectors } from "../../../components/app-context";
import { IgxForOfDirective } from "@infragistics/igniteui-angular";
import { ScrollService } from "../../../components/scroll/scroll.service";
import { Column } from "../..";
import { Router } from "@angular/router";
import * as uriTemplates_ from "uri-templates";
import { DataListService } from "../data-list.service";
const uriTemplates = uriTemplates_;
const DEFAULT_FRAME_HEIGHT_PX: number = 270;
const DEFAULT_REDIRECT_LINK = "apps/product-details?product={identifier}";
@Component({
selector: "nm-data-list-tile-view",
templateUrl: "./data-list-tile-view.component.html",
styleUrls: ["./data-list-tile-view.component.scss"],
})
export class DataListTileViewComponent implements AfterViewInit {
/**
* Sets data-list data.
*/
@Input()
public data: ReplaySubject<any> = new ReplaySubject<any>(1);
/**
* Sets zoom level when zoom slider is changed.
*/
@Input()
public slideChange: ReplaySubject<number> = new ReplaySubject<number>(1);
/**
* Sets data-list grid (IgxGridComponent).
*/
@Input()
public grid: any;
/**
* Sets data-list columns.
*/
@Input()
public columns: ReplaySubject<any> = new ReplaySubject<any>(1);
/**
* Sets frame height.
*/
@Input()
public frameHeight: number = DEFAULT_FRAME_HEIGHT_PX;
/**
* Sets data type.
*/
@Input()
public dataType: string = "products";
@ViewChild("virtDirRemote", { read: IgxForOfDirective })
public virtDirRemote: IgxForOfDirective<any>;
/**
* Sets Tile title redirect link template.
*/
@Input()
public tileRedirectLink: string;
/**
* Overrides data-list tile click event.
*/
@Input()
public overrideTileClickEvent: boolean;
/**
* Allows lazyLoading to work opn tileview.
*/
@Input()
public listService: DataListService;
/**
* Sets identifier fields.
*/
@Input()
public identifierField: string = "identifier";
/**
* Emits when data-list tile is clicked, works when overrideTileClickEvent = true, otherwise the link in tileRedirectLink is opened.
*/
@Output("click")
public click = new EventEmitter();
public selectors: Selectors;
public rows: ReplaySubject<any> = new ReplaySubject<any>(1);
unsubscribe = NgUnsubscribe.create();
public listHeight = "676px";
public boxWidth: string = "33%";
public boxHeight: string = "220px";
public imageinRow: number = 3;
public viewPortHeight: number;
constructor(private scrollService: ScrollService, private router: Router) {}
public ngOnInit() {
this.selectors = { content: this.dataType, target: "nm-list-row" };
this.viewPortHeight =
window.innerHeight ||
document.documentElement.clientHeight ||
document.body.clientHeight;
this.listHeight = String(this.viewPortHeight - this.frameHeight) + "px";
this.scrollService
.getChangeViewPortSize()
.pipe(takeUntil(this.unsubscribe))
.subscribe((newViewPortHeight) => {
this.viewPortHeight = newViewPortHeight;
this.listHeight = String(newViewPortHeight - this.frameHeight) + "px";
if (this.virtDirRemote.cdr && this.virtDirRemote) {
this.detectItemsChanged();
}
});
observableCombineLatest(
this.data,
this.listService.data.pipe(takeUntil(this.unsubscribe)),
this.slideChange.pipe(startWith(3)),
(data, listServiceData, slideChange) => {
if (!this.listService.isEagerLoading) {
return <any>{ listServiceData, slideChange };
}
return <any>{ data, slideChange };
}
)
.pipe(takeUntil(this.unsubscribe))
.subscribe((data) => {
this.updateBoxSizes(data.slideChange);
let rowsArray = [];
let row = [];
data.data.forEach((item, index) => {
if (
this.grid &&
this.grid.selectedRows.indexOf(item[this.identifierField]) > 0
) {
item.selected = true;
}
if (row.length < this.imageinRow) {
row.push(item);
} else {
rowsArray.push(row);
row = [];
row.push(item);
}
if (data.data.length === index + 1) {
rowsArray.push(row);
row = [];
}
});
//To handle table reset when lazy loading
if (
!this.listService.isEagerLoading &&
this.virtDirRemote &&
rowsArray.length === 0
) {
this.virtDirRemote.totalItemCount = null;
}
this.rows.next(rowsArray);
setTimeout(() => {
if (this.virtDirRemote.cdr && this.virtDirRemote) {
this.detectItemsChanged();
this.virtDirRemote.cdr.detectChanges();
}
}, 1);
});
}
ngAfterViewInit() {
this.detectItemsChanged();
if (!this.listService.isEagerLoading) {
this.listService.dataTotalSubject
.pipe(
takeUntil(this.unsubscribe),
filter((total) => !!total)
)
.subscribe((total) => {
this.virtDirRemote.totalItemCount = Math.ceil(
total / this.imageinRow
);
// Necessary to prevent disappearing list and not updating scrollbar after total and rows change
this.processTileData(true);
this.virtDirRemote.cdr.detectChanges();
});
}
}
processTileData(resetStartIndex: boolean) {
if (
this.listService.isEagerLoading ||
this.listService.dataTotalSubject.value === null
) {
return;
}
const virtualization = {
chunkSize: this.getNumberofItemsInView() * this.imageinRow * 3,
startIndex:
!resetStartIndex && this.virtDirRemote.state.startIndex
? this.virtDirRemote.state.startIndex * this.imageinRow
: 0,
};
this.listService.processTileViewData(virtualization);
}
getNumberofItemsInView() {
return Math.ceil(
parseInt(this.listHeight, 10) / parseInt(this.boxHeight, 10)
);
}
detectItemsChanged() {
// Necessary to prevent disappearing list after rows change
this.virtDirRemote.scrollNext();
this.virtDirRemote.scrollPrev();
this.virtDirRemote.cdr.detectChanges();
}
updateBoxSizes(slideChange) {
if (slideChange == 5) {
this.imageinRow = 1;
this.boxWidth = "100%";
this.boxHeight = "700px";
} else if (slideChange == 4) {
this.imageinRow = 2;
this.boxWidth = "50%";
this.boxHeight = "450px";
} else if (slideChange == 3) {
this.imageinRow = 3;
this.boxWidth = "33%";
this.boxHeight = "350px";
} else if (slideChange == 2) {
this.imageinRow = 4;
this.boxWidth = "25%";
this.boxHeight = "250px";
} else if (slideChange == 1) {
this.imageinRow = 5;
this.boxWidth = "20%";
this.boxHeight = "160px";
}
}
onSelectionChange(event, item) {
if (event.checked) {
this.grid.selectRows([item[this.identifierField]], false);
} else {
this.grid.deselectRows([item[this.identifierField]]);
}
this.grid.rowSelected.emit({
newSelection: this.grid.selectedRows,
});
this.grid.cdr.detectChanges();
}
ngOnDestroy(): void {
this.unsubscribe.destroy();
}
public getLink(entry): string {
let link = this.tileRedirectLink
? this.tileRedirectLink
: DEFAULT_REDIRECT_LINK;
const template = uriTemplates(link);
const url = template.fill(entry);
return url;
}
openLink(event, entry) {
if (this.overrideTileClickEvent) {
event.stopPropagation();
this.click.emit(entry);
return false;
}
if (event.ctrlKey) {
// We want to use the default browser logic to handle this
return;
}
const url = this.getLink(entry);
event.stopPropagation();
this.router.navigateByUrl(url);
return false;
}
}
<div
#container
[style.width]="'100%'"
[style.height]="listHeight"
[style.overflow]="'hidden'"
[style.position]="'relative'"
class="nm-tile-view-container"
>
<ng-template
igxFor
let-entries
[igxForOf]="rows | async"
[igxForScrollOrientation]="'vertical'"
[igxForContainerSize]="listHeight"
[igxForItemSize]="boxHeight"
(chunkPreload)="processTileData(false)"
let-rowIndex="index"
#virtDirRemote
>
<ng-container *ngFor="let entry of entries">
<div
class="nm-gridlist-box"
[style.width]="boxWidth"
[style.padding-bottom]="boxHeight"
>
<div class="nm-gridlist-boxInner">
<div class="nm-gridlist-actionBox">
<div class="nm-gridlist-statusBox">
<ng-container
*ngFor="let color of entry.properties; let i = index"
>
<div
*ngIf="color.identifier.startsWith('IPIM_PRODUCT_STATUS')"
matTooltip="{{
('infotext.product.state.' + (i + 1 - 4).toString()
| translate) +
': ' +
(color.value | translate)
}}"
class="traffic_light traffic_light_grid single"
>
<span class="active" [ngClass]="color.value"></span>
</div>
</ng-container>
</div>
<br />
<div class="actions-and-interactions">
<div class="hal-actions">
<ng-container *ngFor="let act of entry._actions | iterable">
<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>
</ng-container>
</div>
<div class="interactions">
<nm-interactions
[param]="entry"
[selectors]="selectors"
></nm-interactions>
</div>
</div>
</div>
<igx-checkbox
class="nm-gridlist-selection"
(change)="onSelectionChange($event, entry)"
[(ngModel)]="entry.selected"
>
</igx-checkbox>
<nm-image
[container]="entry"
asset="main-asset"
[no-preview]="true"
[size]="imageinRow > 2 ? 'full' : 'preview'"
width="auto"
height="auto"
alt="{{ entry[identifierField] }}"
itemsPerRow
></nm-image>
<div class="nm-gridlist-titleBox">
<a href="{{ getLink(entry) }}" (click)="openLink($event, entry)">
<span> {{ entry[identifierField] }}</span>
</a>
<nm-ellipsis [content]="entry.description"> </nm-ellipsis>
</div>
</div>
</div>
</ng-container>
</ng-template>
</div>