nm-data-list-component
src/app/shared/widgets/data-list/data-list-component/data-list.component.ts
OnInit
OnDestroy
AfterViewInit
providers |
EditAttributeService
|
selector | nm-data-list-component |
styleUrls | data-list.component.scss |
templateUrl | ./data-list.component.html |
constructor(localStorageService: LocalStorageService, dialog: DialogService, notificationService: CustomNotificationService, translateService: TranslateService, currentLocaleService: CurrentLocaleService, widgetFrameService: WidgetframeService, appContext: AppContext, appdataStore: AppdataStore, cdr: ChangeDetectorRef, http: HttpClient, progressbarService: ProgressbarService, editAttributeService: EditAttributeService, scrollService: ScrollService, dataListExportService: DataListExportService, websocketService: WebsocketService, userService: UserService, dataListEndEditService: DataListEndEditService, validationService: ValidationService, unsavedChangesService: UnsavedChangesService, appService: AppService, module: NmModuleDescriptor)
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Parameters :
|
additionalParams
|
|
attributeUrl
|
|
autoFocus
|
Type:
Default value: |
clearCellSelection
|
|
clearFiltersAndSorting
|
|
clearRowSelection
|
|
configuration
|
Type: |
contextIdentifier
|
|
data
|
|
dataTypeInput
|
|
dataTypeMode
|
|
disableCellEditMode
|
|
dynamicColumnsIn
|
|
eagerLimit
|
|
endGridEditMode
|
|
export
|
|
filterColumns
|
|
locale
|
|
preselectAttributeProfile
|
|
products
|
|
refreshRows
|
|
reload
|
|
reset
|
|
resetEditData
|
|
restoreGlobalFilter
|
|
rowSelection
|
|
shownAttributesIn
|
|
uri
|
|
widgetId
|
Type: |
api
|
$event type: EventEmitter
|
currentData
|
$event type: EventEmitter
|
dataLoaded
|
$event type: EventEmitter
|
dataType
|
$event type: EventEmitter
|
dynamicColumns
|
$event type: EventEmitter
|
dynamicPrefix
|
$event type: EventEmitter
|
editableCell
|
$event type: EventEmitter
|
editedRow
|
$event type: EventEmitter
|
editedRows
|
$event type: EventEmitter
|
gridOutput
|
$event type: EventEmitter
|
isValid
|
$event type: EventEmitter
|
onCellSelect
|
$event type: EventEmitter
|
onDrop
|
$event type: EventEmitter
|
reorderedRows
|
$event type: EventEmitter
|
rowEditEnter
|
$event type: EventEmitter
|
rowEditLeave
|
$event type: EventEmitter
|
selectedItems
|
$event type: EventEmitter
|
shownAttributes
|
$event type: EventEmitter
|
statusOut
|
$event type: EventEmitter
|
tileClicked
|
$event type: EventEmitter
|
toggleButtonChange
|
$event type: EventEmitter
|
total
|
$event type: EventEmitter
|
viewMode
|
$event type: EventEmitter
|
Public applyDensityFromLocalStorage |
applyDensityFromLocalStorage()
|
Returns :
void
|
Private applyExcelPasteData | ||||||
applyExcelPasteData(response: , selectedCell: )
|
||||||
Parameters :
Returns :
void
|
Private autosizeColumns |
autosizeColumns()
|
Returns :
void
|
Protected buildLazyAllSelectionEvent | ||||||||||||
buildLazyAllSelectionEvent(event: any, grid: IgxGridBaseDirective, service: DataListService)
|
||||||||||||
Parameters :
Returns :
SelectionParams
|
Protected buildSelectionEvent | ||||||||||||
buildSelectionEvent(event: any, grid: IgxGridComponent | IgxHierarchicalGridComponent | IgxTreeGridComponent, service: DataListService)
|
||||||||||||
Parameters :
Returns :
SelectionParams
|
calcTableHeight |
calcTableHeight()
|
Returns :
string
|
Private checkCellForErrors | ||||||
checkCellForErrors(cell: ListCellEditComponent | ListCellComponent)
|
||||||
Parameters :
Returns :
boolean
|
Public clearAllFiltersAndSorting | ||||||||||||||||
clearAllFiltersAndSorting(clearGrouping: , loadData: boolean, restoreGlobalFilter: )
|
||||||||||||||||
Parameters :
Returns :
void
|
Public clearColumnFilter |
clearColumnFilter(input: any, column: any)
|
Returns :
void
|
Public clearGlobalFilter |
clearGlobalFilter()
|
Returns :
void
|
Protected clearSelectedRows |
clearSelectedRows()
|
Returns :
void
|
closeContextMenu |
closeContextMenu()
|
Returns :
void
|
columnInit | ||||||
columnInit(column: any)
|
||||||
Parameters :
Returns :
void
|
columnOrderChanged | ||||||
columnOrderChanged(columnIdentifiers: string[])
|
||||||
Parameters :
Returns :
void
|
Protected dataLoaded | ||||
dataLoaded(data: )
|
||||
Parameters :
Returns :
void
|
Public dataPasted | ||||||
dataPasted(processedData: string[][])
|
||||||
Parameters :
Returns :
void
|
Private doInitialSorting |
doInitialSorting()
|
Returns :
void
|
Public doRefresh |
doRefresh()
|
Returns :
void
|
Public doReload | ||||||||
doReload(force: boolean)
|
||||||||
Parameters :
Returns :
void
|
Protected doReset |
doReset()
|
Returns :
void
|
Public editShownAttributes |
editShownAttributes()
|
Returns :
void
|
Private emitDataListStatus | ||||||
emitDataListStatus(lastChange: string)
|
||||||
Parameters :
Returns :
void
|
Public fireEditedRowsEvent | ||||||||||||||||||
fireEditedRowsEvent(rowId: string, gridRow: any, parent: string, attributes: , configuration: DataListConfiguration)
|
||||||||||||||||||
Parameters :
Returns :
void
|
Public getCellClass | ||||
getCellClass(nmColumn: )
|
||||
Parameters :
Returns :
any
|
Public getColumnHeaderClasses | ||||||
getColumnHeaderClasses(column: Column)
|
||||||
Parameters :
Returns :
{}
|
Private getCurrentRowIndex | ||||||
getCurrentRowIndex(rowList: , cursorPosition: )
|
||||||
Parameters :
Returns :
any
|
Public getDynamicPrefix |
getDynamicPrefix()
|
Returns :
string
|
Public getGridColumnWidth | ||||||
getGridColumnWidth(column: Column)
|
||||||
Parameters :
Returns :
any
|
getHeaderClass | ||||
getHeaderClass(nmColumn: )
|
||||
Parameters :
Returns :
any
|
Public getHighlightReadOnly |
getHighlightReadOnly()
|
Returns :
boolean
|
Protected getShownAttributes |
getShownAttributes()
|
Returns :
any
|
Private getSortDirection | ||||
getSortDirection(direction: )
|
||||
Parameters :
Returns :
any
|
getTableHeight |
getTableHeight()
|
Returns :
string
|
Public getTranslationKey | ||||||
getTranslationKey(column: Column)
|
||||||
Parameters :
Returns :
any
|
Public groupingComparer | ||||||
groupingComparer(column: Column)
|
||||||
Parameters :
Returns :
any
|
Protected handleInput | ||||
handleInput(link: )
|
||||
Parameters :
Returns :
void
|
Public ngAfterViewInit |
ngAfterViewInit()
|
Returns :
void
|
Public ngOnDestroy |
ngOnDestroy()
|
Returns :
void
|
Public ngOnInit |
ngOnInit()
|
Returns :
void
|
onCellClick | ||||
onCellClick(event: )
|
||||
Parameters :
Returns :
void
|
onCellEdit | ||||||||||||
onCellEdit(event: IGridEditEventArgs, configuration: DataListConfiguration)
|
||||||||||||
Parameters :
Returns :
void
|
onCellEditEnter | ||||||
onCellEditEnter(event: IGridEditEventArgs)
|
||||||
Parameters :
Returns :
void
|
onCellEditExit |
onCellEditExit()
|
Returns :
void
|
Public onColumnFilterInput | |||||||||
onColumnFilterInput(input: any, column: IgxColumnComponent)
|
|||||||||
Parameters :
Returns :
void
|
onDataColumnsChange | ||||||||||||
onDataColumnsChange(visibleDataColumns: string[], showAllColumns: boolean)
|
||||||||||||
Parameters :
Returns :
void
|
Public onDataTypeChange | ||||||||
onDataTypeChange(reload: boolean)
|
||||||||
Parameters :
Returns :
void
|
Public onDrop | ||||
onDrop(event: )
|
||||
Parameters :
Returns :
void
|
Public onExport | ||||
onExport(settings: )
|
||||
Parameters :
Returns :
void
|
onFilteringDone |
onFilteringDone()
|
Returns :
void
|
Public onFilterValueChange |
onFilterValueChange()
|
Returns :
void
|
onHeaderSelectorClick | ||||||
onHeaderSelectorClick(event: any)
|
||||||
Parameters :
Returns :
void
|
Protected onInput | ||||
onInput(link: )
|
||||
Parameters :
Returns :
void
|
Public onItemDropped | ||||||||||||
onItemDropped(event: , cell: IgxGridCell, column: Column)
|
||||||||||||
Parameters :
Returns :
void
|
onRangeSelection | ||||||
onRangeSelection(event: GridSelectionRange)
|
||||||
Parameters :
Returns :
void
|
Public onRowDragStart | ||||
onRowDragStart(event: )
|
||||
Parameters :
Returns :
any
|
Public onRowEdit | ||||||||||||||||
onRowEdit(event: IGridEditEventArgs, configuration: DataListConfiguration, parent: string)
|
||||||||||||||||
Parameters :
Returns :
void
|
Public onRowEditCancel |
onRowEditCancel()
|
Returns :
void
|
Public onRowEditEnter |
onRowEditEnter()
|
Returns :
void
|
Public onRowSelection | ||||||
onRowSelection(event: any)
|
||||||
Parameters :
Returns :
void
|
onViewModeChange |
onViewModeChange()
|
Returns :
void
|
Public onVisibilityChanged | ||||
onVisibilityChanged(event: )
|
||||
Parameters :
Returns :
void
|
Public openContextmenu | ||||
openContextmenu(eventArgs: )
|
||||
Parameters :
Returns :
void
|
Public openDialogForShownAttributes |
openDialogForShownAttributes()
|
Returns :
void
|
Private prepareExcelPasteRequestData | |||||||||
prepareExcelPasteRequestData(selectedCell: , processedData: string[][])
|
|||||||||
Parameters :
Returns :
{ data: {}; dtos: {}; needsDateFormatSelection: boolean; needsSeparatorSelection: boolean; needsD...
|
Public primaryKey | ||||||
primaryKey(configuration: DataListTreeConfiguration)
|
||||||
Parameters :
Returns :
string
|
processDataOnChange | |||||||||
processDataOnChange(event: , reset: boolean)
|
|||||||||
Parameters :
Returns :
void
|
Public reRender | ||||||
reRender(ids: string[])
|
||||||
Parameters :
Returns :
void
|
selectAvailableRows | |||||||||||||||
selectAvailableRows(result: SelectionParams, grid: IgxGridBaseDirective, service: DataListService, rowData: any[])
|
|||||||||||||||
Parameters :
Returns :
any
|
Private setDefaultGroupingExpression |
setDefaultGroupingExpression()
|
Returns :
void
|
Private setDefaultSortingExpressions |
setDefaultSortingExpressions()
|
Returns :
void
|
Protected setDynamicColumns | ||||
setDynamicColumns(attributes: )
|
||||
Parameters :
Returns :
void
|
Protected setEditedRowsData | ||||||||||||||||||
setEditedRowsData(rowId: string, row: any, parent: string, attributes: , configuration: DataListConfiguration)
|
||||||||||||||||||
Parameters :
Returns :
void
|
Public setStaticHeight | ||||||||
setStaticHeight(newrows: number)
|
||||||||
Parameters :
Returns :
void
|
Public showFilteringRow | ||||
showFilteringRow(event: )
|
||||
Parameters :
Returns :
void
|
Public sortStrategy | ||||||
sortStrategy(column: Column)
|
||||||
Parameters :
Returns :
ISortingStrategy
|
Public stopPropagation | ||||||
stopPropagation(event: , field: )
|
||||||
Parameters :
Returns :
boolean
|
Protected subscribeToInputs |
subscribeToInputs()
|
Returns :
void
|
Public takeRecommendedAttributes | ||||||
takeRecommendedAttributes(recommendedAttributes: RecommendedAttributes)
|
||||||
Parameters :
Returns :
boolean
|
Public tileClicked | ||||
tileClicked(event: )
|
||||
Parameters :
Returns :
void
|
Public toggleMode | ||||
toggleMode(event: )
|
||||
Parameters :
Returns :
void
|
Public trackColumns |
trackColumns(index: number, column: Column)
|
Returns :
string
|
Protected updateDataLocale | ||||
updateDataLocale(locale: )
|
||||
Parameters :
Returns :
void
|
updateDataOutput |
updateDataOutput()
|
Returns :
void
|
Public updateDynamicColumns | ||||
updateDynamicColumns(attributes: )
|
||||
Function that gets called everytime the columns get updated from the SelectAttributesDialogComponent. Will directly call setDynamicColumns, if not overwritten
Parameters :
Returns :
void
|
Protected updateLocale | ||||
updateLocale(locale: )
|
||||
Parameters :
Returns :
void
|
Private updateTranslations | ||||||
updateTranslations(transObj?: LangChangeEvent)
|
||||||
Parameters :
Returns :
void
|
Protected validateAllRows |
validateAllRows()
|
Returns :
boolean
|
Protected validateGrid | ||||||
validateGrid(grid: IgxGridBaseDirective)
|
||||||
Parameters :
Returns :
boolean
|
Public validateList | |||||||||
validateList(validation: any, configuration: DataListConfiguration)
|
|||||||||
Parameters :
Returns :
void
|
Public _primaryKey |
_primaryKey:
|
Type : string
|
Private ALWAYS_ALLOWED_TYPES |
ALWAYS_ALLOWED_TYPES:
|
Type : []
|
Default value : [
"LOCALIZED_STRING",
"PLAIN_STRING",
"INTEGER_NUMBER",
"DECIMAL_NUMBER",
"DATE",
]
|
Public attributesDataType |
attributesDataType:
|
Type : string
|
Public attributeUrl |
attributeUrl:
|
Type : string
|
Public attributeUrlChannel |
attributeUrlChannel:
|
Default value : new Subject<string>()
|
Public attributeUrlParams |
attributeUrlParams:
|
Type : any
|
Default value : {}
|
Public availableDataTypes |
availableDataTypes:
|
Type : any[]
|
Default value : []
|
Public cellEditModeActive |
cellEditModeActive:
|
Type : boolean
|
Default value : false
|
Private cellSelectable |
cellSelectable:
|
Type : boolean
|
childComponentMenu |
childComponentMenu:
|
Type : DataListContextMenuComponent
|
Decorators : ViewChild
|
Private clearCellSelectionChannel |
clearCellSelectionChannel:
|
Default value : new Subject<void>()
|
Private clearFiltersAndSortingChannel |
clearFiltersAndSortingChannel:
|
Default value : new Subject<void>()
|
Private clearRowSelectionChannel |
clearRowSelectionChannel:
|
Default value : new Subject<void>()
|
Private clearSortingAndFilteringOnReset |
clearSortingAndFilteringOnReset:
|
Type : boolean
|
Public clipboardOptions |
clipboardOptions:
|
Type : any
|
Public columns |
columns:
|
Type : DataListColumnsService
|
Public columnSelector |
columnSelector:
|
Type : ColumnSelectorCallback
|
Public contentVisible |
contentVisible:
|
Type : boolean
|
Default value : true
|
Public contextContent |
contextContent:
|
Public contextIdentifierChannel |
contextIdentifierChannel:
|
Default value : new ReplaySubject<any>(1)
|
Public contextMenuColumn |
contextMenuColumn:
|
Type : Column
|
Public contextMenuCoordinates |
contextMenuCoordinates:
|
Type : any
|
Default value : {
x: 50,
y: 50,
}
|
Public contextValue |
contextValue:
|
Public currentDataChannel |
currentDataChannel:
|
Default value : new ReplaySubject<any>(1)
|
Public currentLocaleService |
currentLocaleService:
|
Type : CurrentLocaleService
|
Private customFilter |
customFilter:
|
Default value : CustomFilteringOperand.instance()
|
Private dataChannel |
dataChannel:
|
Default value : new ReplaySubject<any>(1)
|
Protected dataInitialized |
dataInitialized:
|
Type : boolean
|
Default value : false
|
dataListStateDirective |
dataListStateDirective:
|
Type : DataListStateDirective
|
Decorators : ViewChild
|
Public dataType |
dataType:
|
Public dataTypeInputChannel |
dataTypeInputChannel:
|
Default value : new Subject<any>()
|
Public dataTypeModeChannel |
dataTypeModeChannel:
|
Default value : new BehaviorSubject<string>("choose")
|
Public density |
density:
|
Type : DisplayDensity
|
Default value : DisplayDensity.compact
|
Private disableCellEditModeChannel |
disableCellEditModeChannel:
|
Default value : new Subject<void>()
|
Private disableContextMenu |
disableContextMenu:
|
Type : boolean
|
Public dynamicColumnsInSubject |
dynamicColumnsInSubject:
|
Default value : new Subject<any[]>()
|
Public eagerLimitChannel |
eagerLimitChannel:
|
Type : ReplaySubject<number>
|
Default value : new ReplaySubject<number>(
1
)
|
editableListCells |
editableListCells:
|
Type : QueryList<ListCellEditComponent>
|
Decorators : ViewChildren
|
Protected editedRows |
editedRows:
|
Type : DataListEditedRows
|
Default value : {}
|
Private endGridEditChannel |
endGridEditChannel:
|
Default value : new Subject<void>()
|
Private exportChannel |
exportChannel:
|
Default value : new Subject<any>()
|
Public filterColumnsChannel |
filterColumnsChannel:
|
Default value : new Subject<any>()
|
Public filterMode |
filterMode:
|
Type : string
|
Public frameHeight |
frameHeight:
|
Type : number
|
Default value : DEFAULT_FRAME_HEIGHT_PX
|
Private getNextPageOnLazyLoad |
getNextPageOnLazyLoad:
|
Type : boolean
|
Public globalFilterInput |
globalFilterInput:
|
Type : boolean
|
Public globalFilterValue |
globalFilterValue:
|
Type : string
|
Public grid |
grid:
|
Type : IgxGridComponent
|
Decorators : ViewChild
|
Public groupingEnabled |
groupingEnabled:
|
Type : boolean
|
Public groupingExpressions |
groupingExpressions:
|
Type : IGroupingExpression[]
|
Default value : []
|
Public groupRowTemplate |
groupRowTemplate:
|
Type : TemplateRef<any>
|
Decorators : ViewChild
|
Public heightModifier |
heightModifier:
|
Type : number
|
Default value : 0
|
Public hideFilters |
hideFilters:
|
Type : boolean
|
Default value : false
|
Public identifierCol |
identifierCol:
|
Public infoText |
infoText:
|
Type : string
|
Default value : "list.results"
|
Public initialDataType |
initialDataType:
|
Type : string
|
inputBoxes |
inputBoxes:
|
Type : QueryList<ElementRef>
|
Decorators : ViewChildren
|
Private inputChannel |
inputChannel:
|
Type : ReplaySubject<any>
|
Default value : new ReplaySubject<any>(1)
|
Public isEagerLoading |
isEagerLoading:
|
Type : boolean
|
Default value : true
|
Public isListMode |
isListMode:
|
Type : boolean
|
Default value : true
|
Public lastSelectedCells |
lastSelectedCells:
|
Type : GridSelectionRange
|
Private lastUriLocalStorage |
lastUriLocalStorage:
|
Type : LocalStorageEntry
|
listCells |
listCells:
|
Type : QueryList<ListCellComponent>
|
Decorators : ViewChildren
|
Public listService |
listService:
|
Type : DataListService
|
Private localeChannel |
localeChannel:
|
Default value : new BehaviorSubject<any>(null)
|
Private localstorageColumnsEntry |
localstorageColumnsEntry:
|
Type : LocalStorageEntry
|
Private localstorageShownAttributesEntry |
localstorageShownAttributesEntry:
|
Type : LocalStorageEntry
|
menuTrigger |
menuTrigger:
|
Type : MatMenuTrigger
|
Decorators : ViewChild
|
Public noopFilterStrategy |
noopFilterStrategy:
|
Default value : NoopFilteringStrategy.instance()
|
Public noopSortStrategy |
noopSortStrategy:
|
Default value : NoopSortingStrategy.instance()
|
Public outlet |
outlet:
|
Type : IgxOverlayOutletDirective
|
Decorators : ViewChild
|
Public overrideTileClickEvent |
overrideTileClickEvent:
|
Type : boolean
|
Private pageLimitPerScroll |
pageLimitPerScroll:
|
Type : number
|
Public pinningConfig |
pinningConfig:
|
Type : IPinningConfig
|
Default value : {
columns: ColumnPinningPosition.Start,
rows: RowPinningPosition.Top,
}
|
Private preselectAttributeProfile |
preselectAttributeProfile:
|
Type : string
|
Private preselectAttributeProfileChannel |
preselectAttributeProfileChannel:
|
Default value : new Subject<string>()
|
Public productChannel |
productChannel:
|
Default value : new Subject<string[]>()
|
Public refreshRows |
refreshRows:
|
Default value : new Subject<any[]>()
|
Private reloadChannel |
reloadChannel:
|
Type : Subject<any>
|
Default value : new Subject<any>()
|
Public reloadOnDataTypeChange |
reloadOnDataTypeChange:
|
Type : boolean
|
Public removeColumnHeader |
removeColumnHeader:
|
Type : boolean
|
Public resetChannel |
resetChannel:
|
Default value : new Subject<any>()
|
Private resetEditDataChannel |
resetEditDataChannel:
|
Default value : new Subject<void>()
|
Public restoreGlobalFilter |
restoreGlobalFilter:
|
Default value : new BehaviorSubject<boolean>(false)
|
Public rowPinningEnabled |
rowPinningEnabled:
|
Type : boolean
|
Default value : false
|
Public rowSelectable |
rowSelectable:
|
Type : boolean
|
Private rowSelectionChannel |
rowSelectionChannel:
|
Default value : new Subject<any>()
|
Public rowSelectionMode |
rowSelectionMode:
|
Type : string
|
Public rowSelectionType |
rowSelectionType:
|
Type : string
|
Default value : "multiple"
|
Public selectAllCheckbox |
selectAllCheckbox:
|
Type : boolean
|
Default value : false
|
Public selectedDataType |
selectedDataType:
|
Type : string
|
Private selectedDataTypeStorage |
selectedDataTypeStorage:
|
Type : LocalStorageEntry
|
Public selectedViewMode |
selectedViewMode:
|
Public selectOptions |
selectOptions:
|
Public selectOptionsUriChannel |
selectOptionsUriChannel:
|
Type : ReplaySubject<any>
|
Default value : new ReplaySubject<any>(
1
)
|
Public showActionsInTableColumn |
showActionsInTableColumn:
|
Type : boolean
|
Default value : false
|
Public showAllColumns |
showAllColumns:
|
Type : boolean
|
Default value : true
|
Public showFilterRow |
showFilterRow:
|
Type : boolean
|
Default value : false
|
Private shownAttributesInputChannel |
shownAttributesInputChannel:
|
Default value : new ReplaySubject<any>(1)
|
Public slideChange |
slideChange:
|
Default value : new Subject<number>()
|
Public slidevalue |
slidevalue:
|
Type : number
|
Default value : 3
|
Private sortBy |
sortBy:
|
Type : SortBy[]
|
Public sortingExpressions |
sortingExpressions:
|
Type : ISortingExpression[]
|
Default value : []
|
Public storingEnabled |
storingEnabled:
|
Type : boolean
|
Default value : false
|
Public tableGridHeight |
tableGridHeight:
|
Type : string
|
Public tableGridWidth |
tableGridWidth:
|
Type : string
|
Public tableHeight |
tableHeight:
|
Type : string
|
Private tableHeightRelativeToRows |
tableHeightRelativeToRows:
|
Type : boolean
|
Private tableHeightVisibleRows |
tableHeightVisibleRows:
|
Type : number
|
Public tableWidth |
tableWidth:
|
Type : null
|
Default value : null
|
Public tileIdentifierField |
tileIdentifierField:
|
Type : string
|
Public tileRedirectLink |
tileRedirectLink:
|
Type : string
|
Public toggleButtonLabel |
toggleButtonLabel:
|
Type : string
|
Public total |
total:
|
unsubscribe |
unsubscribe:
|
Default value : NgUnsubscribe.create()
|
Private viewModeLocalStorage |
viewModeLocalStorage:
|
Type : LocalStorageEntry
|
Public viewModeOptions |
viewModeOptions:
|
Public viewPortHeight |
viewPortHeight:
|
Type : number
|
Default value : window.innerHeight ||
document.documentElement.clientHeight ||
document.body.clientHeight
|
Public visibleDataColumns |
visibleDataColumns:
|
Type : string[]
|
Public visibleDataColumnsOptions |
visibleDataColumnsOptions:
|
Type : Observable<Column[]>
|
Public visibleDataColumnsStorage |
visibleDataColumnsStorage:
|
Type : LocalStorageEntry
|
Public widgetSortingStrategy |
widgetSortingStrategy:
|
Default value : new WidgetSortingStrategy()
|
Public wikiLink |
wikiLink:
|
Type : string
|
uri | ||||
seturi(value: )
|
||||
Parameters :
Returns :
void
|
resetEditData | ||||
setresetEditData(value: )
|
||||
Parameters :
Returns :
void
|
locale | ||||
setlocale(value: )
|
||||
Parameters :
Returns :
void
|
reload | ||||
setreload(value: )
|
||||
Parameters :
Returns :
void
|
reset | ||||
setreset(value: )
|
||||
Parameters :
Returns :
void
|
dataTypeMode | ||||
setdataTypeMode(value: )
|
||||
Parameters :
Returns :
void
|
data | ||||
setdata(data: )
|
||||
Parameters :
Returns :
void
|
contextIdentifier | ||||
setcontextIdentifier(data: )
|
||||
Parameters :
Returns :
void
|
shownAttributes | ||||
setshownAttributes(data: )
|
||||
Parameters :
Returns :
void
|
export | ||||
setexport(settings: )
|
||||
Parameters :
Returns :
void
|
disableCellEditMode | ||||
setdisableCellEditMode(value: )
|
||||
Parameters :
Returns :
void
|
clearCellSelection | ||||
setclearCellSelection(value: )
|
||||
Parameters :
Returns :
void
|
rowSelection | ||||
setrowSelection(value: )
|
||||
Parameters :
Returns :
void
|
clearRowSelection | ||||
setclearRowSelection(value: )
|
||||
Parameters :
Returns :
void
|
endGridEditMode | ||||
setendGridEditMode(value: )
|
||||
Parameters :
Returns :
void
|
clearFiltersAndSorting | ||||
setclearFiltersAndSorting(value: )
|
||||
Parameters :
Returns :
void
|
dataTypeInput | ||||
setdataTypeInput(value: )
|
||||
Parameters :
Returns :
void
|
eagerLimit | ||||
seteagerLimit(value: )
|
||||
Parameters :
Returns :
void
|
attributeUrlChannelInput | ||||
setattributeUrlChannelInput(value: )
|
||||
Parameters :
Returns :
void
|
products | ||||
setproducts(value: )
|
||||
Parameters :
Returns :
void
|
refreshRowInput | ||||
setrefreshRowInput(value: )
|
||||
Parameters :
Returns :
void
|
restoreGlobalFilterInput | ||||
setrestoreGlobalFilterInput(value: )
|
||||
Parameters :
Returns :
void
|
dynamicColumnsIn | ||||
setdynamicColumnsIn(value: )
|
||||
Parameters :
Returns :
void
|
additionalParams | ||||
setadditionalParams(value: )
|
||||
Parameters :
Returns :
void
|
filterColumns | ||||
setfilterColumns(value: )
|
||||
Parameters :
Returns :
void
|
preselectAttributeProfileIn | ||||
setpreselectAttributeProfileIn(value: )
|
||||
Parameters :
Returns :
void
|
import {
AfterViewInit,
ChangeDetectorRef,
Component,
ElementRef,
EventEmitter,
Inject,
Input,
OnDestroy,
OnInit,
Optional,
Output,
QueryList,
TemplateRef,
ViewChild,
ViewChildren,
} from "@angular/core";
import {
ColumnPinningPosition,
DefaultSortingStrategy,
FilteringLogic,
GridSelectionRange,
IGridEditEventArgs,
IGroupingExpression,
IgxColumnComponent,
IgxGridBaseDirective,
IgxGridCell,
IgxGridComponent,
IgxOverlayOutletDirective,
IgxStringFilteringOperand,
IPinningConfig,
ISortingExpression,
ISortingStrategy,
RowPinningPosition,
SortingDirection,
IFilteringOperation,
NoopFilteringStrategy,
NoopSortingStrategy,
IgxHierarchicalGridComponent,
IgxTreeGridComponent,
DisplayDensity,
} from "@infragistics/igniteui-angular";
import { HttpClient } from "@angular/common/http";
import { BehaviorSubject, Observable, ReplaySubject, Subject } from "rxjs";
import { getOrDefault, throwIfUndefined } from "../../widget.configuration";
import { NgUnsubscribe } from "../../../ng-unsubscribe";
import { debounceTime, filter, first, take, takeUntil } from "rxjs/operators";
import {
LocalStorageEntry,
LocalStorageService,
} from "../../../components/local-storage/local-storage.service";
import {
DeletionMode,
Scope,
} from "../../../components/local-storage/local-storage-constants";
import { DataListService } from "../data-list.service";
import { SelectAttributesDialogComponent } from "../../../components/dialog/selectAttributesDialog.component";
import { MatMenuTrigger } from "@angular/material/menu";
import {
angularWidgetBridgeInput,
deepCopy,
flatCopy,
getBodyStyleCssProperty,
} from "../../../components/util/util.service";
import { CurrentLocaleService } from "../../../components/i18n/currentLocale.service";
import { LangChangeEvent, TranslateService } from "@ngx-translate/core";
import { WidgetframeService } from "../../widgetframe/widgetframe.service";
import { AppContext } from "../../../components/app-context/app.context";
import { AppdataStore } from "../../../components/appdata/appdata.store";
import {
Column,
ColumnMap,
DataListConfiguration,
DataListStatus,
DataListTreeConfiguration,
RecommendedAttributes,
SelectionParams,
SortBy,
} from "../../interfaces/list.interfaces";
import { ProgressbarService } from "../../../components/progressbar/progressbar.service";
import { DataListColumnsService } from "../data-list-columns.service";
import { EditAttributeService } from "../../../components/edit-attribute/edit-attribute.service";
import { DataListContextMenuComponent } from "../data-list-context-menu-component/data-list-context-menu.component";
import { DataListStateDirective } from "../data-list-state.directive";
import { ScrollService } from "../../../components/scroll/scroll.service";
import { DataListExportService } from "../data-list-export.service";
import { CustomNotificationService } from "../../../components/notification/customnotification.service";
import { ListCellEditComponent } from "../../../components/list-cell/list-cell-edit.component";
import { ListCellComponent } from "../../../components/list-cell/list-cell.component";
import { densityStorageConfig } from "../../layoutcontainer/layoutcontainer.component";
import { AppService } from "../../configuration/app.service";
import { ConfirmationDialogComponent } from "../../../components/dialog/confirmationDialog.component";
import { WebsocketService } from "../../../components/services/websocket.service";
import { UserService } from "../../../components/user/user.service";
import { DataListApi, DataListApiImpl } from "../data-list.api";
import {
Attribute,
Attributes,
} from "../../../components/edit-attribute/attribute";
import {
CellClassesCallbackRegistry,
ColumnSelectorCallback,
ColumnSelectorCallbackRegistry,
HeaderClassesCallbackRegistry,
} from "../../configuration";
import {
extractAttributeFromCell,
extractAttributeFromRow,
} from "../../../components/list-cell/attribute.util";
import { DataListEndEditService } from "../data-list-end-edit.service";
import { ValidationService } from "../../../components/validation";
import {
DataListActionParameter,
updateRowOrCell,
} from "../default-footer-component/default-data-list-footer.component";
import { DialogService, PageDialogComponent } from "../../../components/dialog";
import { ResizeObserver } from "@juggle/resize-observer";
import {
UnsavedChangesDialogConfiguration,
UnsavedChangesService,
} from "../../../components/util";
import {
NmModuleDescriptor,
NOVOMIND_MODULE_DESCRIPTOR,
} from "../../../../nm.module-descriptor";
import { UtilService } from "../../../components/util/util.service";
const DEFAULT_FRAME_HEIGHT_PX: number = 270;
const DEFAULT_MODIFIERS: string[] = [
"page-title",
"page-frame",
"data-list-frame",
"data-list-header",
"data-list-title",
"data-list-column-header",
];
const TABLE_FOOTER_MODIFIER: string = "data-list-footer";
const DEFAULT_EDIT_BAR_HEIGHT_PX: number = 26;
export const DEFAULT_CLIPBOARD_OPTIONS = {
enabled: true,
copyHeaders: false,
copyFormatters: false,
separator: "\t",
};
const UNSAVED_CHANGES_DIALOG_CONFIG: UnsavedChangesDialogConfiguration = {
allowCancel: false,
allowExitWithoutSaving: true,
allowSaveAndExit: true,
};
@Component({
selector: "nm-data-list-component",
templateUrl: "./data-list.component.html",
styleUrls: ["./data-list.component.scss"],
providers: [EditAttributeService],
})
export class DataListComponent implements OnInit, OnDestroy, AfterViewInit {
@Input()
public configuration: DataListConfiguration;
public tileIdentifierField: string;
@Input()
public widgetId: string;
@Input("uri")
public set uri(value) {
angularWidgetBridgeInput(value, this.inputChannel, this.unsubscribe);
}
@Input("resetEditData")
public set resetEditData(value) {
angularWidgetBridgeInput(
value,
this.resetEditDataChannel,
this.unsubscribe
);
}
@Input("locale")
public set locale(value) {
angularWidgetBridgeInput(value, this.localeChannel, this.unsubscribe);
}
@Input("reload")
public set reload(value) {
angularWidgetBridgeInput(value, this.reloadChannel, this.unsubscribe);
}
@Input("reset")
public set reset(value) {
angularWidgetBridgeInput(value, this.resetChannel, this.unsubscribe);
}
@Input("dataTypeMode")
public set dataTypeMode(value) {
angularWidgetBridgeInput(value, this.dataTypeModeChannel, this.unsubscribe);
}
@Input("data")
public set data(data) {
angularWidgetBridgeInput(data, this.dataChannel, this.unsubscribe);
}
@Input("contextIdentifier")
public set contextIdentifier(data) {
angularWidgetBridgeInput(
data,
this.contextIdentifierChannel,
this.unsubscribe
);
}
@Input("shownAttributesIn")
public set shownAttributes(data) {
angularWidgetBridgeInput(
data,
this.shownAttributesInputChannel,
this.unsubscribe
);
}
@Input("export")
public set export(settings) {
angularWidgetBridgeInput(settings, this.exportChannel, this.unsubscribe);
}
@Input("disableCellEditMode")
public set disableCellEditMode(value) {
angularWidgetBridgeInput(
value,
this.disableCellEditModeChannel,
this.unsubscribe
);
}
@Input("clearCellSelection")
public set clearCellSelection(value) {
angularWidgetBridgeInput(
value,
this.clearCellSelectionChannel,
this.unsubscribe
);
}
@Input("rowSelection")
public set rowSelection(value) {
angularWidgetBridgeInput(value, this.rowSelectionChannel, this.unsubscribe);
}
@Input("clearRowSelection")
public set clearRowSelection(value) {
angularWidgetBridgeInput(
value,
this.clearRowSelectionChannel,
this.unsubscribe
);
}
@Input("endGridEditMode")
public set endGridEditMode(value) {
angularWidgetBridgeInput(value, this.endGridEditChannel, this.unsubscribe);
}
@Input("clearFiltersAndSorting")
public set clearFiltersAndSorting(value) {
angularWidgetBridgeInput(
value,
this.clearFiltersAndSortingChannel,
this.unsubscribe
);
}
@Input("dataTypeInput")
public set dataTypeInput(value) {
angularWidgetBridgeInput(
value,
this.dataTypeInputChannel,
this.unsubscribe
);
}
@Input("eagerLimit")
public set eagerLimit(value) {
angularWidgetBridgeInput(value, this.eagerLimitChannel, this.unsubscribe);
}
@Input("attributeUrl")
public set attributeUrlChannelInput(value) {
angularWidgetBridgeInput(value, this.attributeUrlChannel, this.unsubscribe);
}
@Input("products")
public set products(value) {
angularWidgetBridgeInput(value, this.productChannel, this.unsubscribe);
}
@Input("refreshRows")
public set refreshRowInput(value) {
angularWidgetBridgeInput(value, this.refreshRows, this.unsubscribe);
}
@Input("restoreGlobalFilter")
public set restoreGlobalFilterInput(value) {
angularWidgetBridgeInput(value, this.restoreGlobalFilter, this.unsubscribe);
}
@Input("dynamicColumnsIn")
public set dynamicColumnsIn(value) {
angularWidgetBridgeInput(
value,
this.dynamicColumnsInSubject,
this.unsubscribe
);
}
@Input("additionalParams")
public set additionalParams(value) {
this.attributeUrlParams = value;
}
@Input("filterColumns")
public set filterColumns(value) {
angularWidgetBridgeInput(
value,
this.filterColumnsChannel,
this.unsubscribe
);
}
@Input("preselectAttributeProfile")
public set preselectAttributeProfileIn(value) {
angularWidgetBridgeInput(
value,
this.preselectAttributeProfileChannel,
this.unsubscribe
);
}
@Input("autoFocus") public autoFocus: boolean = false;
@Output("dynamicPrefix")
public dynamicPrefixOutput = new EventEmitter<string>();
@Output("dynamicColumns")
public dynamicColumnsOutput = new EventEmitter<Column[]>();
@Output("selectedItems")
public selectedItems = new EventEmitter<SelectionParams>();
@Output("shownAttributes")
public shownAttributesOutput = new EventEmitter<any[]>();
@Output("editedRows")
public editedRowsOutput = new EventEmitter<DataListEditedRows>();
@Output("editedRow")
public editedRowOutput = new EventEmitter<DataListEditedRow>();
@Output("total")
public totalOutput = new EventEmitter<any>();
@Output("gridOutput")
public gridOutput = new EventEmitter<any>();
@Output("viewMode")
public viewModeOutput = new EventEmitter<any>();
@Output("dataType")
public dataTypeOutput = new EventEmitter<any>();
@Output("isValid")
public isValidOutput = new EventEmitter<any>();
@Output("dataLoaded")
public dataLoadedOutput = new EventEmitter<any>();
@Output("currentData")
public currentData = new EventEmitter<any>();
@Output("editableCell")
public editableCell = new EventEmitter<any>();
@Output("rowEditEnter")
public rowEditEnterEmitter = new EventEmitter<any>();
@Output("rowEditLeave")
public rowEditLeaveEmitter = new EventEmitter<any>();
@Output("api")
public apiEmitter = new EventEmitter<DataListApi>();
@Output("toggleButtonChange")
public toggleButtonChangeEmitter = new EventEmitter<boolean>();
@Output("tileClicked")
public tileClickedEventEmitter = new EventEmitter<any>();
@Output("statusOut")
public statusOutput = new EventEmitter<DataListStatus>();
@Output("reorderedRows")
public reorderedRows = new EventEmitter<any>();
@Output("onDrop")
public onDropEmitter = new EventEmitter<any>();
@Output("onCellSelect")
public onCellSelect = new EventEmitter<any>();
public attributeUrlChannel = new Subject<string>();
public productChannel = new Subject<string[]>();
public refreshRows = new Subject<any[]>();
public dynamicColumnsInSubject = new Subject<any[]>();
private resetEditDataChannel = new Subject<void>();
private inputChannel: ReplaySubject<any> = new ReplaySubject<any>(1);
private reloadChannel: Subject<any> = new Subject<any>();
private localeChannel = new BehaviorSubject<any>(null);
private dataChannel = new ReplaySubject<any>(1);
private shownAttributesInputChannel = new ReplaySubject<any>(1);
private exportChannel = new Subject<any>();
public resetChannel = new Subject<any>();
public currentDataChannel = new ReplaySubject<any>(1);
public filterColumnsChannel = new Subject<any>();
public contextIdentifierChannel = new ReplaySubject<any>(1);
public restoreGlobalFilter = new BehaviorSubject<boolean>(false);
private disableCellEditModeChannel = new Subject<void>();
private clearCellSelectionChannel = new Subject<void>();
private clearRowSelectionChannel = new Subject<void>();
private rowSelectionChannel = new Subject<any>();
private endGridEditChannel = new Subject<void>();
private clearFiltersAndSortingChannel = new Subject<void>();
private preselectAttributeProfileChannel = new Subject<string>();
private preselectAttributeProfile: string;
public tableWidth = null;
public slidevalue: number = 3;
public slideChange = new Subject<number>();
public attributeUrl: string;
public attributeUrlParams: any = {};
public attributesDataType: string;
public cellEditModeActive: boolean = false;
// The column that was right clicked when opening the context menu
public contextMenuColumn: Column;
public dataTypeModeChannel = new BehaviorSubject<string>("choose");
public dataTypeInputChannel = new Subject<any>();
public groupingExpressions: IGroupingExpression[] = [];
public sortingExpressions: ISortingExpression[] = [];
public filterMode: string;
public selectOptionsUriChannel: ReplaySubject<any> = new ReplaySubject<any>(
1
);
public eagerLimitChannel: ReplaySubject<number> = new ReplaySubject<number>(
1
);
@ViewChild("table", { static: true }) public grid: IgxGridComponent;
@ViewChild("groupRowTemplate", { static: true })
public groupRowTemplate: TemplateRef<any>;
@ViewChild(MatMenuTrigger) menuTrigger: MatMenuTrigger;
@ViewChild(DataListContextMenuComponent, { static: true })
childComponentMenu: DataListContextMenuComponent;
@ViewChild(DataListStateDirective)
dataListStateDirective: DataListStateDirective;
@ViewChildren(ListCellEditComponent)
editableListCells: QueryList<ListCellEditComponent>;
@ViewChildren(ListCellComponent) listCells: QueryList<ListCellComponent>;
@ViewChildren("inputBox") inputBoxes: QueryList<ElementRef>;
@ViewChild(IgxOverlayOutletDirective, {
read: IgxOverlayOutletDirective,
static: true,
})
public outlet: IgxOverlayOutletDirective;
public pinningConfig: IPinningConfig = {
columns: ColumnPinningPosition.Start,
rows: RowPinningPosition.Top,
};
public isListMode: boolean = true;
private lastUriLocalStorage: LocalStorageEntry;
private localstorageShownAttributesEntry: LocalStorageEntry;
private localstorageColumnsEntry: LocalStorageEntry;
private viewModeLocalStorage: LocalStorageEntry;
private selectedDataTypeStorage: LocalStorageEntry;
public visibleDataColumns: string[];
public visibleDataColumnsStorage: LocalStorageEntry;
public visibleDataColumnsOptions: Observable<Column[]>;
unsubscribe = NgUnsubscribe.create();
public isEagerLoading: boolean = true;
public total;
public rowSelectable: boolean;
public rowSelectionMode: string;
public contextContent;
public contextValue;
public contextMenuCoordinates: any = {
x: 50,
y: 50,
};
public showFilterRow: boolean = false;
public infoText: string = "list.results";
public wikiLink: string;
public contentVisible: boolean = true;
public dataType;
public identifierCol;
public availableDataTypes: any[] = [];
public initialDataType: string;
public reloadOnDataTypeChange: boolean;
public columns: DataListColumnsService;
public listService: DataListService;
public columnSelector: ColumnSelectorCallback;
public widgetSortingStrategy = new WidgetSortingStrategy();
public viewModeOptions;
public selectedViewMode;
public globalFilterValue: string;
public globalFilterInput: boolean;
public selectedDataType: string;
public lastSelectedCells: GridSelectionRange;
public groupingEnabled: boolean;
public viewPortHeight: number =
window.innerHeight ||
document.documentElement.clientHeight ||
document.body.clientHeight;
public tableHeight: string;
public frameHeight: number = DEFAULT_FRAME_HEIGHT_PX;
public rowPinningEnabled: boolean = false;
public heightModifier: number = 0;
public tableGridHeight: string;
public tableGridWidth: string;
protected dataInitialized: boolean = false;
protected editedRows: DataListEditedRows = {};
public selectOptions;
private disableContextMenu: boolean;
private cellSelectable: boolean;
private getNextPageOnLazyLoad: boolean;
private pageLimitPerScroll: number;
private sortBy: SortBy[];
private tableHeightRelativeToRows: boolean;
private tableHeightVisibleRows: number;
public density: DisplayDensity = DisplayDensity.compact;
public _primaryKey: string;
public toggleButtonLabel: string;
public clipboardOptions: any;
public tileRedirectLink: string;
public overrideTileClickEvent: boolean;
public selectAllCheckbox: boolean = false;
public rowSelectionType = "multiple";
private clearSortingAndFilteringOnReset: boolean;
public storingEnabled: boolean = false;
public showAllColumns: boolean = true;
public hideFilters: boolean = false;
public showActionsInTableColumn: boolean = false;
public removeColumnHeader: boolean;
public noopFilterStrategy = NoopFilteringStrategy.instance();
public noopSortStrategy = NoopSortingStrategy.instance();
private customFilter = CustomFilteringOperand.instance();
constructor(
protected localStorageService: LocalStorageService,
protected dialog: DialogService,
protected notificationService: CustomNotificationService,
protected translateService: TranslateService,
public currentLocaleService: CurrentLocaleService,
protected widgetFrameService: WidgetframeService,
protected appContext: AppContext,
protected appdataStore: AppdataStore,
protected cdr: ChangeDetectorRef,
protected http: HttpClient,
protected progressbarService: ProgressbarService,
protected editAttributeService: EditAttributeService,
protected scrollService: ScrollService,
protected dataListExportService: DataListExportService,
protected websocketService: WebsocketService,
protected userService: UserService,
protected dataListEndEditService: DataListEndEditService,
protected validationService: ValidationService,
protected unsavedChangesService: UnsavedChangesService,
@Optional() protected appService: AppService,
@Inject(NOVOMIND_MODULE_DESCRIPTOR) private module: NmModuleDescriptor
) {}
protected dataLoaded(data) {
this.editedRowsOutput.next({});
this.editedRows = {};
if (this.grid) {
this.grid.reflow();
this.setStaticHeight();
}
this.currentData.emit(data);
if (this.configuration.visibleDataColumnsSelection) {
let showAll: boolean = false;
if (this.selectedDataType != "attributes") {
showAll = true;
}
this.onDataColumnsChange(this.visibleDataColumns, showAll);
}
if (this.grid) {
this.grid.verticalScroll.cdr.detectChanges();
this.grid.verticalScrollContainer.cdr.detectChanges();
this.grid.cdr.detectChanges();
this.cdr.detectChanges();
if (this.globalFilterValue) {
this.onFilterValueChange();
}
this.currentDataChannel.next(
this.grid.dataView ? this.grid.dataView : this.grid.data
);
this.onRowSelection({ newSelection: this.grid.selectedRows });
}
this.dataLoadedOutput.next();
this.autosizeColumns();
this.dataListStateDirective.restoreGridState();
}
private autosizeColumns() {
if (!this.grid) {
return;
}
const autosizableColumns = this.columns.autosizableColumns();
if (!autosizableColumns || autosizableColumns.length == 0) {
return;
}
this.grid.columnList
.filter((column: IgxColumnComponent) =>
autosizableColumns.includes(column.field)
)
.forEach((column: IgxColumnComponent) => {
if (!column.headerCell) {
return;
}
column.autosize(true);
});
}
public getGridColumnWidth(column: Column) {
if (!this.grid) {
return column.width;
}
const gridColumn = this.grid.getColumnByName(column.field);
return gridColumn?.width ? gridColumn?.width : column.width;
}
public setStaticHeight(newrows: number = 0) {
if (this.configuration.dynamicTableHeight) {
return;
}
if (
this.configuration.tableGridHeight ||
this.configuration.tableGridHeight === null
) {
return;
}
if (newrows === 0) {
newrows = this.tableHeightVisibleRows;
}
setTimeout(() => {
let height =
(this.grid.data.length + newrows <= 10
? this.grid.data.length + newrows
: 10) *
this.grid.rowHeight +
70;
height = height > 100 ? height : 100;
this.grid.height = height.toString() + "px";
this.grid.cdr.detectChanges();
}, 1);
}
public ngOnInit() {
this._primaryKey = this.primaryKey(this.configuration);
this.toggleButtonLabel = getOrDefault(
this.configuration.toggleButtonLabel,
""
);
this.tileRedirectLink = this.configuration.tileRedirectLink;
this.overrideTileClickEvent = getOrDefault(
this.configuration.overrideTileClickEvent,
false
);
this.tileIdentifierField = getOrDefault(
this.configuration.tileIdentifierField,
"identifier"
);
this.attributeUrl = this.configuration.attributeUrl;
this.attributesDataType = this.configuration.attributesDataType;
this.tableWidth = getOrDefault(this.configuration.tableWidth, "100%");
this.frameHeight = getOrDefault(
this.configuration.frameHeight,
DEFAULT_FRAME_HEIGHT_PX
);
this.tableHeightRelativeToRows = getOrDefault(
this.configuration.tableHeightRelativeToRows,
false
);
this.removeColumnHeader = getOrDefault(
this.configuration.removeColumnHeader,
false
);
this.tableHeightVisibleRows = getOrDefault(
this.configuration.tableHeightVisibleRows,
0
);
this.applyDensityFromLocalStorage();
this.availableDataTypes = getOrDefault(
this.configuration.availableDataTypes,
[]
);
this.columns = new DataListColumnsService(
<DataListConfiguration>this.configuration,
this.appService,
this.translateService
);
this.listService = new DataListService(
this.http,
this.progressbarService,
this.notificationService,
this.translateService,
this.columns,
this.websocketService,
this.localstorageShownAttributesEntry,
this.userService
);
if (this.localeChannel.value) {
this.listService.selectedLocale = this.localeChannel.value;
}
this.columns.dynamicColumns
.pipe(takeUntil(this.unsubscribe))
.subscribe((data) => this.dynamicColumnsOutput.next(data));
this.listService.totalSubject
.pipe(takeUntil(this.unsubscribe))
.subscribe((data) => this.totalOutput.next(data));
this.rowSelectable = getOrDefault(this.configuration.rowSelectable, true);
this.rowSelectionMode = getOrDefault(
this.configuration.rowSelectionMode,
"multiple"
);
this.isEagerLoading =
"eager" == getOrDefault(this.configuration.loadingMode, "eager");
this.globalFilterInput = getOrDefault(
this.configuration.globalFilterInput,
true
);
this.groupingEnabled = getOrDefault(
this.configuration.groupingEnabled,
true
);
this.disableContextMenu = getOrDefault(
this.configuration.disableContextMenu,
false
);
this.cellSelectable = getOrDefault(this.configuration.cellSelectable, true);
this.getNextPageOnLazyLoad = getOrDefault(
this.configuration.getNextPageOnLazyLoad,
false
);
this.rowPinningEnabled = getOrDefault(
this.configuration.rowPinningEnabled,
false
);
this.pageLimitPerScroll = this.configuration.pageLimitPerScroll;
this.initialDataType = this.configuration.initialDataType;
//quickFilter || excelStyleFilter || inlineFilter
this.filterMode = getOrDefault(
this.configuration.filterMode,
"excelStyleFilter"
);
this.reloadOnDataTypeChange = getOrDefault(
this.configuration.reloadOnDataTypeChange,
true
);
this.clearSortingAndFilteringOnReset = getOrDefault(
this.configuration.clearSortingAndFilteringOnReset,
false
);
this.tableGridHeight = getOrDefault(
this.configuration.tableGridHeight,
"100%"
);
this.tableGridWidth = getOrDefault(
this.configuration.tableGridWidth,
"100%"
);
if (this.isEagerLoading && this.configuration.eagerLimit) {
this.listService.setEagerLimit(this.configuration.eagerLimit);
}
if (this.configuration.visibleDataColumnsSelection) {
this.visibleDataColumnsStorage =
this.localStorageService.getLocalStorageEntry(
"visibleDataColumns" + this.configuration.title,
Scope.USER_AND_CLIENT,
DeletionMode.RESET
);
if (this.visibleDataColumnsStorage.exists()) {
this.visibleDataColumns = JSON.parse(
this.visibleDataColumnsStorage.value
);
} else {
this.visibleDataColumns = this.configuration.visibleDataColumnsDefault;
}
}
if (this.availableDataTypes.length > 0) {
this.selectedDataType = this.availableDataTypes[0];
}
if (this.dataTypeModeChannel.value === "choose") {
this.selectedDataTypeStorage =
this.localStorageService.getLocalStorageEntry(
"selectedDataType" + this.configuration.title,
Scope.USER_AND_CLIENT,
DeletionMode.RESET
);
}
if (this.selectedDataTypeStorage.exists()) {
this.selectedDataType = JSON.parse(this.selectedDataTypeStorage.value);
} else if (this.initialDataType) {
this.selectedDataType = this.initialDataType;
} else {
this.selectedDataType = this.availableDataTypes[0];
}
this.listService.initialize(
this.grid,
this.isEagerLoading,
this.configuration,
(data) => this.dataLoaded(data),
this.cdr,
this.selectedDataType
);
this.dataTypeOutput.next(this.selectedDataType);
this.listService.setNextPage(this.getNextPageOnLazyLoad);
this.listService.setPageLimit(this.pageLimitPerScroll);
this.gridOutput.emit(this.grid);
if (this.configuration.columnSelector) {
this.columnSelector = ColumnSelectorCallbackRegistry.get(
this.configuration.columnSelector
);
}
this.viewModeLocalStorage = this.localStorageService.getLocalStorageEntry(
this.configuration["title"] + "-viewMode",
Scope.USER_AND_CLIENT,
DeletionMode.RESET
);
if (this.configuration.viewModeSelection) {
if (this.configuration.viewModeOptions) {
this.viewModeOptions = this.configuration.viewModeOptions;
} else if (this.configuration.viewModeSelection) {
this.viewModeOptions = [];
this.viewModeOptions.push({
identifier: "listView",
description: "button.list-view",
icon: "view_list",
});
this.viewModeOptions.push({
identifier: "tileView",
description: "button.tile-view",
icon: "view_module",
});
}
if (this.viewModeLocalStorage.exists()) {
this.selectedViewMode = this.viewModeOptions.filter(
(mode) =>
mode.identifier === JSON.parse(this.viewModeLocalStorage.value)
)[0];
}
if (!this.selectedViewMode && this.configuration.viewModeSelection) {
this.selectedViewMode = this.viewModeOptions[0];
}
this.viewModeOutput.next(this.selectedViewMode.identifier);
this.listService.setViewmode(this.selectedViewMode.identifier);
}
this.setDefaultGroupingExpression();
this.setDefaultSortingExpressions();
if (this.configuration.pinnedRows) {
this.configuration.pinnedRows.forEach((row) => this.grid.pinRow(row));
}
this.lastUriLocalStorage = this.localStorageService.getLocalStorageEntry(
"last-uri-1" + this.configuration.title,
Scope.USER_AND_CLIENT,
DeletionMode.RESET
);
if (this.configuration.localStorageShownAttributes) {
this.localstorageShownAttributesEntry =
this.localStorageService.getLocalStorageEntry(
this.configuration.localStorageShownAttributes,
Scope.USER_AND_CLIENT,
DeletionMode.NEVER
);
}
if (this.configuration.dynamicColumnLink) {
this.widgetFrameService
.getData(this.configuration.dynamicColumnLink)
.subscribe((attributes) => {
// TODO This wont play nicely with localstorage recovery, since it will just override it :(
this.columns.updateColumns(attributes._embedded.attributes);
});
}
this.clipboardOptions = Object.assign(
{},
DEFAULT_CLIPBOARD_OPTIONS,
this.configuration.clipboardOptions
);
this.tableHeight = this.getTableHeight();
this.localeChannel.pipe(takeUntil(this.unsubscribe)).subscribe((locale) => {
this.updateDataLocale(locale);
});
if (this.configuration.exportPath) {
this.dataListExportService.exportPath = this.configuration.exportPath;
}
this.scrollService
.isToolBoxEditBarVisible()
.pipe(takeUntil(this.unsubscribe))
.subscribe((data) => {
if (this.configuration.tableHeight) {
return;
}
if (data && data.active && !!data.context) {
this.heightModifier = DEFAULT_EDIT_BAR_HEIGHT_PX;
} else {
this.heightModifier = 0;
}
// this.tableHeight = String(this.viewPortHeight - this.frameHeight - this.heightModifier) + 'px';
this.cdr.markForCheck();
});
this.scrollService
.getChangeViewPortSize()
.pipe(takeUntil(this.unsubscribe))
.subscribe((newViewPortHeight) => {
this.viewPortHeight = newViewPortHeight;
// Waiting for sidebar animation to finish to adjust width;
setTimeout(() => {
this.grid.reflow();
}, 200);
});
this.localstorageColumnsEntry =
this.localStorageService.getLocalStorageEntry(
"ColumnsEntry",
Scope.USER_AND_CLIENT,
DeletionMode.NEVER
);
if (
this.localstorageShownAttributesEntry &&
this.localstorageShownAttributesEntry.exists()
) {
this.columns.shownAttributes = JSON.parse(
this.localstorageShownAttributesEntry.value
);
this.columns.updateColumns(this.columns.shownAttributes);
this.shownAttributesOutput.next(this.getShownAttributes());
}
if (this.localstorageColumnsEntry.exists()) {
this.grid.columnList["_results"] = JSON.parse(
this.localstorageColumnsEntry.value
);
}
this.appdataStore.getAppdata().subscribe((appData) => {
this.showActionsInTableColumn =
appData[this.module.identifier].configuration.showActionsInTableColumn;
});
this.subscribeToInputs();
this.sortBy = this.configuration.sortBy;
this.grid.outlet = this.outlet;
//Disable filter and sorting strategy if remote loading
if (!this.isEagerLoading) {
this.grid.sortStrategy = this.noopSortStrategy;
this.grid.filterStrategy = this.noopFilterStrategy;
}
}
protected updateDataLocale(locale) {
if (this.listService) {
this.listService.selectedLocale = locale;
this.listService.processData(true);
}
}
protected updateLocale(locale) {
this.listService.reloadGrid();
this.columns.updateDynamicColumnsHeaders(locale);
}
private setDefaultGroupingExpression() {
if (this.configuration.groupingExpressions) {
this.configuration.groupingExpressions.forEach((expression) => {
const dir =
expression.direction === "asc"
? SortingDirection.Asc
: SortingDirection.Desc;
let strategy = DefaultSortingStrategy.instance();
this.groupingExpressions.push({
dir,
fieldName: expression.field,
ignoreCase: false,
strategy,
groupingComparer: strategy.compareValues,
});
});
}
}
private setDefaultSortingExpressions() {
if (this.configuration.sortingExpressions) {
this.configuration.sortingExpressions.forEach((expression) => {
const dir =
expression.direction === "asc"
? SortingDirection.Asc
: SortingDirection.Desc;
this.sortingExpressions.push({
dir,
fieldName: expression.field,
});
});
}
}
protected clearSelectedRows() {
this.selectedItems.next(null);
if (this.grid.data) {
this.grid.deselectAllRows();
}
}
protected doReset() {
this.clearSelectedRows();
this.listService.reset();
}
public doReload(force: boolean = false) {
this.unsavedChangesService
.leaveContext(UNSAVED_CHANGES_DIALOG_CONFIG)
.subscribe((response) => {
if (!response) {
return;
}
this.listService.reloadGrid(force);
if (this.grid.data) {
this.grid.deselectAllRows();
this.onRowSelection({ newSelection: this.grid.selectedRows });
}
});
}
public doRefresh() {
let selectedRows = this.grid.selectedRows;
this.listService.reloadGrid();
if (selectedRows) {
this.grid.selectRows(selectedRows, true);
this.onRowSelection({ newSelection: this.grid.selectedRows });
}
}
public onDataTypeChange(reload: boolean = true) {
this.unsavedChangesService
.leaveContext(UNSAVED_CHANGES_DIALOG_CONFIG)
.subscribe((response) => {
if (!response) {
return;
}
if (this.grid.data) {
this.grid.deselectAllRows();
}
this.selectedDataTypeStorage.value = JSON.stringify(
this.selectedDataType
);
this.listService.setDataType(
this.selectedDataType,
this.reloadOnDataTypeChange && reload
);
this.dynamicPrefixOutput.next(this.getDynamicPrefix());
this.dataTypeOutput.next(this.selectedDataType);
this.emitDataListStatus("dataType");
});
}
private emitDataListStatus(lastChange: string) {
this.statusOutput.next({
lastChange,
attributes: this.getShownAttributes(),
dataType: this.selectedDataType,
});
}
public ngAfterViewInit() {
this.updateTranslations();
if (this.selectedViewMode) {
this.onViewModeChange();
}
this.grid.groupRowTemplate = this.groupRowTemplate;
setTimeout(() => {
this.grid.reflow();
}, 200);
if (this.sortBy) {
this.doInitialSorting();
}
this.apiEmitter.next(new DataListApiImpl(this, this.configuration));
this.emitDataListStatus(null);
this.dataChannel.pipe(takeUntil(this.unsubscribe)).subscribe((value) => {
if (this.listService) {
this.listService.updateData(value, 0, true);
this.listService.totalSubject.next(value.length);
this.currentData.emit(value);
this.setStaticHeight();
this.grid.cdr.detectChanges();
this.cdr.detectChanges();
this.validateList(null, null);
}
});
this.emitDataListStatus(null);
}
private doInitialSorting() {
let sortingExpressions: ISortingExpression[] = [];
this.sortBy.forEach((element) => {
let columnId = element.field;
let sortDirection = element.direction;
if (sortDirection && columnId) {
let direction = this.getSortDirection(sortDirection.toLowerCase());
sortingExpressions.push({
fieldName: columnId,
dir: direction,
ignoreCase: true,
});
}
});
this.grid.sortingExpressions = sortingExpressions;
}
private getSortDirection(direction) {
if (direction === "asc") {
return SortingDirection.Asc;
} else if (direction === "desc") {
return SortingDirection.Desc;
} else {
return SortingDirection.None;
}
}
protected subscribeToInputs() {
this.shownAttributesInputChannel
.pipe(
takeUntil(this.unsubscribe),
filter((data) => !!data)
)
.subscribe((attributes) => {
this.updateDynamicColumns(attributes);
});
this.reloadChannel
.asObservable()
.pipe(takeUntil(this.unsubscribe))
.subscribe((force) => {
this.doReload(force);
});
this.dataTypeModeChannel.pipe(takeUntil(this.unsubscribe)).subscribe(() => {
this.dynamicPrefixOutput.next(this.getDynamicPrefix());
});
this.inputChannel
.asObservable()
.pipe(takeUntil(this.unsubscribe))
.subscribe((link) => {
this.storingEnabled = false;
if (
this.configuration.reloadWithUnsavedChanges === false &&
this.editedRows &&
Object.keys(this.editedRows).length !== 0
) {
const dialogRef = this.dialog.open(ConfirmationDialogComponent);
dialogRef.componentInstance.message = this.translateService.instant(
"message.confirmation.unsavedChanges"
);
dialogRef.componentInstance.title =
this.translateService.instant("hl.confirmation");
dialogRef.componentInstance.buttonAcceptTitle = "button.accept";
dialogRef.componentInstance.buttonCancelTitle = "button.cancel";
dialogRef.afterClosed().subscribe((data) => {
if (data) {
this.handleInput(link);
}
});
return;
}
this.handleInput(link);
});
this.refreshRows.pipe(takeUntil(this.unsubscribe)).subscribe((data) => {
const primaryKey = this.primaryKey(this.configuration);
const keys = data.map((entry) => entry[primaryKey]);
this.reRender(keys);
});
this.dynamicColumnsInSubject
.pipe(takeUntil(this.unsubscribe))
.subscribe((data) => {
//Treat these columns as if those are coming from the backend,
// since columns coming from the backend will always be accepted
this.columns.updateColumns(data, true);
});
this.productChannel.pipe(takeUntil(this.unsubscribe)).subscribe((data) => {
this.listService.products = data;
});
this.attributeUrlChannel
.pipe(takeUntil(this.unsubscribe))
.subscribe((url) => (this.attributeUrl = url));
this.resetEditDataChannel
.asObservable()
.pipe(takeUntil(this.unsubscribe))
.subscribe(() => {
this.editedRows = {};
this.editedRowsOutput.next({});
this.currentData.emit(this.grid.data);
});
this.resetChannel
.asObservable()
.pipe(takeUntil(this.unsubscribe))
.subscribe(() => {
this.doReset();
if (this.sortBy) {
this.doInitialSorting();
}
if (this.clearSortingAndFilteringOnReset) {
this.clearAllFiltersAndSorting();
}
});
this.exportChannel
.asObservable()
.pipe(takeUntil(this.unsubscribe))
.subscribe((data) => {
this.onExport(data);
});
this.currentLocaleService
.getCurrentLocale()
.pipe(takeUntil(this.unsubscribe))
.subscribe((locale) => {
this.updateLocale(locale);
});
this.translateService.onLangChange
.pipe(takeUntil(this.unsubscribe))
.subscribe((transObj) => {
this.updateTranslations(transObj);
});
this.disableCellEditModeChannel
.asObservable()
.pipe(takeUntil(this.unsubscribe))
.subscribe(() => {
const selectedCells = this.grid.selectedCells;
Object.keys(selectedCells).forEach((key) => {
let cell = this.grid.getCellByColumn(
selectedCells[key].cellID.rowIndex,
selectedCells[key].column.field
);
cell.editMode = false;
});
});
this.clearCellSelectionChannel
.asObservable()
.pipe(takeUntil(this.unsubscribe))
.subscribe(() => {
if (this.grid.selectedCells.length > 0) {
this.grid.clearCellSelection();
}
});
this.clearRowSelectionChannel
.asObservable()
.pipe(takeUntil(this.unsubscribe))
.subscribe(() => {
this.clearSelectedRows();
});
this.rowSelectionChannel
.asObservable()
.pipe(takeUntil(this.unsubscribe))
.subscribe((rows) => {
if (rows) {
this.grid.deselectAllRows();
this.grid.selectRows(rows);
this.onRowSelection({ newSelection: this.grid.selectedRows });
}
});
this.clearFiltersAndSortingChannel
.asObservable()
.pipe(takeUntil(this.unsubscribe))
.subscribe(() => {
this.clearAllFiltersAndSorting();
});
this.endGridEditChannel
.asObservable()
.pipe(takeUntil(this.unsubscribe))
.subscribe(() => {
this.grid.endEdit(true);
});
this.listService.dataLoaded
.asObservable()
.pipe(takeUntil(this.unsubscribe))
.subscribe((data) => {
if (!this.dataInitialized) {
this.dataInitialized = true;
} else if (this.isEagerLoading && this.tableHeightRelativeToRows) {
return;
}
});
this.dataTypeInputChannel
.pipe(takeUntil(this.unsubscribe))
.subscribe((dataType) => {
this.selectedDataType = dataType;
this.onDataTypeChange(this.reloadOnDataTypeChange);
});
this.eagerLimitChannel
.pipe(takeUntil(this.unsubscribe))
.subscribe((eagerLimit) => {
this.listService.setEagerLimit(eagerLimit);
});
this.filterColumnsChannel
.pipe(takeUntil(this.unsubscribe))
.subscribe((columns) => {
this.tableWidth = columns.length === 1 ? null : "100%";
this.grid.columns.forEach((column) => {
column.hidden = columns.indexOf(column.field) === -1;
return column;
});
this.grid.reflow();
this.grid.cdr.detectChanges();
});
this.preselectAttributeProfileChannel
.asObservable()
.pipe(takeUntil(this.unsubscribe))
.subscribe((profile) => (this.preselectAttributeProfile = profile));
}
protected handleInput(link) {
this.grid.navigateTo(0, 0);
this.clearAllFiltersAndSorting(true, false, this.restoreGlobalFilter.value);
this.onInput(link);
if (this.sortBy) {
this.doInitialSorting();
}
}
public reRender(ids: string[]) {
const primaryKey = this.primaryKey(this.configuration);
this.listCells
.filter((cell) => ids.indexOf(cell.row[primaryKey]) !== -1)
.forEach((cell) => {
cell.update();
});
}
protected onInput(link) {
if (this.columns && this.columns.shownAttributes) {
this.columns.updateColumns(this.columns.shownAttributes);
}
this.listService.updateLink(link);
}
public primaryKey(configuration: DataListTreeConfiguration): string {
return configuration.primaryKey || "identifier";
}
public onRowEdit(
event: IGridEditEventArgs,
configuration: DataListConfiguration = this.configuration,
parent: string = null
) {
this.rowEditLeaveEmitter.next();
if (!configuration.rowEditable && parent == null) {
return;
}
const attributes = {};
for (const identifier in event.newValue) {
if (!event.newValue.hasOwnProperty(identifier)) {
continue;
}
if (!event.oldValue.hasOwnProperty(identifier)) {
attributes[identifier] = event.newValue[identifier];
continue;
}
let oldChanges =
event.oldValue[identifier] && event.oldValue[identifier].changes
? event.oldValue[identifier].changes
: 0;
let newChanges =
event.newValue[identifier] && event.newValue[identifier].changes
? event.newValue[identifier].changes
: 0;
if (oldChanges != newChanges) {
attributes[identifier] = event.newValue[identifier];
}
}
this.fireEditedRowsEvent(
event.rowID,
event.newValue,
parent,
attributes,
configuration
);
}
onCellEdit(
event: IGridEditEventArgs,
configuration: DataListConfiguration = this.configuration
) {
if (configuration.rowEditable) {
return;
}
let row = this.grid.getRowByKey(event.rowID);
if (
event.oldValue &&
(event.oldValue === event.newValue ||
(event.oldValue.value && event.oldValue.value === event.newValue.value))
) {
return;
}
// try to find identifier, even if the new value is null/undefined
let value = event.newValue || event.oldValue;
let identifier = null;
if (value) {
identifier = value.identifier ? value.identifier : value;
}
if (!value || !identifier) {
return;
}
const attributes = { [identifier]: event.newValue };
this.fireEditedRowsEvent(
event.rowID,
row.rowData,
null,
attributes,
configuration
);
}
public fireEditedRowsEvent(
rowId: string,
gridRow: any,
parent: string,
attributes,
configuration: DataListConfiguration
) {
this.setEditedRowsData(rowId, gridRow, parent, attributes, configuration);
this.editedRowsOutput.next(this.editedRows);
this.currentData.emit(this.grid.data);
}
protected setEditedRowsData(
rowId: string,
row: any,
parent: string,
attributes,
configuration: DataListConfiguration
) {
const metadata = configuration.metadataKeys
? configuration.metadataKeys.map((key) => row[key])
: [];
if (this.editedRows[rowId]) {
Object.keys(attributes).forEach((key) => {
this.editedRows[rowId].attributes[key] = attributes[key];
this.editedRows[rowId].row = row;
});
} else {
this.editedRows[rowId] = { parent, attributes, row };
//Hide metadata from the public interface since it should no longer be used (you can always directly access the row on the event object
this.editedRows[rowId]["metadata"] = metadata;
}
this.editedRowOutput.next(this.editedRows[rowId]);
}
private updateTranslations(transObj?: LangChangeEvent) {
if (!this.grid) {
return;
}
Object.keys(this.grid.resourceStrings).forEach((key) => {
let value = transObj
? transObj.translations[key]
: this.translateService.instant(key);
if (value) {
this.grid.resourceStrings[key] = value;
}
});
}
public editShownAttributes() {
this.unsavedChangesService
.leaveContext(UNSAVED_CHANGES_DIALOG_CONFIG)
.subscribe((response) => {
if (!response) {
return;
}
this.openDialogForShownAttributes();
});
}
public openDialogForShownAttributes() {
let dialogConf = {
minWidth: "900px",
maxWidth: "900px",
height: this.configuration.profileUrl ? "860px" : "755px",
};
let dialogRef = this.dialog.open(
SelectAttributesDialogComponent,
dialogConf
);
dialogRef.componentInstance.infoText = "infoText.select.attributes";
dialogRef.componentInstance.showRestrictToCategoryButton = getOrDefault(
this.configuration.showRestrictToCategoryButton,
false
);
dialogRef.componentInstance.profileUrl = this.configuration.profileUrl;
dialogRef.componentInstance.preselectAttributeProfile =
this.preselectAttributeProfile;
dialogRef.componentInstance.restrictAttributesToCategoryOnAttributeDialogOpen =
getOrDefault(
this.configuration.restrictAttributesToCategoryOnAttributeDialogOpen,
false
);
dialogRef.componentInstance.preselectedAttributes =
this.getShownAttributes();
dialogRef.componentInstance.enableSorting = true;
dialogRef.componentInstance.currentLocale =
this.currentLocaleService.currentLocale;
dialogRef.componentInstance.additionalProperties = getOrDefault(
this.configuration.selectAttributeAdditionalProperties,
["type", "group", "dataLevels"]
);
dialogRef.componentInstance.selectFilterParams =
this.configuration.selectFilterParams;
dialogRef.componentInstance.maxAttributes = getOrDefault(
this.configuration.selectAttributeMaxAttributes,
100
);
dialogRef.componentInstance.emptySelection = getOrDefault(
this.configuration.selectAttributeEmptySelection,
null
);
if (this.attributesDataType) {
dialogRef.componentInstance.dataType = this.attributesDataType;
}
if (this.listService.products) {
dialogRef.componentInstance.restrictParameters = {
cacheId: null,
products: this.listService.products,
};
} else if (
this.configuration.productNumberField &&
this.listService.dataArray &&
this.listService.dataArray.length !== 0
) {
const products = this.listService.dataArray.map(
(entry) => entry[this.configuration.productNumberField]
);
dialogRef.componentInstance.restrictParameters = {
cacheId: this.listService.cacheId,
products,
};
}
dialogRef.componentInstance.attributeUrl = throwIfUndefined(
this.attributeUrl
);
dialogRef.componentInstance.attributeUrlParams = this.attributeUrlParams;
dialogRef.afterClosed().subscribe((attributes) => {
if (attributes) {
this.storingEnabled = false;
let columns = this.grid.columns
.sort((a, b) => a.visibleIndex - b.visibleIndex)
.map((column) => Attributes.fromField(column.field));
let attributeIdentifier = attributes.map(
(attribute) => attribute.identifier
);
let sorted = columns.sort((a, b) => {
return (
attributeIdentifier.indexOf(a) - attributeIdentifier.indexOf(b)
);
});
this.columns.columnOrder.next(sorted);
this.dataListStateDirective.storeOrder(sorted);
this.updateDynamicColumns(attributes);
this.shownAttributesOutput.next(this.getShownAttributes());
this.emitDataListStatus("attributes");
this.storingEnabled = false;
}
});
}
protected getShownAttributes() {
const sortedColumns = this.grid.columns
.sort((a, b) => a.visibleIndex - b.visibleIndex)
.map((attribute) => Attributes.fromField(attribute.field));
return this.columns.shownAttributes.sort((a, b) => {
return (
sortedColumns.indexOf(a.identifier) -
sortedColumns.indexOf(b.identifier)
);
});
}
/**
* Function that gets called everytime the columns get updated from the SelectAttributesDialogComponent. Will directly call setDynamicColumns, if not overwritten
*/
public updateDynamicColumns(attributes) {
this.setDynamicColumns(attributes);
}
protected setDynamicColumns(attributes) {
this.columns.shownAttributes = deepCopy(attributes);
this.columns.updateColumns(attributes);
if (this.configuration.dynamicColumnsFromData) {
this.doReload();
}
if (this.localstorageShownAttributesEntry) {
this.localstorageShownAttributesEntry.value = JSON.stringify(attributes);
}
}
public onExport(settings) {
let exportData = !this.isEagerLoading ? this.listService.cachedData : null;
this.dataListExportService.export(
this.grid,
settings,
this.configuration.title,
this.configuration.useIgxExport,
exportData
);
}
public ngOnDestroy() {
if (!this.configuration.keepOnPageChangeIdentifier) {
this.columns.destroy();
this.listService.ngOnDestroy();
}
this.unsubscribe.destroy();
}
onCellClick(event) {
this.onCellSelect.next(event.cell);
// use navigateTo to ensure that cell is ready for past and tbody gets focused
if (!event?.cell?.editMode) {
this.grid.navigateTo(
event?.cell?.row?.index,
event?.cell?.column?.visibleIndex,
(args) => {
args?.target?.activate();
this.grid.tbody.nativeElement.focus();
}
);
}
if (this.configuration.rowSelectable !== false) {
return;
}
if (event.cell.row.isSelected) {
this.grid.deselectRows([event.cell.row.rowID]);
} else if (this.cellSelectable) {
this.grid.selectRows([event.cell.row.rowID], true);
}
this.onRowSelection({ newSelection: this.grid.selectedRows });
}
public onRowSelection(event: any) {
const params = this.buildSelectionEvent(event, this.grid, this.listService);
this.selectedItems.next(params);
}
onHeaderSelectorClick(event: any) {
const params = this.buildLazyAllSelectionEvent(
event,
this.grid,
this.listService
);
this.selectedItems.next(params);
}
protected buildLazyAllSelectionEvent(
event: any,
grid: IgxGridBaseDirective,
service: DataListService
): SelectionParams {
let result: SelectionParams = { cacheId: service.cacheId };
this.selectAllCheckbox =
this.selectAllCheckbox === null && event.checked ? false : event.checked;
if (!this.selectAllCheckbox) {
result = {
count: 0,
rows: [],
};
grid.deselectAllRows();
if (service.configuration.emitSelectedItems) {
result.rowData = [];
}
let rowData = service.cachedData.filter((data) => !data.cache);
rowData.forEach((row) => (row.selected = false));
} else {
let rowData = service.cachedData.filter((data) => !data.cache);
rowData.forEach((row) => (row.selected = true));
if (rowData) {
result = this.selectAvailableRows(result, grid, service, rowData);
}
}
return result;
}
protected buildSelectionEvent(
event: any,
grid:
| IgxGridComponent
| IgxHierarchicalGridComponent
| IgxTreeGridComponent,
service: DataListService
): SelectionParams {
let result: SelectionParams = {
count: event.newSelection ? event.newSelection.length : 1,
rows: event.newSelection,
cacheId: service.cacheId,
};
let primaryKey = this.primaryKey(service.configuration);
if (service.configuration.emitSelectedItems && service.isEagerLoading) {
let selection = new Set(event.newSelection);
result.rowData = grid.data.filter((data) =>
selection.has(data[primaryKey])
);
} else if (!service.isEagerLoading) {
let rowData = service.cachedData;
if (event.removed && event.removed.length > 0) {
let removed = new Set(event.removed);
rowData
.filter((data) => removed.has(data[primaryKey]))
.forEach((row) => (row.selected = false));
}
if (event.added && event.added.length > 0) {
let added = new Set(event.added);
rowData
.filter((data) => added.has(data[primaryKey]))
.forEach((row) => (row.selected = true));
}
if (rowData) {
result = this.selectAvailableRows(result, grid, service, rowData);
}
} else if (service.configuration.emitSelectedItems && result) {
result.rowData = result.rows.map((key) => {
return grid.getRowByKey(key).rowData;
});
}
return result;
}
selectAvailableRows(
result: SelectionParams,
grid: IgxGridBaseDirective,
service: DataListService,
rowData: any[]
) {
rowData = rowData.filter((data) => data.selected);
result = {
count: rowData.length,
rows: rowData.map((data) => data[this.primaryKey(service.configuration)]),
};
grid.selectRows(result.rows);
if (result.count == 0) {
this.selectAllCheckbox = false;
grid.deselectAllRows();
} else if (result.count != service.cachedData.length) {
this.selectAllCheckbox = null;
} else {
this.selectAllCheckbox = true;
}
if (service.configuration.emitSelectedItems) {
result.rowData = rowData;
}
return result;
}
onViewModeChange() {
this.listService.setViewmode(
this.selectedViewMode.identifier,
this.configuration.handleViewModeInBackend === true
);
this.viewModeOutput.next(this.selectedViewMode.identifier);
this.isListMode = true;
this.hideFilters = true;
if (this.selectedViewMode.identifier === "listView") {
this.hideFilters = false;
if (
this.columns.shownAttributes &&
this.columns.shownAttributes.length > 0
) {
this.columns.updateColumns(this.columns.shownAttributes);
}
} else if (this.selectedViewMode.identifier === "tileView") {
this.isListMode = false;
this.hideFilters = false;
if (
this.columns.shownAttributes &&
this.columns.shownAttributes.length > 0
) {
this.columns.updateColumns([]);
}
this.groupingExpressions = [];
}
this.viewModeLocalStorage.value = JSON.stringify(
this.selectedViewMode.identifier
);
if (this.globalFilterValue) {
this.onFilterValueChange();
}
this.currentDataChannel.next(
this.grid.dataView ? this.grid.dataView : this.grid.data
);
this.slideChange.next(3);
}
public showFilteringRow(event) {
this.showFilterRow = !this.showFilterRow;
}
public clearGlobalFilter() {
this.globalFilterValue = "";
this.grid.clearFilter();
}
public clearAllFiltersAndSorting(
clearGrouping = true,
loadData: boolean = true,
restoreGlobalFilter = false
) {
if (!restoreGlobalFilter && this.globalFilterInput) {
this.clearGlobalFilter();
}
this.restoreGlobalFilter.next(false);
this.grid.clearFilter();
this.grid.clearSort();
this.grid.clearCellSelection();
this.grid.sortingExpressions = [];
if (clearGrouping) {
this.grid.groupingExpressions = [];
this.setDefaultGroupingExpression();
}
this.setDefaultSortingExpressions();
if (loadData) {
this.listService.processData(true);
}
this.grid.cdr.detectChanges();
}
public trackColumns(index: number, column: Column) {
return (
"" +
column.type +
column.field +
column.hidden +
column.settings.columnOrder
);
}
public getDynamicPrefix() {
if (this.dataTypeModeChannel.value === "choose") {
return this.selectedDataType + "-";
} else {
return "mixed" + "-";
}
}
public getTranslationKey(column: Column) {
if (column.dynamicHeader) {
return this.getDynamicPrefix() + column.header;
}
return column.header;
}
public getColumnHeaderClasses(column: Column) {
let cssClasses = [];
if (column.sortable) {
cssClasses.push("widthSorting");
}
if (column.headerStyle) {
cssClasses.push(column.headerStyle);
}
return cssClasses;
}
public sortStrategy(column: Column): ISortingStrategy {
if (column.type === "widget" && this.isEagerLoading) {
return this.widgetSortingStrategy;
} else {
return DefaultSortingStrategy.instance();
}
}
public groupingComparer(column: Column) {
return null;
}
public onFilterValueChange() {
this.grid.filteringLogic = FilteringLogic.Or;
this.grid.filterGlobal(
this.globalFilterValue,
this.customFilter.condition("object"),
false
);
this.grid.cdr.detectChanges();
this.currentDataChannel.next(this.grid.filteredData);
}
onRangeSelection(event: GridSelectionRange) {
this.lastSelectedCells = event;
let gridData = this.grid.dataView ? this.grid.dataView : this.grid.data;
let range = [];
for (let i = event.rowStart; i < event.rowEnd + 1; i++) {
if (gridData[i].identifier) {
range.push(gridData[i].identifier);
}
}
range = range.filter((id) => !!id);
this.grid.selectRows(range, true);
this.onRowSelection({ newSelection: range });
this.grid.cdr.markForCheck();
}
public onVisibilityChanged(event) {
if (!event.column || !event.column.field) {
return;
}
let newColumns = this.columns.shownAttributes.filter((column) => {
return (
column.identifier !==
this.columns.shownAttributes.filter((column) => {
return (
event.column.field.substr(0, event.column.field.indexOf("#")) ===
column.identifier
);
})[0].identifier
);
});
if (newColumns) {
this.setDynamicColumns(newColumns);
}
}
public stopPropagation(event, field) {
event.stopImmediatePropagation();
event.preventDefault();
this.inputBoxes.forEach((input) => {
if (input.nativeElement.classList.contains(field)) {
input.nativeElement.focus();
}
});
return false;
}
columnInit(column: any) {
if (this.clipboardOptions.copyFormatters) {
column.formatter = (target) => formatCellWidgets(target, "exportValue");
}
}
public onColumnFilterInput(input: any, column: IgxColumnComponent) {
this.grid.filter(
column.field,
input,
this.customFilter.condition("object"),
column.filteringIgnoreCase
);
}
public clearColumnFilter(input: any, column: any) {
this.dataListStateDirective.columnFilterInput[column.field] = null;
this.grid.clearFilter(column.field);
}
public onRowEditEnter() {
this.rowEditEnterEmitter.next();
}
public onRowEditCancel() {
this.rowEditLeaveEmitter.next();
}
public openContextmenu(eventArgs) {
if (!this.disableContextMenu) {
if (eventArgs.cell && eventArgs.cell.column) {
const columnIdentifier = eventArgs.cell.column.field;
this.columns.columns.pipe(first()).subscribe((columns) => {
const column = columns.find(
(entry) => entry.field === columnIdentifier
);
if (column) {
this.contextMenuColumn = column;
}
});
this.contextMenuCoordinates.cell = eventArgs.cell;
}
if (this.lastSelectedCells) {
this.grid.selectRange(this.lastSelectedCells);
}
this.contextMenuCoordinates.x = eventArgs.event.clientX + "px";
this.contextMenuCoordinates.y = eventArgs.event.clientY + "px";
eventArgs.event.preventDefault();
this.menuTrigger.openMenu();
}
}
closeContextMenu() {
if (!this.disableContextMenu) {
this.menuTrigger.closeMenu();
}
}
public validateList(validation: any, configuration: DataListConfiguration) {
if (validation) {
let primaryKey = this.primaryKey(configuration);
this.listCells
.filter(
(cell) =>
cell.row[primaryKey] === validation.primaryKey &&
cell.attribute &&
cell.attribute.identifier === validation.attribute
)
.forEach((cell) => {
cell.cdr.detectChanges();
});
}
let isValid = this.validateAllRows();
this.isValidOutput.emit(isValid);
}
protected validateAllRows(): boolean {
return this.validateGrid(this.grid);
}
protected validateGrid(grid: IgxGridBaseDirective) {
if (this.editedRows == null) {
return true;
}
const rowIds = Object.keys(this.editedRows);
for (let rowId of rowIds) {
const attributes = this.editedRows[rowId]?.attributes;
if (attributes == null) {
continue;
}
const row = grid.data.find(
(record) => record[this._primaryKey] === rowId
);
if (row == null) {
continue;
}
const identifiers = Object.keys(attributes);
for (let identifier of identifiers) {
const value = row[Attributes.toSourceField(identifier)];
if (value?.errors?.length > 0) {
return false;
}
}
}
return true;
}
private checkCellForErrors(
cell: ListCellEditComponent | ListCellComponent
): boolean {
if (!cell.attribute) {
return false;
}
let errors = cell.attribute.errors;
return errors && errors.length > 0;
}
public applyDensityFromLocalStorage() {
if (this.configuration.density) {
this.density = <DisplayDensity>this.configuration.density;
this.grid.displayDensity = this.density;
return;
}
let densityStorage =
this.localStorageService.getLocalStorageEntryByConfig(
densityStorageConfig
);
if (densityStorage.exists()) {
this.density = JSON.parse(densityStorage.value);
}
this.configuration.density = this.density;
this.grid.displayDensity = this.density;
}
onCellEditEnter(event: IGridEditEventArgs) {
this.cellEditModeActive = true;
let field = event.column.field;
let oldValue = event.rowData[Attributes.toSourceField(field)];
if (!oldValue || !oldValue.identifier || oldValue["read-only"]) {
event.cancel = true;
return;
}
this.dataListEndEditService.beginEdit(this.grid);
}
onCellEditExit() {
this.cellEditModeActive = false;
}
updateDataOutput() {
this.grid.cdr.detectChanges();
this.currentDataChannel.next(
this.grid.dataView ? this.grid.dataView : this.grid.data
);
}
getHeaderClass(nmColumn) {
let classes = [];
if (this.configuration.headerClasses) {
for (let cssClass in this.configuration.headerClasses) {
let ref = this.configuration.headerClasses[cssClass];
if (
typeof ref === "string" &&
HeaderClassesCallbackRegistry.get(ref)(nmColumn)
) {
classes.push(cssClass);
}
}
}
// default header style
if (classes.length === 0) {
classes.push(
HeaderClassesCallbackRegistry.getDefaultIsMandatory()(nmColumn)
? "mandatoryCell"
: "default"
);
}
return classes.join(" ");
}
public toggleMode(event) {
this.toggleButtonChangeEmitter.emit(event.checked);
}
public tileClicked(event) {
this.tileClickedEventEmitter.emit(event);
}
public onItemDropped(event, cell: IgxGridCell, column: Column) {
if (column.allowDrop == false) {
return;
}
//Check the type of this event, if this is a data-list-row we know how to handle it, if the target column is of type attribute!
if (event.dragData.type === "data-list-row") {
if (column.type === "attribute") {
//This is an attribute
const value = extractAttributeFromCell(cell, column.field);
const draggingAttribute = extractAttributeFromRow(
event.dragData.source,
event.dragData.column.field
);
if (value && draggingAttribute) {
value.source = deepCopy(draggingAttribute.source);
const attribute = flatCopy(value);
Attributes.updateCell(cell, attribute);
}
}
}
}
public getHighlightReadOnly(): boolean {
return getOrDefault(this.configuration.highlightReadOnly, true);
}
public getCellClass(nmColumn) {
let resolved: any = {};
if (nmColumn.cellClasses) {
for (let cssClass in nmColumn.cellClasses) {
let ref = nmColumn.cellClasses[cssClass];
resolved[cssClass] = ref;
if (typeof ref === "string") {
resolved[cssClass] = CellClassesCallbackRegistry.get(ref) || false;
}
}
} else {
// default cell style
resolved.mandatoryCell =
CellClassesCallbackRegistry.getDefaultIsMandatory();
}
resolved[nmColumn.type ? nmColumn.type : "default"] = true;
return resolved;
}
getTableHeight() {
if (this.configuration.dynamicTableHeight) {
return this.calcTableHeight();
}
return "100%";
}
calcTableHeight() {
let height: string;
let modifiers = DEFAULT_MODIFIERS;
if (this.configuration.dynamicTableHeightAdditionalModifiers) {
modifiers = modifiers.concat(
this.configuration.dynamicTableHeightAdditionalModifiers
);
}
if (this.configuration.dynamicTableHeightContainer) {
const selector = this.configuration.dynamicTableHeightContainer;
let modifier = 0;
if (this.configuration.dynamicTableHeightAdditionalHeight) {
modifier = parseInt(
this.configuration.dynamicTableHeightAdditionalHeight,
10
);
}
let ro = new ResizeObserver((entries, observer) => {
for (let entry of entries) {
const cr = entry.contentRect;
this.tableHeight = `${cr.height - modifier}px`;
return height;
}
});
ro.observe(document.querySelector(selector));
return;
}
let maxHeightContent = getBodyStyleCssProperty("max-height-content");
height = maxHeightContent;
if (modifiers && modifiers.length > 0) {
height = `calc(${maxHeightContent}`;
modifiers.forEach((modifier) => {
height += ` - ${getBodyStyleCssProperty(modifier)}`;
});
if (this.configuration.dynamicTableHeightAdditionalHeight) {
height += ` - ${this.configuration.dynamicTableHeightAdditionalHeight}`;
}
if (
(this.configuration.footer && !this.configuration.footer.hidden) ||
!this.configuration.footer
) {
height += ` - ${getBodyStyleCssProperty(TABLE_FOOTER_MODIFIER)}`;
}
height += `)`;
}
return height;
}
public takeRecommendedAttributes(
recommendedAttributes: RecommendedAttributes
) {
const attributes = new Map<string, Attribute>();
[
...recommendedAttributes.attributes,
...this.columns.shownAttributes,
].forEach((attribute) => attributes.set(attribute.identifier, attribute));
const emptySelection: Attribute[] = getOrDefault(
this.configuration.selectAttributeEmptySelection,
null
);
if (emptySelection) {
emptySelection.forEach((attribute) =>
attributes.delete(attribute.identifier)
);
}
this.updateDynamicColumns(Array.from(attributes.values()));
return false;
}
public dataPasted(processedData: string[][]) {
const uri =
this.configuration.excelCopyParseUrl ||
"/api/core/attributes/parse?include=attribute.source&include=attribute.validation";
const cell = this.grid.selectedCells[0];
if (!cell) {
return;
}
let body = this.prepareExcelPasteRequestData(cell, processedData);
if (
body.needsDateTimeFormatSelection ||
body.needsSeparatorSelection ||
body.needsDateFormatSelection
) {
const dialogConfig = UtilService.getPasteDialogue(body);
let dialogRef = this.dialog.open(PageDialogComponent, dialogConfig);
dialogRef.afterClosed().subscribe((data) => {
if (data) {
body = Object.assign(body, data);
this.widgetFrameService.postData(uri, body).subscribe((response) => {
this.applyExcelPasteData(response, cell);
});
}
});
return;
}
this.widgetFrameService.postData(uri, body).subscribe((response) => {
this.applyExcelPasteData(response, cell);
});
}
public onRowDragStart(event) {
event.dragData.type = "data-list-row";
return event;
}
public onDrop(event) {
if (event.dragData.type !== "data-list-row") {
return;
}
const originalIndex = event.drag.data.index;
const dragRect = event.drag.ghostElement.getBoundingClientRect();
const currRowIndex = this.getCurrentRowIndex(this.grid.rowList.toArray(), {
x: dragRect.x,
y: dragRect.y,
});
if (!currRowIndex) {
return;
}
// remove the row that was dragged and place it onto its new location
this.listService.dataArray.splice(originalIndex, 1);
this.listService.dataArray.splice(currRowIndex, 0, event.dragData.rowData);
this.dataChannel.next(this.listService.dataArray);
this.reorderedRows.emit({
rowData: event.dragData._rowData,
currentRowIndex: currRowIndex,
dataArray: this.listService.dataArray,
});
}
private getCurrentRowIndex(rowList, cursorPosition) {
if (rowList.length === 0) {
return null;
}
const primaryKey = this.primaryKey(this.configuration);
for (const row of rowList) {
const rowRect = row.nativeElement.getBoundingClientRect();
if (cursorPosition.y > rowRect.top && cursorPosition.y < rowRect.bottom) {
// return the index of the targeted row
return this.listService.dataArray.indexOf(
this.listService.dataArray.find(
(r) => r[primaryKey] === row.rowData[primaryKey]
)
);
}
}
}
private ALWAYS_ALLOWED_TYPES = [
"LOCALIZED_STRING",
"PLAIN_STRING",
"INTEGER_NUMBER",
"DECIMAL_NUMBER",
"DATE",
];
private prepareExcelPasteRequestData(
selectedCell,
processedData: string[][]
) {
const pk = this.grid.primaryKey;
const copyEverwhere = this.configuration.excelCopyPasteEverywhere;
const cellData: any[][] = [];
const startRowIndex = selectedCell.row.index;
let needsDateFormatSelection = false;
let needsDateTimeFormatSelection = false;
let needsSeparatorSelection = false;
const cellIndex = selectedCell.column.visibleIndex;
const columns = this.grid.visibleColumns.sort(
(l, r) => l.visibleIndex - r.visibleIndex
);
let rowIteratorIndex = 0;
for (const curentDataRow of processedData) {
const rowData: any[] = [];
cellData.push(rowData);
const dataRec = this.grid.data[startRowIndex + rowIteratorIndex];
if (!dataRec) {
// no rec to update, we are at the end of the list
break;
}
for (
let cellIteratorIndex = 0;
cellIteratorIndex + cellIndex < columns.length &&
cellIteratorIndex < curentDataRow.length;
cellIteratorIndex++
) {
let currentIndex = cellIteratorIndex + cellIndex;
let colKey = Attributes.toSourceField(columns[currentIndex].field);
const data = dataRec[colKey];
if (!data) {
//console.debug(`Cant find field ${colKey} in row`, dataRec)
continue;
}
//We dont have copyeverywhere enabled and this is no attribute type that is always allowed
if (
!copyEverwhere &&
this.ALWAYS_ALLOWED_TYPES.indexOf(data.type) === -1
) {
continue;
}
//We will only write to attribute columns that are not readonly
if (data["read-only"] !== false) {
continue;
}
if (data.type === "DATE") {
needsDateFormatSelection = true;
} else if (data.type === "DATE_TIME") {
needsDateTimeFormatSelection = true;
} else if (
data.type === "MULTI_LOOKUP" ||
data.type === "COMPOSITION_AMOUNT" ||
data.type === "COMPOSITION_PERCENT"
) {
needsSeparatorSelection = true;
}
rowData[cellIteratorIndex] = data;
}
rowIteratorIndex++;
}
const body = {
data: processedData,
dtos: cellData,
needsDateFormatSelection,
needsSeparatorSelection,
needsDateTimeFormatSelection,
};
return body;
}
private applyExcelPasteData(response, selectedCell) {
const rowData = this.grid.data;
let rowIteratorIndex = 0;
const pk = this.grid.primaryKey;
const cellIndex = selectedCell.column.visibleIndex;
const columns = this.grid.visibleColumns;
const startRowIndex = selectedCell.row.index;
const params: DataListActionParameter = {
api: new DataListApiImpl(this, this.configuration),
export: null,
grid: this,
};
response._embedded[response.type].forEach((row) => {
const dataRec = rowData[startRowIndex + rowIteratorIndex];
const rowPkValue = dataRec[pk];
//We need to respect three cases here:
// 1. Everything is fine row and cells are here
// 2. Row wont be found - this happens if we update a row that is outside the viewport (below the current cell) -
// 3. Cell wont be found - this happpens if we update a cell that is outside the viewport (right of the current cells)
const igniteRow = this.grid.getRowByKey(rowPkValue);
let cellIteratorIndex = 0;
row._embedded[row.type].forEach((cell: { identifier: any }) => {
if (cell == null) {
cellIteratorIndex++;
return;
}
let currentIndex = cellIndex + cellIteratorIndex;
let colKey = Attributes.toValueField(columns[currentIndex].field);
// If we cant find the row OR the cell skip the update
if (!igniteRow || !this.grid.getCellByColumn(igniteRow.index, colKey)) {
this.validationService.validateAttribute(cell);
} else {
updateRowOrCell(
cell,
igniteRow,
colKey,
params,
this.validationService
);
cellIteratorIndex++;
}
dataRec[Attributes.toSourceField(cell.identifier)] = cell;
const eventAttributeData = {
[cell.identifier]: cell,
};
params.api.fireEditedRowsEvent(
rowPkValue,
dataRec,
null,
eventAttributeData
);
});
rowIteratorIndex++;
});
this.validateList(null, null);
}
columnOrderChanged(columnIdentifiers: string[]) {
this.columns.columnOrder.next(columnIdentifiers);
}
onDataColumnsChange(
visibleDataColumns: string[],
showAllColumns: boolean = false
) {
this.showAllColumns = showAllColumns;
this.visibleDataColumnsStorage.value = JSON.stringify(visibleDataColumns);
this.visibleDataColumns = visibleDataColumns;
this.cdr.markForCheck();
}
processDataOnChange(event, reset: boolean) {
if (event) {
this.listService.processData(reset);
this.updateDataOutput();
}
}
onFilteringDone() {
this.unsavedChangesService
.leaveContext(UNSAVED_CHANGES_DIALOG_CONFIG)
.subscribe((response) => {
if (!response) {
return;
}
this.listService.processData(true);
this.updateDataOutput();
});
}
}
export function formatCellWidgets(target: any, property: string): string {
let val = "";
if (Array.isArray(target) && target.length > 0) {
val = target
.map((option) => (option[property] ? option[property] : option))
.join(" ");
} else {
val = String(target[property] ? target[property] : target);
}
return val;
}
export class WidgetSortingStrategy implements ISortingStrategy {
public sort(
data: any[],
fieldName: string,
dir: SortingDirection,
ignoreCase: boolean
) {
const cmpFunc = (a, b) => {
return this.compareObjects(a, b, fieldName, ignoreCase, dir);
};
return data.sort(cmpFunc);
}
protected compareObjects(
obj1: any,
obj2: any,
fieldName: string,
ignoreCase: boolean,
dir: SortingDirection
) {
let a = formatCellWidgets(obj1[fieldName], "value");
let b = formatCellWidgets(obj2[fieldName], "value");
if (ignoreCase) {
a = a.toLowerCase();
b = b.toLowerCase();
}
return this.sortByParity(a, b, dir);
}
protected sortByParity(a: any, b: any, dir: SortingDirection) {
if (a > b) return dir === 1 ? +1 : -1;
if (a < b) return dir === 1 ? -1 : +1;
return 0;
}
}
export const PREFIX = "--";
export class CustomFilteringOperand extends IgxStringFilteringOperand {
private constructor() {
super();
this.operations = [customObjectFilteringOperation];
}
}
export const customObjectFilteringOperation: IFilteringOperation = {
iconName: "contains",
isUnary: false,
logic: (target: any, searchVal: string, ignoreCase?: boolean) => {
if (!target && target !== 0) {
return false;
}
let val = "";
if (Array.isArray(target) && target.length > 0) {
val = target
.map((option) => (option.value ? option.value : option))
.join(" ");
} else {
val = String(target.value ? target.value : target);
}
if (ignoreCase) {
return val.toLowerCase().indexOf(searchVal.toLowerCase()) !== -1;
} else {
return val.indexOf(searchVal) !== -1;
}
},
name: "object",
};
/**
* Public interface of the edited Rows
*/
export interface DataListEditedRows {
[key: string]: DataListEditedRow;
}
export interface DataListEditedRow {
parent: string;
//The row that got edited
row: any;
// The edited attributes
attributes: DataListEditedRowsAttributes;
// The tree grid row if we are editing a tree-grid
treeRow?: any;
}
export interface DataListEditedRowsAttributes {
[key: string]: Attribute;
}
<div class="nm-dataList__header">
<mat-form-field
*ngIf="globalFilterInput && !hideFilters"
class="nm-dataList__headerInput"
>
<input
matInput
type="text"
[placeholder]="'placeholder.free.text.search' | translate"
[(ngModel)]="globalFilterValue"
(input)="onFilterValueChange()"
[nmAutofocus]="configuration.focusFreeTextSearch || autoFocus"
/>
<button
mat-icon-button
*ngIf="globalFilterValue"
color="primary"
class="nm-dataList__headerClearButton"
matSuffix
aria-label="Clear"
(click)="clearGlobalFilter()"
>
<mat-icon>close</mat-icon>
</button>
</mat-form-field>
<button
*ngIf="configuration.removeAllFiltersButton && !hideFilters"
class="nm-dataList__headerButton"
[disabled]="
grid.filteringExpressionsTree.filteringOperands.length === 0 &&
grid.sortingExpressions.length === 0
"
mat-icon-button
[pTooltip]="'placeholder.reset.config.table' | translate"
[showDelay]="300"
color="primary"
(click)="clearAllFiltersAndSorting()"
>
<mat-icon>settings_backup_restore</mat-icon>
</button>
<ng-container
*ngIf="listService.recommendedAttributes | async as recommendedAttributes"
>
<a
*ngIf="recommendedAttributes != null && recommendedAttributes.count !== 0"
(click)="takeRecommendedAttributes(recommendedAttributes)"
>
{{
"label.take.recommended.attributes"
| translate: { count: recommendedAttributes.count }
}}
</a>
</ng-container>
<div *ngIf="configuration.headerComponents">
<nm-container
*ngFor="
let component of configuration.headerComponents.configuration
?.components
"
[configuration]="component | widgetFor: configuration"
[parent]="widgetId"
[id]="component"
></nm-container>
</div>
<div
*ngIf="!configuration.removeHeaderAdditionalSpace"
style="flex-grow: 1"
></div>
<mat-slider
type="range"
min="1"
max="5"
*ngIf="selectedViewMode && selectedViewMode.identifier !== 'listView'"
[pTooltip]="'placeholder.image.size' | translate"
[showDelay]="300"
[(ngModel)]="slidevalue"
(change)="slideChange.next(slidevalue)"
>
</mat-slider>
<mat-form-field
style="z-index: 12"
class="nm-dataList__headerSelection"
*ngIf="
dataTypeModeChannel.value === 'choose' && availableDataTypes.length > 0
"
>
<mat-label>{{ "placeholder.dataType" | translate }}</mat-label>
<nm-combo
[options]="availableDataTypes"
[(value)]="selectedDataType"
(valueChange)="onDataTypeChange()"
[clearable]="false"
[showHeader]="availableDataTypes.length > 2"
>
<ng-template nmComboOption let-option>
{{ option | translate }}
</ng-template>
<ng-template nmComboTrigger let-api let-selection="selection">
{{ selection[0] | translate }}
</ng-template>
</nm-combo>
</mat-form-field>
<mat-slide-toggle
*ngIf="configuration.enableToggleButton"
tooltipPosition="bottom"
(change)="toggleMode($event)"
>{{ toggleButtonLabel | translate }}</mat-slide-toggle
>
<button
*ngIf="isListMode && attributeUrl"
class="nm-dataList__headerButton"
mat-stroked-button
(click)="editShownAttributes()"
(keydown.enter)="$event.stopPropagation()"
>
{{ "button.attributes" | translate }}
</button>
<button
*ngIf="configuration.reloadButton"
class="nm-dataList__headerButton"
mat-icon-button
[pTooltip]="'label.refresh' | translate"
[showDelay]="300"
color="primary"
(click)="doRefresh()"
[disabled]="!(listService.data | async)"
>
<mat-icon class="nm-grey-button">refresh</mat-icon>
</button>
<mat-form-field
class="nm-dataList__headerSelection"
*ngIf="configuration.viewModeSelection"
>
<mat-label>{{ "placeholder.viewMode" | translate }}</mat-label>
<nm-combo
[options]="viewModeOptions"
displayKey="description"
[(value)]="selectedViewMode"
(valueChange)="onViewModeChange()"
[clearable]="false"
[showHeader]="viewModeOptions.length > 2"
>
<ng-template nmComboOption let-option>
<ng-container *ngIf="option.icon">
<mat-icon color="primary">{{ option.icon }}</mat-icon
>
</ng-container>
{{ option.description | translate }}
</ng-template>
<ng-template nmComboTrigger let-api let-selection="selection">
<ng-container *ngIf="selection[0] as option">
<span class="nm-dataList__viewMode--trigger">
<ng-container *ngIf="option.icon"
><mat-icon color="primary">{{ option.icon }}</mat-icon
> </ng-container
>
{{ option.description | translate }}
</span>
</ng-container>
</ng-template>
</nm-combo>
</mat-form-field>
<div
*ngIf="
configuration.visibleDataColumnsSelection &&
selectedDataType === 'attributes'
"
class="nm-dataList__headerSelection_icon"
>
<nm-combo
matTooltip="{{ 'label.hidden.columns' | translate }}"
[options]="columns.dataColumnsConfigurableVisibility | async"
[valueKey]="'field'"
[displayKey]="'header' | translate"
[filterPlaceholder]="'placeholder.search' | translate"
[multiple]="true"
[value]="visibleDataColumns"
[clearable]="false"
[iconMode]="true"
(valueChange)="onDataColumnsChange($event)"
>
<ng-template nmComboOption let-option>
{{ option.header | translate }}
</ng-template>
<ng-template nmComboTrigger let-option>
<mat-icon
color="primary"
matBadge="{{
(columns.dataColumnsConfigurableVisibility | async).length -
visibleDataColumns.length
}}"
>view_column
</mat-icon>
</ng-template>
</nm-combo>
</div>
</div>
<ng-container
#tileViewTemplate
*ngIf="selectedViewMode && selectedViewMode.identifier !== 'listView'"
>
<nm-data-list-tile-view
[listService]="listService"
[data]="currentDataChannel"
[slideChange]="slideChange"
[columns]="columns.columns"
[grid]="grid"
[frameHeight]="frameHeight"
[tileRedirectLink]="tileRedirectLink"
[overrideTileClickEvent]="overrideTileClickEvent"
(click)="tileClicked($event)"
[identifierField]="tileIdentifierField"
>
</nm-data-list-tile-view>
</ng-container>
<div
class="nm-dataList__content igx-data-content {{ filterMode }}"
[ngStyle]="{ height: tableHeight }"
[ngClass]="{
'u-hidden': selectedViewMode && selectedViewMode.identifier !== 'listView'
}"
[class.removeColumnHeader]="removeColumnHeader"
>
<igx-grid
nm-paste-handler
[pasteGrid]="table"
(onDataProcessed)="dataPasted($event)"
[data]="listService.data | async"
[height]="tableGridHeight"
[width]="tableGridWidth"
[hideRowSelectors]="!rowSelectable"
[rowSelection]="rowSelectionMode"
(cellClick)="onCellClick($event)"
[columnHiding]="true"
[displayDensity]="density"
[primaryKey]="_primaryKey"
[autoGenerate]="false"
(dataPreLoad)="listService.processData(false)"
[allowFiltering]="true"
[rowEditable]="configuration.rowEditable"
(rowEdit)="onRowEdit($event)"
(rowEditEnter)="onRowEditEnter()"
(rowEditExit)="onRowEditCancel()"
(cellEdit)="onCellEdit($event)"
(cellEditEnter)="onCellEditEnter($event)"
(cellEditExit)="onCellEditExit()"
(sortingDone)="processDataOnChange($event, true)"
(filteringDone)="onFilteringDone()"
(rowSelected)="onRowSelection($event)"
(rangeSelected)="onRangeSelection($event)"
[filterMode]="filterMode"
[class.showFilterRow]="showFilterRow"
[class.isTileView]="!isListMode"
[groupingExpressions]="groupingExpressions"
[sortingExpressions]="sortingExpressions"
(columnVisibilityChanged)="onVisibilityChanged($event)"
(contextMenu)="openContextmenu($event)"
[tableIdentifier]="
(contextIdentifierChannel | async)
? (contextIdentifierChannel | async)
: (configuration.identifier
? configuration.identifier
: configuration.title) +
(selectedDataType ? '-' + selectedDataType : '')
"
[clipboardOptions]="clipboardOptions"
[pinning]="pinningConfig"
[rowDraggable]="configuration.enableRowDragging"
(rowDragStart)="onRowDragStart($event)"
(dropped)="onDrop($event)"
(columnOrderChanged)="columnOrderChanged($event)"
(storingEnabled)="(storingEnabled)"
(columnInit)="columnInit($event)"
[locale]="listService.selectedLocale || currentLocaleService.currentLocale"
igxDrop
[dataList]="this"
(filteringExpressionsTreeChange)="!isEagerLoading ? grid.navigateTo(0) : ''"
statefulDataList
#table
>
<ng-template igxDragIndicatorIcon>
<igx-icon>drag_handle</igx-icon>
</ng-template>
<ng-template igxHeadSelector let-headContext *ngIf="!isEagerLoading">
<div
class="igx-grid__cbx-padding"
style="height: 100%"
(click)="$event.stopPropagation()"
>
<igx-checkbox
[checked]="selectAllCheckbox"
[indeterminate]="selectAllCheckbox === null"
(change)="onHeaderSelectorClick($event)"
>
</igx-checkbox>
</div>
</ng-template>
<igx-column
*ngFor="
let nmColumn of (showActionsInTableColumn
? columns.columns
: columns.dataColumns
)
| async
| nmDataListColumnSettings
: this
: (columns.columnOrder | async)
: visibleDataColumns
: showAllColumns;
trackBy: trackColumns
"
[field]="nmColumn.field"
[sortable]="nmColumn.sortable"
[filterable]="nmColumn.filter"
[header]="
(nmColumn.dynamicHeader
? listService.dataType + '-' + nmColumn.header
: nmColumn.header
) | translate
"
[width]="nmColumn.width ? nmColumn.width : '200px'"
[minWidth]="nmColumn.minWidth ? nmColumn.minWidth : '0px'"
[maxWidth]="nmColumn.maxWidth ? nmColumn.maxWidth : '10000px'"
[pinned]="isListMode ? nmColumn.pinned : false"
[hidden]="nmColumn.hidden"
[editable]="true === nmColumn.editable"
[groupable]="nmColumn.groupable"
[disableHiding]="nmColumn.disableHiding ? nmColumn.disableHiding : true"
[movable]="isListMode ? true : false"
[resizable]="isListMode ? true : false"
[sortStrategy]="nmColumn.settings.sortStrategy"
[groupingComparer]="nmColumn.settings.groupingComparer"
[cellClasses]="nmColumn.settings.cellClasses"
[headerClasses]="nmColumn.settings.headerClasses"
[dataType]="nmColumn.dataType"
[additionalTemplateContext]="nmColumn"
[headerTemplate]="
filterMode === 'inlineFilter' || nmColumn.tooltip
? columnHeaderTemplate
: null
"
[cellEditorTemplate]="columnEditorTemplate"
[cellTemplate]="columnCellTemplate"
>
</igx-column>
<ng-container *ngIf="!showActionsInTableColumn">
<igx-action-strip
*ngIf="!rowPinningEnabled; else rowPinningEnabledTemplate"
#actionStrip
>
<ng-container
*ngTemplateOutlet="
!this.cellEditModeActive ? actionStripTemplate : undefined;
context: { actionStrip: actionStrip }
"
>
</ng-container>
</igx-action-strip>
<ng-template #rowPinningEnabledTemplate>
<igx-action-strip *ngIf="rowPinningEnabled" #actionStrip>
<ng-container
*ngTemplateOutlet="
actionStripTemplate;
context: { actionStrip: actionStrip }
"
>
</ng-container>
<igx-grid-pinning-actions></igx-grid-pinning-actions>
</igx-action-strip>
</ng-template>
</ng-container>
</igx-grid>
</div>
<div
*ngIf="childComponentMenu.menuObs | async as menu"
style="position: fixed"
#menuTrigger="matMenuTrigger"
[style.left]="contextMenuCoordinates.x"
[style.top]="contextMenuCoordinates.y"
[matMenuTriggerFor]="menu"
></div>
<nm-grid-contextmenu
[cell]="contextMenuCoordinates.cell"
[grid]="this"
[column]="contextMenuColumn"
[selected-items]="selectedItems"
[total]="listService.totalSubject"
[link]="listService.linkWithoutPaging"
[configuration]="configuration"
[api]="apiEmitter | async"
(closeContextMenu)="closeContextMenu()"
(export)="onExport($event)"
>
</nm-grid-contextmenu>
<ng-template #groupRowTemplate igxGroupByRow let-groupRow>
<nm-data-list-group-component
[grid]="grid"
[record]="groupRow"
(groupSelectionChange)="onRowSelection($event)"
></nm-data-list-group-component>
</ng-template>
<ng-template #actionStripTemplate let-actionStrip="actionStrip">
<nm-list-cell-action-strip
[actionColumns]="columns.actionColumns | async"
[rowContext]="actionStrip.context"
[dataType]="listService.dataType"
>
</nm-list-cell-action-strip>
</ng-template>
<div igxOverlayOutlet></div>
<ng-template #columnHeaderTemplate let-column>
<ng-container *ngIf="filterMode === 'inlineFilter'; else showTooltip">
<div
class="title-inner"
[attr.draggable]="false"
[ngClass]="column.additionalTemplateContext.settings.columnHeaderClasses"
>
<span
*ngIf="!column.additionalTemplateContext.filter"
class="nm-title-container"
>
{{
(column.additionalTemplateContext.dynamicHeader
? listService.dataType +
"-" +
column.additionalTemplateContext.header
: column.additionalTemplateContext.header
) | translate
}}
</span>
<mat-form-field
*ngIf="column.additionalTemplateContext.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)"
(keydown)="$event.stopImmediatePropagation()"
[placeholder]="
(column.additionalTemplateContext.dynamicHeader
? listService.dataType +
'-' +
column.additionalTemplateContext.header
: column.additionalTemplateContext.header
) | translate
"
[(ngModel)]="dataListStateDirective.columnFilterInput[column.field]"
(input)="
onColumnFilterInput(
dataListStateDirective.columnFilterInput[column.field],
column
)
"
/>
<button
(click)="$event.stopPropagation()"
[attr.draggable]="false"
mat-button
*ngIf="dataListStateDirective.columnFilterInput[column.field]"
matSuffix
mat-icon-button
aria-label="Clear"
(click)="
clearColumnFilter(
dataListStateDirective.columnFilterInput[column.field],
column
)
"
>
<mat-icon [attr.draggable]="false">close</mat-icon>
</button>
</mat-form-field>
<mat-icon
*ngIf="!column.additionalTemplateContext.hidePin"
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-container>
<ng-template #showTooltip>
<span
pTooltip="{{ column.additionalTemplateContext.tooltip | translate }}"
>{{ column.header }}</span
>
</ng-template>
</ng-template>
<ng-template #columnEditorTemplate let-val let-cell="cell">
<nm-list-cell-edit
[column]="cell.column?.additionalTemplateContext"
[dataType]="listService.dataType"
[cell]="cell"
[primaryKey]="_primaryKey"
[density]="density"
[validation]="{ grid: this, config: configuration }"
(editableCell)="editableCell.emit($event)"
[attr.data-rowindex]="cell.row.index"
>
</nm-list-cell-edit>
</ng-template>
<ng-template #columnCellTemplate let-val let-cell="cell">
<nm-list-cell
*ngIf="
cell?.column &&
!cell.row.rowData.cache &&
!cell.column?.additionalTemplateContext.draggable
"
[source]="
cell.row.rowData[cell.column?.additionalTemplateContext.settings.source]
"
[column]="cell.column?.additionalTemplateContext"
[row]="cell.row.rowData"
[value]="cell.value"
[highlightReadOnly]="
cell.column?.additionalTemplateContext.settings.highlightReadOnly
"
[cell]="cell"
[density]="density"
[ignoreSeconds]="configuration.ignoreSeconds"
[chipColors]="configuration.chipColors"
[columnSelector]="columnSelector"
[attr.data-rowindex]="cell.row.index"
[dataType]="listService.dataType"
igxDrop
(dropped)="
onItemDropped($event, cell, cell.column?.additionalTemplateContext)
"
>
</nm-list-cell>
<nm-list-cell
*ngIf="
cell?.column &&
!cell.row.rowData.cache &&
cell.column?.additionalTemplateContext.draggable
"
[source]="
cell.row.rowData[cell.column?.additionalTemplateContext.settings.source]
"
[column]="cell.column?.additionalTemplateContext"
[value]="cell.value"
[dataType]="listService.dataType"
[row]="cell.row.rowData"
[highlightReadOnly]="
cell.column?.additionalTemplateContext.settings.highlightReadOnly
"
[cell]="cell"
[density]="density"
[ignoreSeconds]="configuration.ignoreSeconds"
[chipColors]="configuration.chipColors"
[columnSelector]="columnSelector"
[igxDrag]="{
type: 'data-list-row',
source: cell.row.rowData,
column: cell.column?.additionalTemplateContext
}"
[attr.data-rowindex]="cell.row.index"
igxDrop
(dropped)="
onItemDropped($event, cell, cell.column?.additionalTemplateContext)
"
igxDragHandle
>
</nm-list-cell>
<nm-content-preview
*ngIf="cell.row.rowData.cache"
[min-width]="cell.column?.additionalTemplateContext.minWidth"
[max-width]="
cell.column?.additionalTemplateContext.width ||
cell.column?.additionalTemplateContext.maxWidth
"
>
</nm-content-preview>
</ng-template>