@rangertechnologies/ngnxt
Version:
This library was used for creating dymanic UI based on the input JSON/data
373 lines (372 loc) • 18.8 kB
TypeScript
import { EventEmitter, ElementRef, Renderer2, SimpleChanges, ChangeDetectorRef } from '@angular/core';
import { MatSort } from '@angular/material/sort';
import { TranslationService } from '../../services/translation/translation.service';
import { DataService } from '../../services/data/data.service';
import { ChangeService } from '../../services/change/change.service';
import { StorageService } from '../../services/storage/storage.service';
import { CountryService } from '../../services/country/country.service';
import * as i0 from "@angular/core";
/** Configuration for a single advanced-filter control. */
export interface AdvancedFilterConfig {
/** Data field path (supports dot-notation, e.g. 'employee.name'). */
field: string;
/** Human-readable label shown above the control. */
label: string;
/** Control type determines which reusable control is rendered. */
type: 'text' | 'date' | 'dropdown' | 'list';
/** Options list for 'dropdown' and 'searchDropdown' types.
* Each option should have the shape: { id, name, value, label, ... }
* Use `labelField` to pick the display property and `valueField` for the match value. */
options?: any[];
/** Placeholder text shown inside the control. */
placeholder?: string;
/** Property on an option object used as display label (default: 'label'). */
labelField?: string;
/** Property on an option object used as the filter/match value (default: 'value').
* For searchDropdown, the emitted object `{ id, name, value }` is read with this key. */
valueField?: string;
/** CSS width for the control, e.g. '180px'. Defaults to 160px for text, 190px for dropdowns. */
width?: string;
/** Evaluation priority. Lower number runs first. Default: index order. */
priority?: number;
/** Pre-populate this filter with a default value on init. */
defaultValue?: any;
/** If true, the control is rendered in read-only/disabled state. */
disabled?: boolean;
/** If true, the filter item is not rendered in the bar. */
hidden?: boolean;
}
/** SKS1JUL26 Represents a date-range filter value for type:'date' fields. */
export interface AdvancedDateRange {
startDate: string;
endDate: string;
}
/** SKS1JUL26 Map of field -> current filter value (scalar or date-range). */
export type AdvancedFilterValues = Record<string, string | AdvancedDateRange | null>;
export declare class NxtDatatable {
private countryService;
private storageService;
private cdRef;
private translationService;
private renderer;
private dataService;
private changeService;
data: any[];
summaryValues: {
[label: string]: any;
};
tableFilterData: any[];
columns: Array<any>;
withCheckBox: boolean;
searchBar: boolean;
tableSaveButton: boolean;
hideSaveButton: boolean;
stickyColumn: boolean;
tableWidth: string;
actionColumHeader: string;
actionButton: boolean;
title: any;
isButtons: boolean;
buttonArray: any;
tableId: any;
isEditRow: boolean;
isDeleteRow: boolean;
addInlineRecord: boolean;
searchConfigs: any;
direction: 'rtl' | 'ltr';
pagination: boolean;
actionButtonArray: any;
multipleFilter: any;
isPagination: any;
isListViews: any;
id: any;
isNosIndicator: any;
isEditable: any;
from: any;
question: any;
rowTextSize: any;
rowTextColor: any;
apiMeta: any;
summaryRows: any;
summaryColumns: any;
isLoading: any;
tableConfig: any;
tableParams: any;
listViews: any[];
mode: 'view' | 'edit' | 'print';
languageCode: string;
selectedColumn: string | null;
allIcons: any[];
isButtonLoading: boolean;
isPreview: boolean;
groupFilter: boolean;
groupFilterConfig: any;
groupFilterColumn: any;
onlyView: boolean;
tableHeight: any;
serialNumberColumn: boolean;
/** SKS1JUL26 SKS1JUL26: Configuration array for the advanced filter bar. Each entry produces one filter control. */
advancedFilters: AdvancedFilterConfig[];
tableRowClick: EventEmitter<any>;
onEditData: EventEmitter<any>;
onSaveData: EventEmitter<any>;
saveButtonData: EventEmitter<any>;
onDeleteData: EventEmitter<any>;
buttonEmit: EventEmitter<any>;
hyperLinkEmit: EventEmitter<any>;
sideNavEmit: EventEmitter<{
data: any;
col: any;
config: any;
}>;
actionButtonEmit: EventEmitter<any>;
columnSelected: EventEmitter<{
uniqueIdentifier: string;
data: any[];
}>;
removeColumn: EventEmitter<{
uniqueIdentifier: string;
data: any[];
}>;
valueChange: EventEmitter<any>;
selectedValues: EventEmitter<any[]>;
fileEmit: EventEmitter<any>;
NxtTableFilterEmit: EventEmitter<any>;
hadleDropDownDependent: EventEmitter<any>;
NxtTableParamsEmit: EventEmitter<any>;
sort: MatSort;
tableContainer: ElementRef<HTMLElement>;
selection: any;
stickyCondition: number;
searchFilter: boolean;
filterArray: Array<any>;
selectedFilter: any;
pageSizeOptions: Array<any>;
dataSource: any;
totalCount: number;
searchBoxValue: any;
prevSearch: any;
activeColumn: string | null;
isScrolled: boolean;
isShadowHidden: boolean;
currentSortColumn: string;
currentSortDirection: 'asc' | 'desc' | 'none';
originalData: any;
hoveredColumn: string | null;
searchText: any;
multipleFilterArray: any;
tableFilterArray: any;
filterDataArray: any;
isResized: boolean;
sFilterData: any;
currentColumns: Array<any>;
inlineElement: any;
pageSize: any;
pageIndex: any;
totalRecords: number;
deleteData: any;
deleteModal: boolean;
dropdownActionButton: any;
currentOpenIndex: number | null;
clickListener: any;
deleteIndex: number;
showPopover: boolean;
isSummaryColumn: boolean;
isSummaryStartColumn: any[];
isSummaryEndColumn: any[];
filterBoxData: any;
filterTableNos: any;
selectedView: any;
isDropdownOpen: boolean;
currentViewFilter: any;
isFullTableSummaryRow: boolean;
isImageHover: boolean;
isImageEdit: boolean;
selectedImageElement: any;
private questionsCache;
isResizing: boolean;
private currentColumn;
private startX;
private startWidth;
private resizeFrameId;
columnWidthTrack: any;
currentTableData: any;
oldTableData: any;
viewEdit: boolean;
currencyOption: any;
columnSourceId: any;
summaryRowsOrginal: any;
displaySummaryRows: any;
Array: ArrayConstructor;
tableEditTrack: boolean;
alignRight: boolean;
selectedIsEmpty: boolean;
private destroy$;
private timers;
/** Current values for every advanced filter control. */
advancedFilterValues: AdvancedFilterValues;
/**
* SKS1JUL26: Emits a JSON-serialised snapshot of advancedFilterValues
* so that debounceTime(300) + distinctUntilChanged() both work correctly.
* Subject<void> makes distinctUntilChanged useless because every emission
* looks the same. Subject<string> compares serialised state.
*/
private advancedFilter$;
constructor(countryService: CountryService, storageService: StorageService, cdRef: ChangeDetectorRef, translationService: TranslationService, renderer: Renderer2, dataService: DataService, changeService: ChangeService);
ngOnChanges(changes: SimpleChanges): void;
ngOnInit(): void;
ngAfterViewInit(): void;
autoDistributeExtraTableWidth(from?: any): void;
onResizeStart(event: MouseEvent): void;
private onResizeMove;
private applyWidthToColumn;
private onResizeEnd;
ngOnDestroy(): void;
computeSummaryColumns(): void;
computeSummaryValues(from?: any): void;
sortData(column: string, sortingState?: any | undefined, currentState?: any | undefined, from?: any): void;
onScroll(tableContainer: HTMLElement): void;
onDocumentClick(event: any): void;
filter(datas: any, event: MouseEvent): void;
pageParams(event: any, from?: any): void;
/** SKS29OCT25 Formats a cell value exactly the way it appears in the UI */
private formatDateForSearch;
applyFilter(event: any, from?: any): void;
/** SKS15FEB25 Whether the number of selected elements matches the total number of rows. */
isAllSelected(): boolean;
/** SKS15FEB25 Selects all rows if they are not all selected; otherwise clear selection. */
masterToggle(): void;
isSomeSelected(): boolean;
separateRowSelect(data: any, element: any): void;
tableClick(data: any): void;
getNestedValue(obj: any, path: string): any;
filterRetain(filterkeyMap: any, from?: any): void;
removeDuplicates(objects: any): any[];
deleteRecord(data: any, index: number): void;
deleteRecordData(): void;
saveButton(element: any): void;
private isSameRow;
private normalizeRow;
onEdit(data: any): void;
onSave(data: any): void;
commonButtonClick(button: any): void;
getObjValue(element: any, column: string): any;
onClickHyperlink(column: any, element: any, isHyperLink: any): void;
addTableRecord(element: any, from?: any): void;
prepareActionVisibility(rows: any[]): any[];
evaluateConditionString(row: any, condition: string): boolean;
onSearch(event: any, from?: any): void;
emptySearch(event: any): void;
onSideNavInfoClick(data: any, col: any): void;
onColumnClick(uniqueIdentifier: string): void;
closefilter(from?: any): void;
isSelected(event: any): boolean;
checkedData(event: any, from?: any): void;
private addClickOutsideListener;
private removeClickListener;
toggleDropdown(index: number): void;
actionButtonClicked(event: any, data: any): void;
removeCol(uniqueIdentifier: string): void;
emitTableDataValue(updatedTableData: any): void;
updateEdit(index: number, value: any, element: any, column: any, type?: any): void;
updateValue(element: any, column: string, value: any): any;
expenseAttachment(event: any): void;
listViewEmit(event: any): void;
onImageEdit(ques: any): Promise<void>;
onImageDelete(ques: any): Promise<void>;
fileChangeEvent(ques: any, event: any): Promise<void>;
private readFileAsDataURL;
getDropDown(event: any): void;
trackByRow(index: number, row: any): any;
trackByColumn(index: number, column: any): any;
trackBySummary(index: number, summary: any): any;
trackByIndex(index: number): number;
editModeChange(): void;
saveTable(): void;
discardChanges(): void;
groupFilterEmit(event: any, from?: any): void;
groupFilterRetain(filterkey: any, from?: any): void;
changeAnnounce(event: any): void;
/**
* THE SINGLE UNIFIED FILTER PIPELINE (client-side mode).
*
* Pipeline order matches the documented priority:
* originalData
* 1. List View → sFilterData (managed by listViewEmit / ngOnChanges)
* 2. Advanced Filter → applyAdvancedFilters(sFilterData)
* 3. Global Search → searchBoxValue contains match
* 4. Column Filter → filterDataArray exact match
* 5. Sort → currentSortColumn / currentSortDirection
* 6. Pagination → pageIndex / pageSize → dataSource.data
*
* For server-side (pagination=true), we skip client filtering and just emit
* the full params object (including advancedFilterData) to the parent.
*
* All event handlers (onAdvancedFilterChange, applyFilter, filterRetain,
* checkedData, closefilter, pageParams) ultimately call this method so
* there is exactly ONE place where filtering logic lives.
*/
refreshTableData(from?: string): void;
/**
* Builds the `advancedFilterValues` map from the current `advancedFilters` config.
* Existing values are preserved if their field still exists in the new config.
* Respects `defaultValue` from the config for initial population.
*/
initializeAdvancedFilters(): void;
/**
* Called from the template whenever any advanced filter control changes.
*
* @param field - The data field this filter maps to
* @param value - New value:
* - text/dropdown: plain string
* - searchDropdown: scalar extracted via config.valueField from
* the emitted object shape `{ id, name, value, label, ... }`
* - date: ISO 8601 string from app-nxt-datepicker
* @param subKey - For date filters only: 'startDate' | 'endDate'
*/
onAdvancedFilterChange(field: string, value: any, subKey?: 'startDate' | 'endDate'): void;
/**
* Applies current advancedFilterValues against a data array.
* Returns a new filtered array — never mutates the input.
*
* Reuses existing helpers:
* - getObjValue() for field access
* - formatDateForSearch() for display-safe date formatting (NxtDatePipe)
*
* Date comparison uses formatDateForSearch() on both cell and filter values
* so timezone handling is consistent with the rest of the table.
*
* Filter logic per type:
* text → case-insensitive contains
* dropdown → strict string equality
* searchDropdown → strict string equality on extracted valueField
* date → >= startDate and/or <= endDate (normalised via NxtDatePipe)
*/
applyAdvancedFilters(baseData: any[]): any[];
/**
* Resets all advanced filter values and re-runs the unified pipeline.
* pageIndex is reset to 1 so users don't get confused on high page numbers.
*/
clearAdvancedFilters(): void;
/**
* Returns true if at least one visible advanced filter field has a non-empty value.
* Used in the template to decide whether to show the clear-all button.
*/
hasAdvancedFilter(): boolean;
/**
* Returns a clean snapshot of the ACTIVE advanced filter values.
* Included in NxtTableParamsEmit so server-side implementations receive
* the filter state under the `advancedFilterData` key:
*
* tableParams = {
* pagination: { pageSize, pageIndex },
* tableSearch: { fields, value },
* searchFilterData: { [column]: [values] },
* advancedFilterData: { [field]: string | AdvancedDateRange }, ← NEW
* sort: { column, direction, listView },
* }
*/
buildAdvancedFilterObject(): AdvancedFilterValues;
static ɵfac: i0.ɵɵFactoryDeclaration<NxtDatatable, never>;
static ɵcmp: i0.ɵɵComponentDeclaration<NxtDatatable, "nxt-datatable", never, { "data": { "alias": "data"; "required": false; }; "summaryValues": { "alias": "summaryValues"; "required": false; }; "tableFilterData": { "alias": "tableFilterData"; "required": false; }; "columns": { "alias": "columns"; "required": false; }; "withCheckBox": { "alias": "withCheckBox"; "required": false; }; "searchBar": { "alias": "searchBar"; "required": false; }; "tableSaveButton": { "alias": "tableSaveButton"; "required": false; }; "hideSaveButton": { "alias": "hideSaveButton"; "required": false; }; "stickyColumn": { "alias": "stickyColumn"; "required": false; }; "tableWidth": { "alias": "tableWidth"; "required": false; }; "actionColumHeader": { "alias": "actionColumHeader"; "required": false; }; "actionButton": { "alias": "actionButton"; "required": false; }; "title": { "alias": "title"; "required": false; }; "isButtons": { "alias": "isButtons"; "required": false; }; "buttonArray": { "alias": "buttonArray"; "required": false; }; "tableId": { "alias": "tableId"; "required": false; }; "isEditRow": { "alias": "isEditRow"; "required": false; }; "isDeleteRow": { "alias": "isDeleteRow"; "required": false; }; "addInlineRecord": { "alias": "addInlineRecord"; "required": false; }; "searchConfigs": { "alias": "searchConfigs"; "required": false; }; "direction": { "alias": "direction"; "required": false; }; "pagination": { "alias": "pagination"; "required": false; }; "actionButtonArray": { "alias": "actionButtonArray"; "required": false; }; "multipleFilter": { "alias": "multipleFilter"; "required": false; }; "isPagination": { "alias": "isPagination"; "required": false; }; "isListViews": { "alias": "isListViews"; "required": false; }; "id": { "alias": "id"; "required": false; }; "isNosIndicator": { "alias": "isNosIndicator"; "required": false; }; "isEditable": { "alias": "isEditable"; "required": false; }; "from": { "alias": "from"; "required": false; }; "question": { "alias": "question"; "required": false; }; "rowTextSize": { "alias": "rowTextSize"; "required": false; }; "rowTextColor": { "alias": "rowTextColor"; "required": false; }; "apiMeta": { "alias": "apiMeta"; "required": false; }; "summaryRows": { "alias": "summaryRows"; "required": false; }; "summaryColumns": { "alias": "summaryColumns"; "required": false; }; "isLoading": { "alias": "isLoading"; "required": false; }; "tableConfig": { "alias": "tableConfig"; "required": false; }; "tableParams": { "alias": "tableParams"; "required": false; }; "listViews": { "alias": "listViews"; "required": false; }; "mode": { "alias": "mode"; "required": false; }; "languageCode": { "alias": "languageCode"; "required": false; }; "selectedColumn": { "alias": "selectedColumn"; "required": false; }; "allIcons": { "alias": "allIcons"; "required": false; }; "isButtonLoading": { "alias": "isButtonLoading"; "required": false; }; "isPreview": { "alias": "isPreview"; "required": false; }; "groupFilter": { "alias": "groupFilter"; "required": false; }; "groupFilterConfig": { "alias": "groupFilterConfig"; "required": false; }; "groupFilterColumn": { "alias": "groupFilterColumn"; "required": false; }; "onlyView": { "alias": "onlyView"; "required": false; }; "tableHeight": { "alias": "tableHeight"; "required": false; }; "serialNumberColumn": { "alias": "serialNumberColumn"; "required": false; }; "advancedFilters": { "alias": "advancedFilters"; "required": false; }; }, { "tableRowClick": "tableRowClick"; "onEditData": "onEditData"; "onSaveData": "onSaveData"; "saveButtonData": "saveButtonData"; "onDeleteData": "onDeleteData"; "buttonEmit": "buttonEmit"; "hyperLinkEmit": "hyperLinkEmit"; "sideNavEmit": "sideNavEmit"; "actionButtonEmit": "actionButtonEmit"; "columnSelected": "columnSelected"; "removeColumn": "removeColumn"; "valueChange": "valueChange"; "selectedValues": "selectedValues"; "fileEmit": "fileEmit"; "NxtTableFilterEmit": "NxtTableFilterEmit"; "hadleDropDownDependent": "hadleDropDownDependent"; "NxtTableParamsEmit": "NxtTableParamsEmit"; }, never, never, true, never>;
}