ngx-primeng-toolkit
Version:
A comprehensive TypeScript utility library for Angular component state management, PrimeNG table state management, ng-select helpers, data storage, and memoized HTTP caching. Compatible with Angular 19+ and PrimeNG 19+ (optimized for Angular 20+ and Prime
1,436 lines (1,426 loc) • 63.5 kB
text/typescript
import { HttpClient, HttpContextToken, HttpContext } from '@angular/common/http';
import * as _angular_core from '@angular/core';
import { Signal, DestroyRef, Injector, Provider } from '@angular/core';
import { TableLazyLoadEvent, Table } from 'primeng/table';
import { z } from 'zod';
import { SelectItem } from 'primeng/api';
import { Subject, Observable } from 'rxjs';
/**
* Makes all properties of T nullable (T | null) recursively, handling functions, arrays, and objects
* @template Thing - The type to make nullable
* @example
* ```typescript
* type User = { id: number; name: string; email: string; tags: string[] };
* type NullableUser = RecursiveNullable<User>;
* // Result: {
* // id: number | null;
* // name: string | null;
* // email: string | null;
* // tags: (string | null)[] | null;
* // }
* ```
*/
type RecursiveNullable<Thing> = Thing extends Function ? Thing : Thing extends Array<infer InferredArrayMember> ? RecursiveNullableArray<InferredArrayMember> : Thing extends Record<string, any> ? RecursiveNullableObject<Thing> : Exclude<Thing, undefined> | null;
type RecursiveNullableObject<Thing extends object> = {
[Key in keyof Thing]: RecursiveNullable<Thing[Key]>;
};
interface RecursiveNullableArray<Thing> extends Array<RecursiveNullable<Thing>> {
}
/**
* Makes all properties of T nullish (T | null | undefined)
* @template T - The base type
* @example
* ```typescript
* type User = { id: number; name: string };
* type NullishUser = Nullish<User>;
* // Result: { id: number | null | undefined; name: string | null | undefined }
* ```
*/
type Nullish<T> = {
[P in keyof T]: Exclude<T[P], null | undefined> | null | undefined;
};
/**
* Makes all properties of T nullish (T | null | undefined) recursively, handling functions, arrays, and objects
* @template Thing - The type to make nullish
* @example
* ```typescript
* type User = { id: number; profile: { name: string; age: number }; tags: string[] };
* type NullishUser = RecursiveNullish<User>;
* // Result: {
* // id: number | null | undefined;
* // profile: {
* // name: string | null | undefined;
* // age: number | null | undefined
* // } | null | undefined;
* // tags: (string | null | undefined)[] | null | undefined;
* // }
* ```
*/
type RecursiveNullish<Thing> = Thing extends Function ? Thing : Thing extends Array<infer InferredArrayMember> ? RecursiveNullishArray<InferredArrayMember> : Thing extends Record<string, any> ? RecursiveNullishObject<Thing> : Exclude<Thing, null | undefined> | null | undefined;
type RecursiveNullishObject<Thing extends object> = {
[Key in keyof Thing]: RecursiveNullish<Thing[Key]>;
};
interface RecursiveNullishArray<Thing> extends Array<RecursiveNullish<Thing>> {
}
/**
* Makes all properties optional recursively, useful for partial updates, handling functions, arrays, and objects
* @template Thing - The type to make recursively partial
* @example
* ```typescript
* type User = {
* id: number;
* profile: { name: string; age: number };
* settings: { theme: string; notifications: boolean };
* tags: string[];
* };
* type PartialUser = RecursivePartial<User>;
* // Result: {
* // id?: number | undefined;
* // profile?: { name?: string | undefined; age?: number | undefined } | undefined;
* // settings?: { theme?: string | undefined; notifications?: boolean | undefined } | undefined;
* // tags?: (string | undefined)[] | undefined;
* // }
* ```
*/
type RecursivePartial<Thing> = Thing extends Function ? Thing : Thing extends Array<infer InferredArrayMember> ? RecursivePartialArray<InferredArrayMember> : Thing extends object ? RecursivePartialObject<Thing> : Thing | undefined;
type RecursivePartialObject<Thing> = {
[Key in keyof Thing]?: RecursivePartial<Thing[Key]>;
};
interface RecursivePartialArray<Thing> extends Array<RecursivePartial<Thing>> {
}
/**
* Enumeration for manipulation types in component operations
* Used for tracking the current operation state in component management
*
* @example
* ```typescript
* // In a component
* currentOperation: ManipulationType = ManipulationType.Create;
*
* // Check operation type
* if (this.currentOperation === ManipulationType.Update) {
* // Handle update logic
* }
* ```
*/
declare enum ManipulationType {
/** Creating a new item */
Create = "create",
/** Updating an existing item */
Update = "update",
/** Creating a child item */
CreateChild = "create-child",
/** Deleting an item */
Delete = "delete",
/** Viewing item details */
View = "view",
/** Saving an item */
Save = "save"
}
/**
* Key-value pair type for common data structures
* @template K The type of the key
* @template D The type of the data
*/
interface KeyData<K, D> {
key: K;
data: D;
}
/**
* Common API response wrapper type
* @template T The type of the data payload
*/
interface ApiResponse<T> {
data: T;
message?: string;
status: number;
success: boolean;
}
/**
* Pagination metadata interface
*/
interface PaginationMeta {
currentPage: number;
totalPages: number;
totalItems: number;
itemsPerPage: number;
hasNextPage: boolean;
hasPreviousPage: boolean;
}
/**
* Paginated response type
* @template T The type of the data items
*/
interface PaginatedResponse<T> {
data: T[];
meta: PaginationMeta;
}
/**
* Query parameters for pagination
*/
interface PaginationParams {
page?: number;
limit?: number;
offset?: number;
}
/**
* Common sort parameters
*/
interface SortParams {
sortBy?: string;
sortOrder?: "asc" | "desc";
}
/**
* Combined query parameters for API requests
*/
type QueryParams = Record<string, string | number | boolean> & Partial<PaginationParams> & Partial<SortParams>;
/**
* String filter types for PrimeNG table filtering
*/
type StringFilterType = "startsWith" | "notStartsWith" | "endsWith" | "notEndsWith" | "contains" | "notContains";
/**
* Numeric filter types for PrimeNG table filtering
*/
type NumericFilterType = "equals" | "notEquals" | "greaterThan" | "lessThan" | "greaterThanOrEqual" | "lessThanOrEqual";
/**
* Boolean filter types for PrimeNG table filtering
*/
type BooleanFilterType = Extract<NumericFilterType, "equals" | "notEquals">;
/**
* Combined filter types
*/
type FilterType = StringFilterType | NumericFilterType;
/**
* Filter type mappings for backend API
*/
type FilterTypeMapped = "starts" | "!starts" | "ends" | "!ends" | "like" | "!like" | "=" | "!=" | ">" | "<" | ">=" | "<=";
/**
* PrimeNG table header configuration interface
*/
interface PrimeNgTableHeader {
identifier: {
label?: string;
field: string;
hasSort?: boolean;
isBoolean?: boolean;
isNested?: boolean;
isDate?: boolean;
isDateTime?: boolean;
isTimeOnly?: boolean;
styleClass?: string;
};
filter?: {
type: "text" | "numeric" | "boolean" | "date" | "dropdown" | "multiselect";
placeholder?: string;
matchModeOptions?: any[];
defaultMatchMode: FilterType;
ariaLabel?: string;
colspan?: number;
styleClass?: Record<string, string>;
};
}
/**
* Dynamic query DTO interface
*/
interface DynamicQueryDto {
size: number;
page: number;
filter: DynamicQueryFilterDto[];
sort: DynamicQuerySortDto[];
}
/**
* Filter DTO for dynamic queries
*/
interface DynamicQueryFilterDto {
field: string;
value: string;
type: FilterTypeMapped;
}
/**
* Sort DTO for dynamic queries
*/
interface DynamicQuerySortDto {
field: string;
dir: "asc" | "desc";
}
/**
* Paged data response interface
*/
interface DynamicQueryPagedDataResponse<T> {
data: T[];
last_page: number;
last_row: number;
}
/**
* Paged data response interface for simple pagination
*/
interface PagedDataResponse<T> {
payload: T[];
totalCount: number;
}
/**
* Internal table state interface for dynamic table
*/
interface PrimeNgTableState<T> {
data: Array<T>;
isLoading: boolean;
size: number;
page: number;
totalRecords: number;
filter: DynamicQueryFilterDto[];
sort: DynamicQuerySortDto[];
}
/**
* Internal state interface for paged table
*/
interface PrimeNgPagedTableState<T> {
data: Array<T>;
isLoading: boolean;
totalRecords: number;
limit: number;
page: number;
}
/**
* Query DTO interface for paged data requests
*/
interface PagedDataQueryDto {
limit: number;
page: number;
}
/**
* Query parameters type for additional HTTP request parameters
*/
type PrimeNgTableStateHelperQueryParam = Record<string, string | number | boolean>;
/**
* Zod schema for dynamic query response validation
*/
declare const dynamicQueryResponseZodSchema: z.ZodObject<{
data: z.ZodArray<z.ZodAny>;
last_page: z.ZodNumber;
last_row: z.ZodNumber;
}, z.core.$strip>;
/**
* Zod schema for paged data response validation
*/
declare const PagedDataResponseZodSchema: z.ZodObject<{
payload: z.ZodArray<z.ZodAny>;
totalCount: z.ZodNumber;
}, z.core.$strip>;
/**
* Zod schema for number/string key with string data validation
*/
declare const NumberStringKeyDataSchema: z.ZodObject<{
key: z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>;
data: z.ZodString;
}, z.core.$strip>;
type NumberStringKeyData = z.infer<typeof NumberStringKeyDataSchema>;
/**
* Zod schema for nullable API response validation
* @template T The Zod schema type for the payload
* @param payloadSchema The Zod schema for the payload data
* @returns Zod schema for nullable API response
*/
declare const NullableApiResponseSchema: <T extends z.ZodTypeAny>(payloadSchema: T) => z.ZodObject<{
payload: z.ZodNullable<T>;
}, z.core.$strip>;
/**
* Type for nullable API response
* @template T The type of the payload data
*/
type NullableApiResponse<T> = {
payload: T | null;
};
/**
* Error response interface
*/
interface ErrorResponse {
error: string;
message: string;
statusCode: number;
timestamp: string;
}
/**
* Creates a key-value pair object
* @param key The key value
* @param data The data value
* @returns KeyData object
*/
declare function createKeyData<K, D>(key: K, data: D): KeyData<K, D>;
/**
* Type guard to check if a response is an API response
* @param response The response to check
* @returns true if response is ApiResponse, false otherwise
*/
declare function isApiResponse<T>(response: any): response is ApiResponse<T>;
/**
* Type guard to check if a response is paginated
* @param response The response to check
* @returns true if response is PaginatedResponse, false otherwise
*/
declare function isPaginatedResponse<T>(response: any): response is PaginatedResponse<T>;
/**
* Type guard to check if a response is a simple paged response
* @param response The response to check
* @returns true if response is PagedDataResponse, false otherwise
*/
declare function isSimplePagedResponse<T>(response: any): response is PagedDataResponse<T>;
/**
* Type guard to check if a response is a dynamic query response
* @param response The response to check
* @returns true if response is PagedDataResponse, false otherwise
*/
declare function isDynamicQueryResponse<T>(response: any): response is DynamicQueryPagedDataResponse<T>;
type NestableColumn = {
isNested?: boolean;
};
/**
* Calculates pagination parameters from PrimeNG table lazy load event
* @param event - The PrimeNG table lazy load event
* @param defaultValue - Default pagination values if event is null
* @returns Object containing page and limit for pagination
*/
declare function calculatePrimengTablePagination(event: TableLazyLoadEvent | null, defaultValue?: {
page: number;
limit: number;
}): {
page: number;
limit: number;
};
/**
* Options for creating PrimeNgDynamicTableStateHelper
*/
type PrimeNgDynamicTableStateOpts = {
url: string;
httpClient: HttpClient;
skipLoadingSpinner?: boolean;
};
/**
* PrimeNG Dynamic Table State Helper class for managing table state with lazy loading, filtering, and sorting
*
* This helper provides advanced table functionality including:
* - Lazy loading with pagination
* - Column filtering with multiple filter types
* - Multi-column sorting
* - State management with NgRx Signals
* - Automatic API integration
* - Route parameter support
* - Query parameter management
*
* @example
* ```typescript
* const tableState = PrimeNgDynamicTableStateHelper.create<User>({
* url: '/api/users',
* httpClient: this.httpClient
* });
*
* // In template
* <p-table [value]="tableState.data()"
* [lazy]="true"
* [loading]="tableState.isLoading()"
* [totalRecords]="tableState.totalRecords()"
* (onLazyLoad)="tableState.onLazyLoad($event)">
* </p-table>
* ```
*/
declare class PrimeNgDynamicTableStateHelper<T> {
#private;
private url;
private readonly httpClient;
private readonly state;
private urlWithOutRouteParam;
private skipLoadingSpinner;
readonly uniqueKey: Signal<string>;
readonly totalRecords: Signal<number>;
readonly isLoading: Signal<boolean>;
readonly data: Signal<Array<T>>;
private constructor();
/**
* Creates a new instance of PrimeNgDynamicTableStateHelper
* @param options - Configuration options
* @returns New instance of PrimeNgDynamicTableStateHelper
*/
static create<T>(options: PrimeNgDynamicTableStateOpts): PrimeNgDynamicTableStateHelper<T>;
/**
* Sets whether to skip the loading spinner
* @param skip - Whether to skip the loading spinner
* @returns This instance for method chaining
*/
setSkipLoadingSpinner(skip: boolean): this;
/**
* Sets the unique key field for table rows
* @param newUniqueKey - The field name to use as unique identifier
* @returns This instance for method chaining
*/
setUniqueKey(newUniqueKey: string): this;
/**
* Updates the API URL
* @param newUrl - The new API URL
* @returns This instance for method chaining
*/
setUrl(newUrl: string): this;
/**
* Appends a route parameter to the URL
* @param newRouteParam - The route parameter to append
* @returns This instance for method chaining
*/
setRouteParam(newRouteParam: string): this;
/**
* Patches existing query parameters
* @param value - Query parameters to merge
* @returns This instance for method chaining
*/
patchQueryParams(value: PrimeNgTableStateHelperQueryParam): this;
/**
* Removes a specific query parameter
* @param key - The key to remove
* @returns This instance for method chaining
*/
removeQueryParam(key: string): this;
/**
* Sets all query parameters (replaces existing)
* @param newQueryParams - New query parameters
* @returns This instance for method chaining
*/
setQueryParams(newQueryParams: PrimeNgTableStateHelperQueryParam): this;
/**
* Handles PrimeNG table lazy load events
* @param event - The lazy load event from PrimeNG table
*/
onLazyLoad(event: TableLazyLoadEvent): Promise<void>;
/**
* Clears table data and resets to first page
* @param table - Optional PrimeNG Table reference to reset
*/
clearTableData(table?: Table): Promise<void>;
/**
* Manually triggers data refresh with current state
*/
refresh(): Promise<void>;
/**
* Fetches data from the API
*/
private fetchData;
/**
* Builds the DTO for API requests
*/
private dtoBuilder;
/**
* Maps PrimeNG filters to API filter format
*/
private filterMapper;
/**
* Maps PrimeNG filter match modes to API filter types
*/
private evaluateInput;
}
/**
* Options for creating PrimengPagedDataTableStateHelper
*/
type PrimeNgPagedTableStateOpts = {
url: string;
httpClient: HttpClient;
skipLoadingSpinner?: boolean;
};
/**
* Simple paged data table state helper for basic pagination without filtering
*
* This helper provides basic table functionality including:
* - Simple pagination (page and limit only)
* - Basic state management with NgRx Signals
* - API integration for paged data
* - Route parameter support
* - Query parameter management
*
* Use this when you need simple pagination without complex filtering and sorting.
* For advanced features, use PrimeNgDynamicTableStateHelper instead.
*
* @example
* ```typescript
* const tableState = PrimengPagedDataTableStateHelper.create<Product>({
* url: '/api/products',
* httpClient: this.httpClient
* });
*
* // In template
* <p-table [value]="tableState.data()"
* [lazy]="true"
* [loading]="tableState.isLoading()"
* [totalRecords]="tableState.totalRecords()"
* (onLazyLoad)="tableState.onLazyLoad($event)">
* </p-table>
* ```
*/
declare class PrimeNgPagedDataTableStateHelper<T> {
#private;
private url;
private readonly httpClient;
private urlWithOutRouteParam;
private skipLoadingSpinner;
readonly uniqueKey: Signal<string>;
readonly totalRecords: Signal<number>;
readonly isLoading: Signal<boolean>;
readonly data: Signal<Array<T>>;
readonly currentPage: Signal<number>;
readonly currentPageSize: Signal<number>;
private constructor();
/**
* Creates a new instance of PrimengPagedDataTableStateHelper
* @param option - Configuration options
* @returns New instance of PrimengPagedDataTableStateHelper
*/
static create<T>(option: PrimeNgPagedTableStateOpts): PrimeNgPagedDataTableStateHelper<T>;
/**
* Creates a new instance without initial URL (can be set later)
* @param option - Configuration options without URL
* @returns New instance of PrimengPagedDataTableStateHelper
*/
static createWithBlankUrl<T>(option: Omit<PrimeNgPagedTableStateOpts, "url">): PrimeNgPagedDataTableStateHelper<T>;
/**
* Sets whether to skip the loading spinner
* @param skip - Whether to skip the loading spinner
* @returns This instance for method chaining
*/
setSkipLoadingSpinner(skip: boolean): this;
/**
* Sets the unique key field for table rows
* @param newUniqueKey - The field name to use as unique identifier
* @returns This instance for method chaining
*/
setUniqueKey(newUniqueKey: string): this;
/**
* Updates the API URL
* @param newUrl - The new API URL
* @returns This instance for method chaining
*/
setUrl(newUrl: string): this;
/**
* Appends a route parameter to the URL
* @param newRouteParam - The route parameter to append
* @returns This instance for method chaining
*/
setRouteParam(newRouteParam: string): this;
/**
* Patches existing query parameters
* @param value - Query parameters to merge
* @returns This instance for method chaining
*/
patchQueryParams(value: PrimeNgTableStateHelperQueryParam): this;
/**
* Removes a specific query parameter
* @param key - The key to remove
* @returns This instance for method chaining
*/
removeQueryParam(key: string): this;
/**
* Removes all query parameters
* @returns This instance for method chaining
*/
removeAllQueryParams(): this;
/**
* Sets all query parameters (replaces existing)
* @param newQueryParams - New query parameters
* @returns This instance for method chaining
*/
setQueryParams(newQueryParams: PrimeNgTableStateHelperQueryParam): this;
/**
* Handles PrimeNG table lazy load events
* @param event - The lazy load event from PrimeNG table
*/
onLazyLoad(event: TableLazyLoadEvent): Promise<void>;
/**
* Clears table data and resets to first page
* @param table - Optional PrimeNG Table reference to reset
*/
clearTableData(table?: Table): Promise<void>;
/**
* Manually triggers data refresh with current state
*/
refresh(): Promise<void>;
/**
* Fetches data from the API
*/
private fetchData;
/**
* Builds the DTO for API requests
*/
private dtoBuilder;
}
/**
* HTTP Context Token to skip loading spinner on HTTP requests
* Usage: Set this token to true in HttpContext to skip showing loading spinner
*
* @example
* ```typescript
* const context = new HttpContext().set(SkipLoadingSpinner, true);
* this.httpClient.get('/api/data', { context });
* ```
*/
declare const SkipLoadingSpinner: HttpContextToken<boolean>;
/**
* Creates PrimeNG SelectItem array for numeric filter match modes
* @param styleClass - CSS class for styling the options
* @param disabled - Whether the options should be disabled
* @returns Array of SelectItem for numeric filters
*/
declare function createPrimengNumberMatchModes(styleClass?: string, disabled?: boolean): SelectItem<NumericFilterType>[];
/**
* Creates PrimeNG SelectItem array for string filter match modes
* @param styleClass - CSS class for styling the options
* @param disabled - Whether the options should be disabled
* @returns Array of SelectItem for string filters
*/
declare function createPrimengStringMatchModes(styleClass?: string, disabled?: boolean): SelectItem<StringFilterType>[];
/**
* Creates a complete table header configuration for text columns
* @param field - The field name for the column
* @param label - Display label for the column header
* @param options - Additional configuration options
* @returns Complete PrimeNgTableHeader configuration
*/
declare function createTextColumn(field: string, label: string, options?: {
hasSort?: boolean;
hasFilter?: boolean;
placeholder?: string;
matchModeOptions?: SelectItem<StringFilterType>[];
defaultMatchMode?: StringFilterType;
styleClass?: string;
filterStyleClass?: Record<string, string>;
} & NestableColumn): PrimeNgTableHeader;
/**
* Creates a complete table header configuration for numeric columns
* @param field - The field name for the column
* @param label - Display label for the column header
* @param options - Additional configuration options
* @returns Complete PrimeNgTableHeader configuration
*/
declare function createNumericColumn(field: string, label: string, options?: {
hasSort?: boolean;
hasFilter?: boolean;
placeholder?: string;
matchModeOptions?: SelectItem<NumericFilterType>[];
defaultMatchMode?: NumericFilterType;
styleClass?: string;
filterStyleClass?: Record<string, string>;
} & NestableColumn): PrimeNgTableHeader;
/**
* Creates a complete table header configuration for boolean columns
* @param field - The field name for the column
* @param label - Display label for the column header
* @param options - Additional configuration options
* @returns Complete PrimeNgTableHeader configuration
*/
declare function createBooleanColumn(field: string, label: string, options?: {
hasSort?: boolean;
hasFilter?: boolean;
styleClass?: string;
filterStyleClass?: Record<string, string>;
} & NestableColumn): PrimeNgTableHeader;
/**
* Creates a complete table header configuration for date columns (date only)
* @param field - The field name for the column
* @param label - Display label for the column header
* @param options - Additional configuration options
* @returns Complete PrimeNgTableHeader configuration
*/
declare function createDateColumn(field: string, label: string, options?: {
hasSort?: boolean;
hasFilter?: boolean;
placeholder?: string;
styleClass?: string;
filterStyleClass?: Record<string, string>;
} & NestableColumn): PrimeNgTableHeader;
/**
* Creates a complete table header configuration for datetime columns (date and time)
* @param field - The field name for the column
* @param label - Display label for the column header
* @param options - Additional configuration options
* @returns Complete PrimeNgTableHeader configuration
*/
declare function createDateTimeColumn(field: string, label: string, options?: {
hasSort?: boolean;
hasFilter?: boolean;
placeholder?: string;
styleClass?: string;
filterStyleClass?: Record<string, string>;
} & NestableColumn): PrimeNgTableHeader;
/**
* Creates a complete table header configuration for time-only columns
* @param field - The field name for the column
* @param label - Display label for the column header
* @param options - Additional configuration options
* @returns Complete PrimeNgTableHeader configuration
*/
declare function createTimeColumn(field: string, label: string, options?: {
hasSort?: boolean;
hasFilter?: boolean;
placeholder?: string;
styleClass?: string;
filterStyleClass?: Record<string, string>;
} & NestableColumn): PrimeNgTableHeader;
/**
* Creates a complete table header configuration for dropdown columns
* @param field - The field name for the column
* @param label - Display label for the column header
* @param dropdownOptions - Options for the dropdown filter
* @param options - Additional configuration options
* @returns Complete PrimeNgTableHeader configuration
*/
declare function createDropdownColumn(field: string, label: string, dropdownOptions: SelectItem[], options?: {
hasSort?: boolean;
hasFilter?: boolean;
placeholder?: string;
styleClass?: string;
filterStyleClass?: Record<string, string>;
}): PrimeNgTableHeader;
/**
* Creates a complete table header configuration for multiselect columns
* @param field - The field name for the column
* @param label - Display label for the column header
* @param multiselectOptions - Options for the multiselect filter
* @param options - Additional configuration options
* @returns Complete PrimeNgTableHeader configuration
*/
declare function createMultiselectColumn(field: string, label: string, multiselectOptions: SelectItem[], options?: {
hasSort?: boolean;
hasFilter?: boolean;
placeholder?: string;
styleClass?: string;
filterStyleClass?: Record<string, string>;
}): PrimeNgTableHeader;
/**
* Creates a simple table header configuration without filtering
* @param field - The field name for the column
* @param label - Display label for the column header
* @param options - Additional configuration options
* @returns Simple PrimeNgTableHeader configuration
*/
declare function createSimpleColumn(field: string, label: string, options?: {
hasSort?: boolean;
styleClass?: string;
} & NestableColumn): PrimeNgTableHeader;
/**
* Utility function to merge multiple table header configurations
* @param headers - Array of table header configurations
* @returns Array of merged headers
*/
declare function mergeTableHeaders(...headers: PrimeNgTableHeader[]): PrimeNgTableHeader[];
/**
* Utility function to create boolean SelectItem options
* @param trueLabel - Label for true value
* @param falseLabel - Label for false value
* @returns Array of SelectItem for boolean values
*/
declare function createBooleanSelectItems(trueLabel?: string, falseLabel?: string): SelectItem[];
/**
* Utility function to create status SelectItem options
* @param statusOptions - Object mapping status values to labels
* @returns Array of SelectItem for status values
*/
declare function createStatusSelectItems(statusOptions: Record<string | number, string>): SelectItem[];
/**
* Utility function to remove null and undefined values from an object
*
* This is particularly useful when setting query parameters, as null/undefined
* values should typically be filtered out before sending to APIs.
*
* @param o The object to clean
* @returns A new object with null and undefined values removed
*
* @example
* ```typescript
* const queryParams = {
* name: 'John',
* age: null,
* email: 'john@example.com',
* phone: undefined
* };
*
* const cleaned = cleanNullishFromObject(queryParams);
* // Result: { name: 'John', email: 'john@example.com' }
*
* // Use case with table state
* this.tableState.setQueryParams(cleanNullishFromObject(queryParams));
* ```
*/
declare function cleanNullishFromObject(obj?: object): Record<string, any>;
declare function hasNullishInObject(obj: object): boolean;
declare function routeParamConcat(baseUrl: string, routeParam: number | string): string;
declare function binarySearch<TItem>(arr: TItem[], val: TItem): number;
declare function emptyCallback(): void;
declare function nullableKeyData<TKey, TData>(key: TKey | null, data: TData | null): KeyData<TKey, TData> | null;
declare class ReloadNotification {
static create(): ReloadNotification;
}
/**
* Represents a tree node structure compatible with PrimeNG TreeNode
* @template T The type of data stored in the node
*/
type TreeItem<T> = {
data: T;
children?: TreeItem<T>[];
};
/**
* Creates a hierarchical tree structure from flat array data
*
* Converts a flat array of items with parent-child relationships into a tree structure
* compatible with PrimeNG Tree component.
*
* @template T The type of items in the array
* @param data Array of flat data items
* @param idKey The property name that contains the unique identifier
* @param parentIdKey The property name that contains the parent identifier
* @returns Array of root tree nodes with nested children
*
* @example
* ```typescript
* interface Category {
* id: number;
* name: string;
* parentCategoryId: number | null;
* }
*
* const categories: Category[] = [
* { id: 1, name: 'Electronics', parentCategoryId: null },
* { id: 2, name: 'Computers', parentCategoryId: 1 },
* { id: 3, name: 'Laptops', parentCategoryId: 2 }
* ];
*
* const tree = createHierarchicalTree(categories, 'id', 'parentCategoryId');
* // Result: Tree structure with Electronics -> Computers -> Laptops
* ```
*/
declare function createHierarchicalTree<T extends Record<string, any>>(data: Array<T>, idKey: string, parentIdKey: string, expanded?: boolean): TreeItem<T>[];
/**
* A generic class for memoizing data storage with HTTP caching capabilities
* Provides methods to load and cache single data objects or arrays with automatic loading states
*
* @template T The type of data to be stored and managed
*
* @example
* ```typescript
* interface User { id: number; name: string; }
*
* const userStorage = new MemoizedDataStorage<User>(httpClient);
* await userStorage.loadSingleData('/api/user/1');
* console.log(userStorage.singleData()); // User data or null
*
* const usersStorage = new MemoizedDataStorage<User>(httpClient);
* await usersStorage.loadMultipleData('/api/users');
* console.log(usersStorage.multipleData()); // Array of User data
* ```
*/
declare class MemoizedDataStorage<T> {
#private;
readonly httpClient: HttpClient;
private skipLoadingSpinner;
/**
* Creates a new instance of MemoizedDataStorage
* @param httpClient Angular HttpClient instance for making HTTP requests
* @param skipLoadingSpinner Whether to skip the loading spinner for HTTP requests
*/
constructor(httpClient: HttpClient, skipLoadingSpinner?: boolean);
/**
* Sets whether to skip the loading spinner for HTTP requests
* @param skip Whether to skip the loading spinner
* @returns This instance for method chaining
*/
setSkipLoadingSpinner(skip: boolean): this;
/**
* Read-only signal containing single data object or null
*/
readonly singleData: _angular_core.Signal<T | null>;
/**
* Read-only signal containing array of data objects
*/
readonly multipleData: _angular_core.Signal<T[]>;
/**
* Read-only signal indicating whether a request is currently loading
*/
readonly isLoading: _angular_core.Signal<boolean>;
/**
* Disables memoization for the next read operation and clears cached data
* This forces the next loadSingleData or loadMultipleData call to fetch fresh data
*
* @example
* ```typescript
* const storage = new MemoizedDataStorage<User>(httpClient);
* await storage.loadSingleData('/api/user/1'); // Fetches data
* await storage.loadSingleData('/api/user/1'); // Returns cached data
*
* storage.disableMemoizationOnNextRead();
* await storage.loadSingleData('/api/user/1'); // Fetches fresh data
* ```
*/
disableMemoizationOnNextRead(): void;
/**
* Loads a single data object from the specified URL with optional query parameters
* Uses memoization to avoid redundant requests unless explicitly disabled
*
* @param url The URL to fetch data from
* @param queryParams Optional query parameters to include in the request
* @returns Promise that resolves when the data is loaded
* @throws Error if the HTTP request fails
*
* @example
* ```typescript
* const storage = new MemoizedDataStorage<User>(httpClient);
* await storage.loadSingleData('/api/user/1', { include: 'profile' });
* const user = storage.singleData(); // User data or null
* ```
*/
loadSingleData(url: string, queryParams?: Record<string, string | number>): Promise<void>;
/**
* Loads multiple data objects from the specified URL with optional query parameters
* Uses memoization to avoid redundant requests unless explicitly disabled
*
* @param url The URL to fetch data from
* @param queryParams Optional query parameters to include in the request
* @returns Promise that resolves when the data is loaded
* @throws Error if the HTTP request fails
*
* @example
* ```typescript
* const storage = new MemoizedDataStorage<User>(httpClient);
* await storage.loadMultipleData('/api/users', { page: 1, limit: 10 });
* const users = storage.multipleData(); // Array of User data
* ```
*/
loadMultipleData(url: string, queryParams?: Record<string, string | number>): Promise<void>;
/**
* Clears all cached data and resets the storage to initial state
*
* @example
* ```typescript
* const storage = new MemoizedDataStorage<User>(httpClient);
* await storage.loadSingleData('/api/user/1');
* storage.clear(); // Clears cached data
* console.log(storage.singleData()); // null
* console.log(storage.multipleData()); // []
* ```
*/
clear(): void;
/**
* Checks if single data is currently cached
* @returns true if single data is cached, false otherwise
*/
hasSingleData(): boolean;
/**
* Checks if multiple data is currently cached
* @returns true if multiple data is cached (non-empty array), false otherwise
*/
hasMultipleData(): boolean;
}
/**
* A reactive state management class for Angular components using signals
* Provides common component state properties and computed values
*
* @example
* ```typescript
* @Component({
* selector: 'app-user-management',
* template: `
* <h2>{{ componentState.componentTitleWithManipulationType() }}</h2>
* <p-button
* [loading]="componentState.isAnyAjaxOperationRunning()"
* [disabled]="componentState.isAnyAjaxOperationRunning()">
* Save
* </p-button>
* `
* })
* export class UserManagementComponent {
* componentState = new ComponentState()
* .updateComponentTitle('User')
* .updateCheckBoxSelectionStatus(true);
* }
* ```
*/
declare class ComponentState {
readonly isAjaxDataIncoming: _angular_core.WritableSignal<boolean>;
readonly enableCheckBoxSelection: _angular_core.WritableSignal<boolean>;
readonly isSelectableRowEnabled: _angular_core.WritableSignal<boolean>;
readonly isAjaxRequestOutgoing: _angular_core.WritableSignal<boolean>;
readonly hasMultipleSelection: _angular_core.WritableSignal<boolean>;
readonly isCreateOrUpdateDialogOpen: _angular_core.WritableSignal<boolean>;
readonly isUpdateDialogOpen: _angular_core.WritableSignal<boolean>;
readonly isCreateDialogOpen: _angular_core.WritableSignal<boolean>;
readonly manipulationType: _angular_core.WritableSignal<ManipulationType>;
readonly componentTitle: _angular_core.WritableSignal<string>;
readonly isDataManipulationPageOpen: _angular_core.WritableSignal<boolean>;
readonly isCreateOrUpdatePageOpen: _angular_core.WritableSignal<boolean>;
readonly isUpdatePageOpen: _angular_core.WritableSignal<boolean>;
readonly isCreatePageOpen: _angular_core.WritableSignal<boolean>;
readonly manipulationTypeLabel: _angular_core.Signal<"" | "Create" | "Update" | "Create Child" | "Delete" | "View" | "Save">;
/**
* Updates the component title
* @param componentTitle - The new title for the component
* @returns This instance for method chaining
*/
updateComponentTitle: (componentTitle: string) => this;
/**
* Updates the multiple selection status
* @param newStatus - Whether multiple selection is enabled
* @returns This instance for method chaining
*/
updateMultipleSelectionStatus: (newStatus: boolean) => this;
/**
* Updates the checkbox selection status
* @param newStatus - Whether checkbox selection is enabled
* @returns This instance for method chaining
*/
updateCheckBoxSelectionStatus: (newStatus: boolean) => this;
/**
* Updates the selectable row status
* @param newStatus - Whether row selection is enabled
* @returns This instance for method chaining
*/
updateSelectableRowStatus: (newStatus: boolean) => this;
/**
* Updates the manipulation type (Create, Update, Delete, View)
* @param type - The manipulation type
* @returns This instance for method chaining
*/
updateManipulationType: (type: ManipulationType) => this;
/**
* Sets the incoming Ajax data status
* @param status - Whether Ajax data is incoming
* @returns This instance for method chaining
*/
setAjaxDataIncoming: (status: boolean) => this;
/**
* Sets the outgoing Ajax request status
* @param status - Whether Ajax request is outgoing
* @returns This instance for method chaining
*/
setAjaxRequestOutgoing: (status: boolean) => this;
/**
* Sets the create or update dialog open status
* @param status - Whether the dialog is open
* @returns This instance for method chaining
*/
setCreateOrUpdateDialogOpen: (status: boolean) => this;
/**
* Sets the update dialog open status
* @param status - Whether the update dialog is open
* @returns This instance for method chaining
*/
setUpdateDialogOpen: (status: boolean) => this;
/**
* Sets the create dialog open status
* @param status - Whether the create dialog is open
* @returns This instance for method chaining
*/
setCreateDialogOpen: (status: boolean) => this;
/**
* Computed signal that combines component title with manipulation type
*/
readonly componentTitleWithManipulationType: _angular_core.Signal<string>;
/**
* Computed signal that indicates if component is in update state
*/
readonly isOnUpdateState: _angular_core.Signal<boolean>;
/**
* Computed signal that indicates if component is in create state
*/
readonly isOnCreateState: _angular_core.Signal<boolean>;
/**
* Computed signal that indicates if component is in delete state
*/
readonly isOnDeleteState: _angular_core.Signal<boolean>;
/**
* Computed signal that indicates if component is in view state
*/
readonly isOnViewState: _angular_core.Signal<boolean>;
/**
* Computed signal that indicates if any Ajax operation is currently running
*/
readonly isAnyAjaxOperationRunning: _angular_core.Signal<boolean>;
/**
* Computed signal that indicates if any dialog is open
*/
readonly isAnyDialogOpen: _angular_core.Signal<boolean>;
/**
* Resets all state to default values
* @returns This instance for method chaining
*/
reset: () => this;
}
/**
* A generic component data storage class using Angular signals
* Provides reactive data management for both single objects and arrays
*
* @template T The type of data to be stored and managed
*
* @example
* ```typescript
* interface User {
* id: number;
* name: string;
* email: string;
* }
*
* @Component({
* selector: 'app-user-list',
* template: `
* <!-- Single user display -->
* @if (dataStorage.singleData(); as user) {
* <div>
* <h3>{{ user.name }}</h3>
* <p>{{ user.email }}</p>
* </div>
* }
*
* <!-- Multiple users display -->
* @for (user of dataStorage.multipleData(); track user.id) {
* <div>{{ user.name }} - {{ user.email }}</div>
* }
* `
* })
* export class UserListComponent {
* dataStorage = new ComponentDataStorage<User>();
*
* ngOnInit() {
* // Set initial data
* this.dataStorage
* .updateSingleData({ id: 1, name: 'John', email: 'john@example.com' })
* .updateMultipleData([
* { id: 1, name: 'John', email: 'john@example.com' },
* { id: 2, name: 'Jane', email: 'jane@example.com' }
* ]);
* }
* }
* ```
*/
declare class ComponentDataStorage<T> {
readonly singleData: _angular_core.WritableSignal<T | null>;
readonly multipleData: _angular_core.WritableSignal<T[]>;
/**
* Patches multiple data by appending new data to the existing array
* @param newData - Array of new data to append
* @returns This instance for method chaining
*
* @example
* ```typescript
* const storage = new ComponentDataStorage<User>();
* storage.updateMultipleData([{ id: 1, name: 'John' }]);
* storage.patchMultipleData([{ id: 2, name: 'Jane' }]);
* // Result: [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }]
* ```
*/
patchMultipleData(newData: Array<T>): this;
/**
* Patches single data by merging new properties with existing data
* If no existing data, creates new object with provided data
* @param newData - Partial data to merge with existing single data
* @returns This instance for method chaining
*
* @example
* ```typescript
* const storage = new ComponentDataStorage<User>();
* storage.updateSingleData({ id: 1, name: 'John', email: 'john@example.com' });
* storage.patchSingleData({ email: 'john.doe@example.com' });
* // Result: { id: 1, name: 'John', email: 'john.doe@example.com' }
* ```
*/
patchSingleData(newData: Partial<T>): this;
/**
* Replaces the entire multiple data array
* @param newData - New array of data to replace existing data
* @returns This instance for method chaining
*/
updateMultipleData(newData: Array<T>): this;
/**
* Replaces the single data object
* @param newData - New data object or null to replace existing data
* @returns This instance for method chaining
*/
updateSingleData(newData: T | null): this;
/**
* Adds a single item to the multiple data array
* @param item - Single item to add to the array
* @returns This instance for method chaining
*/
addToMultipleData(item: T): this;
/**
* Removes an item from the multiple data array based on a predicate function
* @param predicate - Function that returns true for items to remove
* @returns This instance for method chaining
*
* @example
* ```typescript
* storage.removeFromMultipleData(user => user.id === 1);
* ```
*/
removeFromMultipleData(predicate: (item: T) => boolean): this;
/**
* Updates an item in the multiple data array based on a predicate function
* @param predicate - Function that returns true for items to update
* @param updateFn - Function that returns the updated item
* @returns This instance for method chaining
*
* @example
* ```typescript
* storage.updateItemInMultipleData(
* user => user.id === 1,
* user => ({ ...user, name: 'Updated Name' })
* );
* ```
*/
updateItemInMultipleData(predicate: (item: T) => boolean, updateFn: (item: T) => T): this;
/**
* Clears all data (both single and multiple)
* @returns This instance for method chaining
*/
clearAll(): this;
/**
* Clears only the single data
* @returns This instance for method chaining
*/
clearSingleData(): this;
/**
* Clears only the multiple data
* @returns This instance for method chaining
*/
clearMultipleData(): this;
/**
* Checks if single data exists (is not null)
* @returns true if single data exists, false otherwise
*/
hasSingleData: _angular_core.Signal<boolean>;
/**
* Checks if multiple data has items
* @returns true if multiple data array has items, false if empty
*/
hasMultipleData: _angular_core.Signal<boolean>;
/**
* Gets the count of items in multiple data
* @returns Number of items in the multiple data array
*/
getMultipleDataCount: _angular_core.Signal<number>;
/**
* Finds an item in the multiple data array
* @param predicate - Function that returns true for the item to find
* @returns The found item or undefined
*/
findInMultipleData(predicate: (item: T) => boolean): T | undefined;
/**
* Checks if an item exists in the multiple data array
* @param predicate - Function that returns true for the item to check
* @returns true if item exists, false otherwise
*/
existsInMultipleData(predicate: (item: T) => boolean): boolean;
}
/**
* Configuration options for NgSelectHelper
*/
type NgSelectHelperOpts = {
ajaxUrl: string;
httpClient: HttpClient;
destroyRef: DestroyRef;
usePostRequest?: boolean;
initialSearchText?: string;
limit?: number;
useCache?: boolean;
skipLoadingSpinner?: boolean;
};
/**
* Reset options for NgSelectHelper
*/
type NgSelectHelperResetOpts = {
resetQueryParams: boolean;
resetBody: boolean;
resetCache: boolean;
};
/**
* Query parameter type for NgSelectHelper
*/
type NgSelectHelperQueryParam = Record<string, string | number | boolean>;
/**
* Body type for NgSelectHelper POST requests
*/
type NgSelectHelperBody = Array<string | number | boolean | null | Record<string, string | number | boolean | null>> | Record<string, string | number | boolean | null | Array<string | number | boolean | null | Record<string, string | number | boolean | null>>>;
/**
* Paged data response specifically for ng-select
*/
declare class NgSelectPagedDataResponse<TData> {
readonly payload: Array<TData>;
readonly totalCount: number;
constructor(payload: Array<TData>, totalCount: number);
}
/**
* NgSelectHelper class for managing ng-select components with HTTP data loading,
* pagination, caching, and search functionality using Angular signals
*
* @template TData The type of data items in the select options
*
* @example
* ```typescript
* interface User {
* id: number;
* name: string;
* email: string;
* }
*
* @Component({
* selector: 'app-user-select',
* template: `
* <ng-select
* [items]="selectHelper.loadedData().payload"
* bindLabel="name"
* bindValue="id"
* [loading]="selectHelper.isLoading()"
* [typeahead]="selectHelper.inputSubject"
* (open)="selectHelper.onOpen()"
* (close)="selectHelper.onClose()"
* (clear)="selectHelper.onClear()"
* (scrollToEnd)="selectHelper.onScrollToEnd()">
* </ng-select>
* `
* })
* export class UserSelectComponent implements OnInit {
* private httpClient = inject(HttpClient);
* private destroyRef = inject(DestroyRef);
*
* selectHelper = NgSelectHelper.create<User>({
* ajaxUrl: '/api/users',
* httpClient: this.httpClient,
* destroyRef: this.destroyRef,
* usePostRequest: false,
* limit: 20
* });
*
* ngOnInit() {
* this.selectHelper.init();
* }
* }
*
* ```
*/
/**
* @deprecated Migrate to `offsetPaginatedNgSelectState`
*
* **Migration Guide:**
*
* - `init` method is removed because no manual state initialization is needed.
* - `resetAll` method is renamed to `reset`.
* - Loaded data is exposed as data signal. Use it like: `[items]="ngSelectState.data()"`
* - `search` event handling is now compulsory with `onSearch`. Handle it like: `(search)="ngSelectState.onSearch($event)"`
* - `blur` event handling is not required and the method `onBlur` is removed.
* - `setQueryParams` method is removed. Current example approach: `ngSelectState.removeAllQueryParams().patchQueryParams({id: 123})`
* - `setRouteParam` method is removed. If route param needs update, pass a signal of type string in the url and update the signal afterwards.
* - Cache is now disabled by default and supports TTL.
* - `skipLoadingSpinner` is removed. Instead, use the exported `OffsetPaginatedNgSelectNetworkRequest` http context token.
* - `offsetPaginatedNgSelectState` must be run within injection context. Provide injector manually to run outside injection context.
*/
declare class NgSelectHelper<TData> {
#private;
private ajaxUrl;
private readonly httpClient;
private readonly destroyRef;
readonly usePostRequest: boolean;
private readonly useCache;
private skipLoadingSpinner;
constructor(ajaxUrl: string, httpClient: HttpClient, destroyRef: DestroyRef, usePostRequest?: boolean, limit?: number, useCache?: boolean, skipLoadingSpinner?: boolean, initialSearchText?: string);
readonly inputSubject: Subject<string>;
readonly ajaxError$: Observable<Error>;
readonly loadedData: _angular_core.Signal<NgSelectPagedDataResponse<TData>>;
readonly isLoading: _angular_core.Signal<boole