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 lines • 109 kB
Source Map (JSON)
{"version":3,"sources":["../src/dynamic-table-state-helper.ts","../src/http-context-tokens.ts","../src/types.ts","../src/paged-table-state-helper.ts","../src/table-utils.ts","../src/utils.ts","../src/memoized-data-storage.ts","../src/component-state.ts","../src/component-data-storage.ts","../src/ng-select-helper.ts","../src/ng-select-utils.ts"],"sourcesContent":["import { HttpClient, HttpContext } from '@angular/common/http';\nimport { signal, Signal } from '@angular/core';\nimport { signalState, patchState } from '@ngrx/signals';\nimport { FilterMetadata } from 'primeng/api';\nimport { Table, TableLazyLoadEvent } from 'primeng/table';\nimport { firstValueFrom } from 'rxjs';\n\nimport { SkipLoadingSpinner } from './http-context-tokens';\nimport {\n DynamicQueryDto,\n DynamicQueryFilterDto,\n DynamicQuerySortDto,\n PagedDataResponse,\n PrimeNgTableState,\n PrimeNgTableStateHelperQueryParam,\n FilterTypeMapped,\n dynamicQueryResponseZodSchema\n} from './types';\n\n/**\n * Initial state factory function for dynamic table\n */\nfunction initialDynamicState<T>(): PrimeNgTableState<T> {\n return {\n data: [],\n isLoading: false,\n totalRecords: 0,\n size: 15,\n page: 1,\n filter: [],\n sort: []\n };\n}\n\n/**\n * Options for creating PrimeNgDynamicTableStateHelper\n */\ntype PrimeNgDynamicTableStateOpts = {\n url: string;\n httpClient: HttpClient;\n skipLoadingSpinner?: boolean;\n};\n\n/**\n * PrimeNG Dynamic Table State Helper class for managing table state with lazy loading, filtering, and sorting\n * \n * This helper provides advanced table functionality including:\n * - Lazy loading with pagination\n * - Column filtering with multiple filter types\n * - Multi-column sorting\n * - State management with NgRx Signals\n * - Automatic API integration\n * - Route parameter support\n * - Query parameter management\n * \n * @example\n * ```typescript\n * const tableState = PrimeNgDynamicTableStateHelper.create<User>({\n * url: '/api/users',\n * httpClient: this.httpClient\n * });\n * \n * // In template\n * <p-table [value]=\"tableState.data()\"\n * [lazy]=\"true\"\n * [loading]=\"tableState.isLoading()\"\n * [totalRecords]=\"tableState.totalRecords()\"\n * (onLazyLoad)=\"tableState.onLazyLoad($event)\">\n * </p-table>\n * ```\n */\nexport class PrimeNgDynamicTableStateHelper<T> {\n private readonly state = signalState<PrimeNgTableState<T>>(initialDynamicState<T>());\n private urlWithOutRouteParam: string;\n private skipLoadingSpinner: boolean;\n readonly #uniqueKey = signal(\"id\");\n readonly uniqueKey = this.#uniqueKey.asReadonly();\n #queryParams: PrimeNgTableStateHelperQueryParam = {};\n\n // Public readonly signals\n readonly totalRecords: Signal<number> = this.state.totalRecords;\n readonly isLoading: Signal<boolean> = this.state.isLoading;\n readonly data: Signal<Array<T>> = this.state.data;\n\n private constructor(\n private url: string,\n private readonly httpClient: HttpClient,\n skipLoadingSpinner: boolean = true\n ) {\n this.urlWithOutRouteParam = url;\n this.skipLoadingSpinner = skipLoadingSpinner;\n }\n\n /**\n * Creates a new instance of PrimeNgDynamicTableStateHelper\n * @param options - Configuration options\n * @returns New instance of PrimeNgDynamicTableStateHelper\n */\n public static create<T>(options: PrimeNgDynamicTableStateOpts): PrimeNgDynamicTableStateHelper<T> {\n return new PrimeNgDynamicTableStateHelper<T>(\n options.url,\n options.httpClient,\n options.skipLoadingSpinner ?? true\n );\n }\n\n /**\n * Sets whether to skip the loading spinner\n * @param skip - Whether to skip the loading spinner\n * @returns This instance for method chaining\n */\n public setSkipLoadingSpinner(skip: boolean): this {\n this.skipLoadingSpinner = skip;\n return this;\n }\n\n /**\n * Sets the unique key field for table rows\n * @param newUniqueKey - The field name to use as unique identifier\n * @returns This instance for method chaining\n */\n public setUniqueKey(newUniqueKey: string): this {\n this.#uniqueKey.set(newUniqueKey);\n return this;\n }\n\n /**\n * Updates the API URL\n * @param newUrl - The new API URL\n * @returns This instance for method chaining\n */\n public setUrl(newUrl: string): this {\n this.url = newUrl;\n this.urlWithOutRouteParam = newUrl;\n return this;\n }\n\n /**\n * Appends a route parameter to the URL\n * @param newRouteParam - The route parameter to append\n * @returns This instance for method chaining\n */\n public setRouteParam(newRouteParam: string): this {\n this.url = `${this.urlWithOutRouteParam}/${newRouteParam}`;\n return this;\n }\n\n /**\n * Patches existing query parameters\n * @param value - Query parameters to merge\n * @returns This instance for method chaining\n */\n public patchQueryParams(value: PrimeNgTableStateHelperQueryParam): this {\n this.#queryParams = { ...this.#queryParams, ...value };\n return this;\n }\n\n /**\n * Removes a specific query parameter\n * @param key - The key to remove\n * @returns This instance for method chaining\n */\n public removeQueryParam(key: string): this {\n delete this.#queryParams[key];\n return this;\n }\n\n /**\n * Sets all query parameters (replaces existing)\n * @param newQueryParams - New query parameters\n * @returns This instance for method chaining\n */\n public setQueryParams(newQueryParams: PrimeNgTableStateHelperQueryParam): this {\n this.#queryParams = newQueryParams;\n return this;\n }\n\n /**\n * Handles PrimeNG table lazy load events\n * @param event - The lazy load event from PrimeNG table\n */\n public async onLazyLoad(event: TableLazyLoadEvent): Promise<void> {\n patchState(this.state, {\n size: event.rows || 15,\n page: Math.floor((event.first || 0) / (event.rows || 15)) + 1,\n filter: this.filterMapper(event.filters || {}),\n sort: Object.keys(event.multiSortMeta || {}).length > 0\n ? (event.multiSortMeta || []).map((sort: any) => ({\n field: sort.field,\n dir: (sort.order === 1 ? \"asc\" : \"desc\") as \"asc\" | \"desc\"\n }))\n : event.sortField\n ? [{\n field: event.sortField,\n dir: ((event.sortOrder || 1) === 1 ? \"asc\" : \"desc\") as \"asc\" | \"desc\"\n }]\n : []\n });\n\n await this.fetchData(this.dtoBuilder());\n }\n\n /**\n * Clears table data and resets to first page\n * @param table - Optional PrimeNG Table reference to reset\n */\n public async clearTableData(table?: Table): Promise<void> {\n patchState(this.state, {\n data: [],\n totalRecords: 0,\n page: 1,\n filter: [],\n sort: []\n });\n\n if (table) {\n table.reset();\n }\n\n await this.fetchData(this.dtoBuilder());\n }\n\n /**\n * Manually triggers data refresh with current state\n */\n public async refresh(): Promise<void> {\n await this.fetchData(this.dtoBuilder());\n }\n\n /**\n * Fetches data from the API\n */\n private async fetchData(dto: DynamicQueryDto): Promise<void> {\n try {\n patchState(this.state, { isLoading: true });\n\n const params = new URLSearchParams();\n Object.entries(this.#queryParams).forEach(([key, value]) => {\n params.append(key, String(value));\n });\n\n const urlWithParams = params.toString() \n ? `${this.url}?${params.toString()}`\n : this.url;\n\n const response = await firstValueFrom(\n this.httpClient.post(urlWithParams, dto, { context: new HttpContext().set(SkipLoadingSpinner, this.skipLoadingSpinner) })\n );\n\n const validatedResponse = dynamicQueryResponseZodSchema.parse(response);\n\n patchState(this.state, {\n data: validatedResponse.data,\n totalRecords: validatedResponse.last_row,\n isLoading: false\n });\n } catch (error) {\n console.error('Error fetching table data:', error);\n patchState(this.state, {\n data: [],\n totalRecords: 0,\n isLoading: false\n });\n }\n }\n\n /**\n * Builds the DTO for API requests\n */\n private dtoBuilder(): DynamicQueryDto {\n return {\n size: this.state.size(),\n page: this.state.page(),\n filter: this.state.filter(),\n sort: this.state.sort()\n };\n }\n\n /**\n * Maps PrimeNG filters to API filter format\n */\n private filterMapper(\n dto: Record<string, FilterMetadata | FilterMetadata[] | undefined>\n ): DynamicQueryFilterDto[] {\n const filters: DynamicQueryFilterDto[] = [];\n\n Object.entries(dto).forEach(([field, filterData]) => {\n if (!filterData) return;\n\n const processFilter = (filter: FilterMetadata) => {\n if (filter.value === null || filter.value === undefined || filter.value === '') return;\n\n const mappedType = this.evaluateInput(filter.matchMode || 'contains');\n if (mappedType) {\n filters.push({\n field,\n value: String(filter.value),\n type: mappedType\n });\n }\n };\n\n if (Array.isArray(filterData)) {\n filterData.forEach(processFilter);\n } else {\n processFilter(filterData);\n }\n });\n\n return filters;\n }\n\n /**\n * Maps PrimeNG filter match modes to API filter types\n */\n private evaluateInput(input: string): FilterTypeMapped | null {\n const filterMap: Record<string, FilterTypeMapped> = {\n startsWith: \"starts\",\n notStartsWith: \"!starts\",\n endsWith: \"ends\",\n notEndsWith: \"!ends\",\n contains: \"like\",\n notContains: \"!like\",\n equals: \"=\",\n notEquals: \"!=\",\n greaterThan: \">\",\n lessThan: \"<\",\n greaterThanOrEqual: \">=\",\n lessThanOrEqual: \"<=\"\n };\n\n return filterMap[input] || null;\n }\n}\n","import { HttpContextToken } from \"@angular/common/http\";\n\n/**\n * HTTP Context Token to skip loading spinner on HTTP requests\n * Usage: Set this token to true in HttpContext to skip showing loading spinner\n * \n * @example\n * ```typescript\n * const context = new HttpContext().set(SkipLoadingSpinner, true);\n * this.httpClient.get('/api/data', { context });\n * ```\n */\nexport const SkipLoadingSpinner = new HttpContextToken(() => false);\n","import { FilterMetadata } from 'primeng/api';\nimport { z } from 'zod';\n\n// ===============================================================================\n// TypeScript Utility Types\n// ===============================================================================\n\n/**\n * Makes all properties of T nullable (T | null)\n * @template T - The type to make nullable\n * @example\n * ```typescript\n * type User = { id: number; name: string; email: string };\n * type NullableUser = RecursiveNullable<User>;\n * // Result: { id: number | null; name: string | null; email: string | null }\n * ```\n */\nexport type RecursiveNullable<T> = {\n [P in keyof T]: T[P] | null;\n};\n\n/**\n * Represents a value that can be null or undefined\n * @template T - The base type\n * @example\n * ```typescript\n * type MaybeString = Nullish<string>; // string | null | undefined\n * ```\n */\nexport type Nullish<T> = T | null | undefined;\n\n/**\n * Makes all properties of T nullish (T | null | undefined) recursively\n * @template T - The type to make nullish\n * @example\n * ```typescript\n * type User = { id: number; profile: { name: string; age: number } };\n * type NullishUser = RecursiveNullish<User>;\n * // Result: { \n * // id: number | null | undefined; \n * // profile: { \n * // name: string | null | undefined; \n * // age: number | null | undefined \n * // } | null | undefined \n * // }\n * ```\n */\nexport type RecursiveNullish<T> = {\n [P in keyof T]: T[P] extends object\n ? RecursiveNullish<T[P]> | null | undefined\n : T[P] | null | undefined;\n};\n\n/**\n * Makes all properties optional recursively, useful for partial updates\n * @template T - The type to make recursively partial\n * @example\n * ```typescript\n * type User = { \n * id: number; \n * profile: { name: string; age: number }; \n * settings: { theme: string; notifications: boolean } \n * };\n * type PartialUser = RecursivePartial<User>;\n * // Result: { \n * // id?: number; \n * // profile?: { name?: string; age?: number }; \n * // settings?: { theme?: string; notifications?: boolean } \n * // }\n * ```\n */\nexport type RecursivePartial<T> = {\n [P in keyof T]?: T[P] extends object ? RecursivePartial<T[P]> : T[P];\n};\n\n// ===============================================================================\n// Core Data Types\n// ===============================================================================\n\n/**\n * Enumeration for manipulation types in component operations\n * Used for tracking the current operation state in component management\n * \n * @example\n * ```typescript\n * // In a component\n * currentOperation: ManipulationType = ManipulationType.Create;\n * \n * // Check operation type\n * if (this.currentOperation === ManipulationType.Update) {\n * // Handle update logic\n * }\n * ```\n */\nexport enum ManipulationType {\n /** Creating a new item */\n Create = \"Create\",\n /** Updating an existing item */\n Update = \"Update\", \n /** Creating a child item */\n CreateChild = \"Create Child\",\n /** Deleting an item */\n Delete = \"Delete\",\n /** Viewing item details */\n View = \"View\"\n}\n\n/**\n * Key-value pair type for common data structures\n * @template K The type of the key\n * @template D The type of the data\n */\nexport interface KeyData<K, D> {\n key: K;\n data: D;\n}\n\n/**\n * Common API response wrapper type\n * @template T The type of the data payload\n */\nexport interface ApiResponse<T> {\n data: T;\n message?: string;\n status: number;\n success: boolean;\n}\n\n/**\n * Pagination metadata interface\n */\nexport interface PaginationMeta {\n currentPage: number;\n totalPages: number;\n totalItems: number;\n itemsPerPage: number;\n hasNextPage: boolean;\n hasPreviousPage: boolean;\n}\n\n/**\n * Paginated response type\n * @template T The type of the data items\n */\nexport interface PaginatedResponse<T> {\n data: T[];\n meta: PaginationMeta;\n}\n\n/**\n * Query parameters for pagination\n */\nexport interface PaginationParams {\n page?: number;\n limit?: number;\n offset?: number;\n}\n\n/**\n * Common sort parameters\n */\nexport interface SortParams {\n sortBy?: string;\n sortOrder?: 'asc' | 'desc';\n}\n\n/**\n * Combined query parameters for API requests\n */\nexport type QueryParams = Record<string, string | number | boolean> & \n Partial<PaginationParams> & \n Partial<SortParams>;\n\n// ===============================================================================\n// Table State Types\n// ===============================================================================\n\n/**\n * String filter types for PrimeNG table filtering\n */\nexport type StringFilterType =\n | \"startsWith\"\n | \"notStartsWith\"\n | \"endsWith\"\n | \"notEndsWith\"\n | \"contains\"\n | \"notContains\";\n\n/**\n * Numeric filter types for PrimeNG table filtering\n */\nexport type NumericFilterType =\n | \"equals\"\n | \"notEquals\"\n | \"greaterThan\"\n | \"lessThan\"\n | \"greaterThanOrEqual\"\n | \"lessThanOrEqual\";\n\n/**\n * Boolean filter types for PrimeNG table filtering\n */\nexport type BooleanFilterType = Extract<NumericFilterType, \"equals\" | \"notEquals\">;\n\n/**\n * Combined filter types\n */\nexport type FilterType = StringFilterType | NumericFilterType;\n\n/**\n * Filter type mappings for backend API\n */\nexport type FilterTypeMapped =\n | \"starts\"\n | \"!starts\"\n | \"ends\"\n | \"!ends\"\n | \"like\"\n | \"!like\"\n | \"=\"\n | \"!=\"\n | \">\"\n | \"<\"\n | \">=\"\n | \"<=\";\n\n/**\n * PrimeNG table header configuration interface\n */\nexport interface PrimeNgTableHeader {\n identifier: {\n label?: string;\n field: string;\n hasSort?: boolean;\n isBoolean?: boolean;\n isNested?: boolean;\n isDate?: boolean;\n isDateTime?: boolean;\n styleClass?: string;\n };\n filter?: {\n type: \"text\" | \"numeric\" | \"boolean\" | \"date\" | \"dropdown\" | \"multiselect\";\n placeholder?: string;\n matchModeOptions?: any[];\n defaultMatchMode: FilterType;\n ariaLabel?: string;\n colspan?: number;\n styleClass?: Record<string, string>;\n };\n}\n\n/**\n * Dynamic query DTO interface\n */\nexport interface DynamicQueryDto {\n size: number;\n page: number;\n filter: DynamicQueryFilterDto[];\n sort: DynamicQuerySortDto[];\n}\n\n/**\n * Filter DTO for dynamic queries\n */\nexport interface DynamicQueryFilterDto {\n field: string;\n value: string;\n type: FilterTypeMapped;\n}\n\n/**\n * Sort DTO for dynamic queries\n */\nexport interface DynamicQuerySortDto {\n field: string;\n dir: \"asc\" | \"desc\";\n}\n\n/**\n * Paged data response interface\n */\nexport interface PagedDataResponse<T> {\n data: T[];\n last_page: number;\n last_row: number;\n}\n\n/**\n * Paged data response interface for simple pagination\n */\nexport interface SimplePagedDataResponse<T> {\n payload: T[];\n totalCount: number;\n}\n\n/**\n * Internal table state interface for dynamic table\n */\nexport interface PrimeNgTableState<T> {\n data: Array<T>;\n isLoading: boolean;\n size: number;\n page: number;\n totalRecords: number;\n filter: DynamicQueryFilterDto[];\n sort: DynamicQuerySortDto[];\n}\n\n/**\n * Internal state interface for paged table\n */\nexport interface PrimeNgPagedTableState<T> {\n data: Array<T>;\n isLoading: boolean;\n totalRecords: number;\n limit: number;\n page: number;\n}\n\n/**\n * Query DTO interface for paged data requests\n */\nexport interface PagedDataQueryDto {\n limit: number;\n page: number;\n}\n\n/**\n * Query parameters type for additional HTTP request parameters\n */\nexport type PrimeNgTableStateHelperQueryParam = Record<string, string | number | boolean>;\n\n// ===============================================================================\n// Zod Schemas\n// ===============================================================================\n\n/**\n * Zod schema for dynamic query response validation\n */\nexport const dynamicQueryResponseZodSchema = z.object({\n data: z.any().array(),\n last_page: z.number(),\n last_row: z.number()\n});\n\n/**\n * Zod schema for paged data response validation\n */\nexport const PagedDataResponseZodSchema = z.object({\n payload: z.any().array(),\n totalCount: z.number()\n});\n\n// ===============================================================================\n// Utility Functions and Type Guards\n// ===============================================================================\n\n/**\n * Error response interface\n */\nexport interface ErrorResponse {\n error: string;\n message: string;\n statusCode: number;\n timestamp: string;\n}\n\n/**\n * Creates a key-value pair object\n * @param key The key value\n * @param data The data value\n * @returns KeyData object\n */\nexport function createKeyData<K, D>(key: K, data: D): KeyData<K, D> {\n return { key, data };\n}\n\n/**\n * Type guard to check if a response is an API response\n * @param response The response to check\n * @returns true if response is ApiResponse, false otherwise\n */\nexport function isApiResponse<T>(response: any): response is ApiResponse<T> {\n return (\n typeof response === 'object' &&\n response !== null &&\n 'data' in response &&\n 'status' in response &&\n 'success' in response\n );\n}\n\n/**\n * Type guard to check if a response is paginated\n * @param response The response to check\n * @returns true if response is PaginatedResponse, false otherwise\n */\nexport function isPaginatedResponse<T>(response: any): response is PaginatedResponse<T> {\n return (\n typeof response === 'object' &&\n response !== null &&\n 'data' in response &&\n Array.isArray(response.data) &&\n 'meta' in response &&\n typeof response.meta === 'object'\n );\n}\n\n/**\n * Type guard to check if a response is a simple paged response\n * @param response The response to check\n * @returns true if response is SimplePagedDataResponse, false otherwise\n */\nexport function isSimplePagedResponse<T>(response: any): response is SimplePagedDataResponse<T> {\n return (\n typeof response === 'object' &&\n response !== null &&\n 'payload' in response &&\n Array.isArray(response.payload) &&\n 'totalCount' in response &&\n typeof response.totalCount === 'number'\n );\n}\n\n/**\n * Type guard to check if a response is a dynamic query response\n * @param response The response to check\n * @returns true if response is PagedDataResponse, false otherwise\n */\nexport function isDynamicQueryResponse<T>(response: any): response is PagedDataResponse<T> {\n return (\n typeof response === 'object' &&\n response !== null &&\n 'data' in response &&\n Array.isArray(response.data) &&\n 'last_page' in response &&\n 'last_row' in response\n );\n}\n","import { HttpClient, HttpContext } from '@angular/common/http';\nimport { signal, Signal } from '@angular/core';\nimport { signalState, patchState } from '@ngrx/signals';\nimport { Table, TableLazyLoadEvent } from 'primeng/table';\nimport { firstValueFrom } from 'rxjs';\n\nimport { SkipLoadingSpinner } from './http-context-tokens';\nimport {\n SimplePagedDataResponse,\n PrimeNgPagedTableState,\n PagedDataQueryDto,\n PrimeNgTableStateHelperQueryParam,\n PagedDataResponseZodSchema\n} from './types';\n\n/**\n * Initial state factory function for paged table\n */\nfunction initialPagedState<T>(): PrimeNgPagedTableState<T> {\n return {\n data: [],\n isLoading: false,\n totalRecords: 0,\n limit: 15,\n page: 1\n };\n}\n\n/**\n * Options for creating PrimengPagedDataTableStateHelper\n */\ntype PrimeNgPagedTableStateOpts = {\n url: string;\n httpClient: HttpClient;\n skipLoadingSpinner?: boolean;\n};\n\n/**\n * Simple paged data table state helper for basic pagination without filtering\n * \n * This helper provides basic table functionality including:\n * - Simple pagination (page and limit only)\n * - Basic state management with NgRx Signals\n * - API integration for paged data\n * - Route parameter support\n * - Query parameter management\n * \n * Use this when you need simple pagination without complex filtering and sorting.\n * For advanced features, use PrimeNgDynamicTableStateHelper instead.\n * \n * @example\n * ```typescript\n * const tableState = PrimengPagedDataTableStateHelper.create<Product>({\n * url: '/api/products',\n * httpClient: this.httpClient\n * });\n * \n * // In template\n * <p-table [value]=\"tableState.data()\"\n * [lazy]=\"true\"\n * [loading]=\"tableState.isLoading()\"\n * [totalRecords]=\"tableState.totalRecords()\"\n * (onLazyLoad)=\"tableState.onLazyLoad($event)\">\n * </p-table>\n * ```\n */\nexport class PrimengPagedDataTableStateHelper<T> {\n readonly #state = signalState<PrimeNgPagedTableState<T>>(initialPagedState<T>());\n private urlWithOutRouteParam: string;\n private skipLoadingSpinner: boolean;\n readonly #uniqueKey = signal(\"id\");\n readonly uniqueKey = this.#uniqueKey.asReadonly();\n #queryParams: PrimeNgTableStateHelperQueryParam = {};\n\n // Public readonly signals\n readonly totalRecords: Signal<number> = this.#state.totalRecords;\n readonly isLoading: Signal<boolean> = this.#state.isLoading;\n readonly data: Signal<Array<T>> = this.#state.data;\n readonly currentPage = this.#state.page;\n readonly currentPageSize = this.#state.limit;\n\n private constructor(\n private url: string,\n private readonly httpClient: HttpClient,\n skipLoadingSpinner: boolean = true\n ) {\n this.urlWithOutRouteParam = url;\n this.skipLoadingSpinner = skipLoadingSpinner;\n }\n\n /**\n * Creates a new instance of PrimengPagedDataTableStateHelper\n * @param option - Configuration options\n * @returns New instance of PrimengPagedDataTableStateHelper\n */\n public static create<T>(option: PrimeNgPagedTableStateOpts): PrimengPagedDataTableStateHelper<T> {\n return new PrimengPagedDataTableStateHelper<T>(option.url, option.httpClient, option.skipLoadingSpinner ?? true);\n }\n\n /**\n * Creates a new instance without initial URL (can be set later)\n * @param option - Configuration options without URL\n * @returns New instance of PrimengPagedDataTableStateHelper\n */\n public static createWithBlankUrl<T>(\n option: Omit<PrimeNgPagedTableStateOpts, \"url\">\n ): PrimengPagedDataTableStateHelper<T> {\n return new PrimengPagedDataTableStateHelper<T>(\"\", option.httpClient, option.skipLoadingSpinner ?? true);\n }\n\n /**\n * Sets whether to skip the loading spinner\n * @param skip - Whether to skip the loading spinner\n * @returns This instance for method chaining\n */\n public setSkipLoadingSpinner(skip: boolean): this {\n this.skipLoadingSpinner = skip;\n return this;\n }\n\n /**\n * Sets the unique key field for table rows\n * @param newUniqueKey - The field name to use as unique identifier\n * @returns This instance for method chaining\n */\n public setUniqueKey(newUniqueKey: string): this {\n this.#uniqueKey.set(newUniqueKey);\n return this;\n }\n\n /**\n * Updates the API URL\n * @param newUrl - The new API URL\n * @returns This instance for method chaining\n */\n public setUrl(newUrl: string): this {\n this.url = newUrl;\n this.urlWithOutRouteParam = newUrl;\n return this;\n }\n\n /**\n * Appends a route parameter to the URL\n * @param newRouteParam - The route parameter to append\n * @returns This instance for method chaining\n */\n public setRouteParam(newRouteParam: string): this {\n this.url = `${this.urlWithOutRouteParam}/${newRouteParam}`;\n return this;\n }\n\n /**\n * Patches existing query parameters\n * @param value - Query parameters to merge\n * @returns This instance for method chaining\n */\n public patchQueryParams(value: PrimeNgTableStateHelperQueryParam): this {\n this.#queryParams = { ...this.#queryParams, ...value };\n return this;\n }\n\n /**\n * Removes a specific query parameter\n * @param key - The key to remove\n * @returns This instance for method chaining\n */\n public removeQueryParam(key: string): this {\n delete this.#queryParams[key];\n return this;\n }\n\n /**\n * Removes all query parameters\n * @returns This instance for method chaining\n */\n public removeAllQueryParams(): this {\n this.#queryParams = {};\n return this;\n }\n\n /**\n * Sets all query parameters (replaces existing)\n * @param newQueryParams - New query parameters\n * @returns This instance for method chaining\n */\n public setQueryParams(newQueryParams: PrimeNgTableStateHelperQueryParam): this {\n this.#queryParams = newQueryParams;\n return this;\n }\n\n /**\n * Handles PrimeNG table lazy load events\n * @param event - The lazy load event from PrimeNG table\n */\n public async onLazyLoad(event: TableLazyLoadEvent): Promise<void> {\n const newPage = Math.floor((event.first || 0) / (event.rows || 15)) + 1;\n const newLimit = event.rows || 15;\n\n patchState(this.#state, {\n limit: newLimit,\n page: newPage\n });\n\n await this.fetchData(this.dtoBuilder());\n }\n\n /**\n * Clears table data and resets to first page\n * @param table - Optional PrimeNG Table reference to reset\n */\n public async clearTableData(table?: Table): Promise<void> {\n patchState(this.#state, {\n data: [],\n totalRecords: 0,\n page: 1\n });\n\n if (table) {\n table.reset();\n }\n\n await this.fetchData(this.dtoBuilder());\n }\n\n /**\n * Manually triggers data refresh with current state\n */\n public async refresh(): Promise<void> {\n await this.fetchData(this.dtoBuilder());\n }\n\n /**\n * Fetches data from the API\n */\n private async fetchData(dto: PagedDataQueryDto): Promise<void> {\n try {\n patchState(this.#state, { isLoading: true });\n\n const params = new URLSearchParams();\n Object.entries(this.#queryParams).forEach(([key, value]) => {\n params.append(key, String(value));\n });\n Object.entries(dto).forEach(([key, value]) => {\n params.append(key, String(value));\n });\n\n const urlWithParams = params.toString() \n ? `${this.url}?${params.toString()}`\n : this.url;\n\n const response = await firstValueFrom(\n this.httpClient.get(urlWithParams, { context: new HttpContext().set(SkipLoadingSpinner, this.skipLoadingSpinner) })\n );\n\n const validatedResponse = PagedDataResponseZodSchema.parse(response);\n\n patchState(this.#state, {\n data: validatedResponse.payload,\n totalRecords: validatedResponse.totalCount,\n isLoading: false\n });\n } catch (error) {\n console.error('Error fetching paged data:', error);\n patchState(this.#state, {\n data: [],\n totalRecords: 0,\n isLoading: false\n });\n }\n }\n\n /**\n * Builds the DTO for API requests\n */\n private dtoBuilder(): PagedDataQueryDto {\n return {\n limit: this.#state.limit(),\n page: this.#state.page()\n };\n }\n}\n","import { SelectItem } from \"primeng/api\";\nimport { \n StringFilterType, \n NumericFilterType, \n PrimeNgTableHeader \n} from \"./types\";\n\n/**\n * Creates PrimeNG SelectItem array for numeric filter match modes\n * @param styleClass - CSS class for styling the options\n * @param disabled - Whether the options should be disabled\n * @returns Array of SelectItem for numeric filters\n */\nexport function createPrimengNumberMatchModes(\n styleClass: string = \"p-text-capitalize\",\n disabled: boolean = false\n): SelectItem<NumericFilterType>[] {\n return [\n {\n label: \"Equals\",\n value: \"equals\",\n title: \"Equals\",\n styleClass: styleClass,\n disabled: disabled\n },\n {\n label: \"Not Equals\",\n value: \"notEquals\",\n title: \"Not Equals\",\n styleClass: styleClass,\n disabled: disabled\n },\n {\n label: \"Greater Than\",\n value: \"greaterThan\",\n title: \"Greater Than\",\n styleClass: styleClass,\n disabled: disabled\n },\n {\n label: \"Greater Than Or Equals\",\n value: \"greaterThanOrEqual\",\n title: \"Greater Than Or Equals\",\n styleClass: styleClass,\n disabled: disabled\n },\n {\n label: \"Less Than\",\n value: \"lessThan\",\n title: \"Less Than\",\n styleClass: styleClass,\n disabled: disabled\n },\n {\n label: \"Less Than Or Equals\",\n value: \"lessThanOrEqual\",\n title: \"Less Than Or Equals\",\n styleClass: styleClass,\n disabled: disabled\n }\n ];\n}\n\n/**\n * Creates PrimeNG SelectItem array for string filter match modes\n * @param styleClass - CSS class for styling the options\n * @param disabled - Whether the options should be disabled\n * @returns Array of SelectItem for string filters\n */\nexport function createPrimengStringMatchModes(\n styleClass: string = \"p-text-capitalize\",\n disabled: boolean = false\n): SelectItem<StringFilterType>[] {\n return [\n {\n label: \"Contains\",\n value: \"contains\",\n title: \"Contains\",\n styleClass: styleClass,\n disabled: disabled\n },\n {\n label: \"Not Contains\",\n value: \"notContains\",\n title: \"Not Contains\",\n styleClass: styleClass,\n disabled: disabled\n },\n {\n label: \"Starts With\",\n value: \"startsWith\",\n title: \"Starts With\",\n styleClass: styleClass,\n disabled: disabled\n },\n {\n label: \"Not Starts With\",\n value: \"notStartsWith\",\n title: \"Not Starts With\",\n styleClass: styleClass,\n disabled: disabled\n },\n {\n label: \"Ends With\",\n value: \"endsWith\",\n title: \"Ends With\",\n styleClass: styleClass,\n disabled: disabled\n },\n {\n label: \"Not Ends With\",\n value: \"notEndsWith\",\n title: \"Not Ends With\",\n styleClass: styleClass,\n disabled: disabled\n }\n ];\n}\n\n/**\n * Creates a complete table header configuration for text columns\n * @param field - The field name for the column\n * @param label - Display label for the column header\n * @param options - Additional configuration options\n * @returns Complete PrimeNgTableHeader configuration\n */\nexport function createTextColumn(\n field: string,\n label: string,\n options: {\n hasSort?: boolean;\n hasFilter?: boolean;\n placeholder?: string;\n matchModeOptions?: SelectItem<StringFilterType>[];\n defaultMatchMode?: StringFilterType;\n styleClass?: string;\n filterStyleClass?: Record<string, string>;\n } = {}\n): PrimeNgTableHeader {\n const header: PrimeNgTableHeader = {\n identifier: {\n label,\n field,\n hasSort: options.hasSort ?? false,\n styleClass: options.styleClass\n }\n };\n\n if (options.hasFilter ?? false) {\n header.filter = {\n type: \"text\",\n placeholder: options.placeholder ?? `Search by ${label.toLowerCase()}`,\n matchModeOptions: options.matchModeOptions ?? createPrimengStringMatchModes(),\n defaultMatchMode: options.defaultMatchMode ?? \"contains\",\n ariaLabel: `Filter by ${label}`,\n styleClass: options.filterStyleClass\n };\n }\n\n return header;\n}\n\n/**\n * Creates a complete table header configuration for numeric columns\n * @param field - The field name for the column\n * @param label - Display label for the column header\n * @param options - Additional configuration options\n * @returns Complete PrimeNgTableHeader configuration\n */\nexport function createNumericColumn(\n field: string,\n label: string,\n options: {\n hasSort?: boolean;\n hasFilter?: boolean;\n placeholder?: string;\n matchModeOptions?: SelectItem<NumericFilterType>[];\n defaultMatchMode?: NumericFilterType;\n styleClass?: string;\n filterStyleClass?: Record<string, string>;\n } = {}\n): PrimeNgTableHeader {\n const header: PrimeNgTableHeader = {\n identifier: {\n label,\n field,\n hasSort: options.hasSort ?? false,\n styleClass: options.styleClass\n }\n };\n\n if (options.hasFilter ?? false) {\n header.filter = {\n type: \"numeric\",\n placeholder: options.placeholder ?? `Filter by ${label.toLowerCase()}`,\n matchModeOptions: options.matchModeOptions ?? createPrimengNumberMatchModes(),\n defaultMatchMode: options.defaultMatchMode ?? \"equals\",\n ariaLabel: `Filter by ${label}`,\n styleClass: options.filterStyleClass\n };\n }\n\n return header;\n}\n\n/**\n * Creates a complete table header configuration for boolean columns\n * @param field - The field name for the column\n * @param label - Display label for the column header\n * @param options - Additional configuration options\n * @returns Complete PrimeNgTableHeader configuration\n */\nexport function createBooleanColumn(\n field: string,\n label: string,\n options: {\n hasSort?: boolean;\n hasFilter?: boolean;\n styleClass?: string;\n filterStyleClass?: Record<string, string>;\n } = {}\n): PrimeNgTableHeader {\n const header: PrimeNgTableHeader = {\n identifier: {\n label,\n field,\n hasSort: options.hasSort ?? false,\n isBoolean: true,\n styleClass: options.styleClass\n }\n };\n\n if (options.hasFilter ?? false) {\n header.filter = {\n type: \"boolean\",\n defaultMatchMode: \"equals\",\n ariaLabel: `Filter by ${label}`,\n styleClass: options.filterStyleClass\n };\n }\n\n return header;\n}\n\n/**\n * Creates a complete table header configuration for date columns\n * @param field - The field name for the column\n * @param label - Display label for the column header\n * @param options - Additional configuration options\n * @returns Complete PrimeNgTableHeader configuration\n */\nexport function createDateColumn(\n field: string,\n label: string,\n options: {\n hasSort?: boolean;\n hasFilter?: boolean;\n placeholder?: string;\n styleClass?: string;\n filterStyleClass?: Record<string, string>;\n } = {}\n): PrimeNgTableHeader {\n const header: PrimeNgTableHeader = {\n identifier: {\n label,\n field,\n hasSort: options.hasSort ?? false,\n styleClass: options.styleClass\n }\n };\n\n if (options.hasFilter ?? false) {\n header.filter = {\n type: \"date\",\n placeholder: options.placeholder ?? `Select ${label.toLowerCase()}`,\n defaultMatchMode: \"equals\",\n ariaLabel: `Filter by ${label}`,\n styleClass: options.filterStyleClass\n };\n }\n\n return header;\n}\n\n/**\n * Creates a complete table header configuration for dropdown columns\n * @param field - The field name for the column\n * @param label - Display label for the column header\n * @param dropdownOptions - Options for the dropdown filter\n * @param options - Additional configuration options\n * @returns Complete PrimeNgTableHeader configuration\n */\nexport function createDropdownColumn(\n field: string,\n label: string,\n dropdownOptions: SelectItem[],\n options: {\n hasSort?: boolean;\n hasFilter?: boolean;\n placeholder?: string;\n styleClass?: string;\n filterStyleClass?: Record<string, string>;\n } = {}\n): PrimeNgTableHeader {\n const header: PrimeNgTableHeader = {\n identifier: {\n label,\n field,\n hasSort: options.hasSort ?? false,\n styleClass: options.styleClass\n }\n };\n\n if (options.hasFilter ?? false) {\n header.filter = {\n type: \"dropdown\",\n placeholder: options.placeholder ?? `Select ${label.toLowerCase()}`,\n matchModeOptions: dropdownOptions,\n defaultMatchMode: \"equals\",\n ariaLabel: `Filter by ${label}`,\n styleClass: options.filterStyleClass\n };\n }\n\n return header;\n}\n\n/**\n * Creates a complete table header configuration for multiselect columns\n * @param field - The field name for the column\n * @param label - Display label for the column header\n * @param multiselectOptions - Options for the multiselect filter\n * @param options - Additional configuration options\n * @returns Complete PrimeNgTableHeader configuration\n */\nexport function createMultiselectColumn(\n field: string,\n label: string,\n multiselectOptions: SelectItem[],\n options: {\n hasSort?: boolean;\n hasFilter?: boolean;\n placeholder?: string;\n styleClass?: string;\n filterStyleClass?: Record<string, string>;\n } = {}\n): PrimeNgTableHeader {\n const header: PrimeNgTableHeader = {\n identifier: {\n label,\n field,\n hasSort: options.hasSort ?? false,\n styleClass: options.styleClass\n }\n };\n\n if (options.hasFilter ?? false) {\n header.filter = {\n type: \"multiselect\",\n placeholder: options.placeholder ?? `Select ${label.toLowerCase()}`,\n matchModeOptions: multiselectOptions,\n defaultMatchMode: \"equals\",\n ariaLabel: `Filter by ${label}`,\n styleClass: options.filterStyleClass\n };\n }\n\n return header;\n}\n\n/**\n * Creates a simple table header configuration without filtering\n * @param field - The field name for the column\n * @param label - Display label for the column header\n * @param options - Additional configuration options\n * @returns Simple PrimeNgTableHeader configuration\n */\nexport function createSimpleColumn(\n field: string,\n label: string,\n options: {\n hasSort?: boolean;\n styleClass?: string;\n } = {}\n): PrimeNgTableHeader {\n return {\n identifier: {\n label,\n field,\n hasSort: options.hasSort ?? false,\n styleClass: options.styleClass\n }\n };\n}\n\n/**\n * Utility function to merge multiple table header configurations\n * @param headers - Array of table header configurations\n * @returns Array of merged headers\n */\nexport function mergeTableHeaders(...headers: PrimeNgTableHeader[]): PrimeNgTableHeader[] {\n return headers;\n}\n\n/**\n * Utility function to create boolean SelectItem options\n * @param trueLabel - Label for true value\n * @param falseLabel - Label for false value\n * @returns Array of SelectItem for boolean values\n */\nexport function createBooleanSelectItems(\n trueLabel: string = \"Yes\",\n falseLabel: string = \"No\"\n): SelectItem[] {\n return [\n { label: trueLabel, value: true },\n { label: falseLabel, value: false }\n ];\n}\n\n/**\n * Utility function to create status SelectItem options\n * @param statusOptions - Object mapping status values to labels\n * @returns Array of SelectItem for status values\n */\nexport function createStatusSelectItems(\n statusOptions: Record<string | number, string>\n): SelectItem[] {\n return Object.entries(statusOptions).map(([value, label]) => ({\n label,\n value: isNaN(Number(value)) ? value : Number(value)\n }));\n}\n","/**\n * Utility function to remove null and undefined values from an object\n * \n * This is particularly useful when setting query parameters, as null/undefined\n * values should typically be filtered out before sending to APIs.\n * \n * @param o The object to clean\n * @returns A new object with null and undefined values removed\n * \n * @example\n * ```typescript\n * const queryParams = {\n * name: 'John',\n * age: null,\n * email: 'john@example.com',\n * phone: undefined\n * };\n * \n * const cleaned = cleanNullishFromObject(queryParams);\n * // Result: { name: 'John', email: 'john@example.com' }\n * \n * // Use case with table state\n * this.tableState.setQueryParams(cleanNullishFromObject(queryParams));\n * ```\n */\nexport function cleanNullishFromObject(o: object): Record<string, any> {\n return Object.fromEntries(Object.entries(o).filter(([, v]) => v != null));\n}\n","import { signal } from \"@angular/core\";\nimport { HttpClient, HttpContext } from \"@angular/common/http\";\nimport { firstValueFrom } from \"rxjs\";\nimport { SkipLoadingSpinner } from \"./http-context-tokens\";\n\n/**\n * A generic class for memoizing data storage with HTTP caching capabilities\n * Provides methods to load and cache single data objects or arrays with automatic loading states\n * \n * @template T The type of data to be stored and managed\n * \n * @example\n * ```typescript\n * interface User { id: number; name: string; }\n * \n * const userStorage = new MemoizedDataStorage<User>(httpClient);\n * await userStorage.loadSingleData('/api/user/1');\n * console.log(userStorage.singleData()); // User data or null\n * \n * const usersStorage = new MemoizedDataStorage<User>(httpClient);\n * await usersStorage.loadMultipleData('/api/users');\n * console.log(usersStorage.multipleData()); // Array of User data\n * ```\n */\nexport class MemoizedDataStorage<T> {\n private skipLoadingSpinner: boolean = true;\n\n /**\n * Creates a new instance of MemoizedDataStorage\n * @param httpClient Angular HttpClient instance for making HTTP requests\n * @param skipLoadingSpinner Whether to skip the loading spinner for HTTP requests\n */\n constructor(readonly httpClient: HttpClient, skipLoadingSpinner: boolean = true) {\n this.skipLoadingSpinner = skipLoadingSpinner;\n }\n\n /**\n * Sets whether to skip the loading spinner for HTTP requests\n * @param skip Whether to skip the loading spinner\n * @returns This instance for method chaining\n */\n setSkipLoadingSpinner(skip: boolean): this {\n this.skipLoadingSpinner = skip;\n return this;\n }\n readonly #singleData = signal<T | null>(null);\n readonly #multipleData = signal<Array<T>>([]);\n readonly #isLoading = signal<boolean>(false);\n\n // Public readonly signals for external consumption\n /**\n * Read-only signal containing single data object or null\n */\n readonly singleData = this.#singleData.asReadonly();\n\n /**\n * Read-only signal containing array of data objects\n */\n readonly multipleData = this.#multipleData.asReadonly();\n\n /**\n * Read-only signal indicating whether a request is currently loading\n */\n readonly isLoading = this.#isLoading.asReadonly();\n\n // Private flag to control memoization behavior\n #isMemoizationDisabledOnNextRead = false;\n\n /**\n * Disables memoization for the next read operation and clears cached data\n * This forces the next loadSingleData or loadMultipleData call to fetch fresh data\n * \n * @example\n * ```typescript\n * const storage = new MemoizedDataStorage<User>(httpClient);\n * await storage.loadSingleData('/api/user/1'); // Fetches data\n * await storage.loadSingleData('/api/user/1'); // Returns cached data\n * \n * storage.disableMemoizationOnNextRead();\n * await storage.loadSingleData('/api/user/1'); // Fetches fresh data\n * ```\n */\n disableMemoizationOnNextRead(): void {\n this.#isMemoizationDisabledOnNextRead = true;\n this.#singleData.set(null);\n this.#multipleData.set([]);\n }\n\n /**\n * Loads a single data object from the specified URL with optional query parameters\n * Uses memoization to avoid redundant requests unless explicitly disabled\n * \n * @param url The URL to fetch data from\n * @param queryParams Optional query parameters to include in the request\n * @returns Promise that resolves when the data is loaded\n * @throws Error if the HTTP request fails\n * \n * @example\n * ```typescript\n * const storage = new MemoizedDataStorage<User>(httpClient);\n * await storage.loadSingleData('/api/user/1', { include: 'profile' });\n * const user = storage.singleData(); // User data or null\n * ```\n */\n async loadSingleData(\n url: string,\n queryParams: Record<string, string | number> = {}\n ): Promise<void> {\n // Skip loading if data is already cached and memoization is enabled\n if (!this.#isMemoizationDisabledOnNextRead && this.#singleData() !== null) {\n return;\n }\n\n try {\n this.#isLoading.set(true);\n\n const data = await firstValueFrom(\n this.httpClient.get<T>(url, {\n params: queryParams,\n context: new HttpContext().set(SkipLoadingSpinner, this.skipLoadingSpinner)\n })\n );\n this.#singleData.set(data);\n } catch (error) {\n this.#singleData.set(null);\n throw error;\n } finally {\n this.#isLoading.set(false);\n this.#isMemoizationDisabledOnNextRead = false;\n }\n }\n\n /**\n * Loads multiple data objects from the specified URL with optional query parameters\n * Uses memoization to avoid redundant requests unless explicitly disabled\n * \n * @param url The URL to fetch data from\n * @param queryParams Optional query parameters to include in the request\n * @returns Promise that resolves when the data is loaded\n * @throws Error if the HTTP request fails\n * \n * @example\n * ```typescript\n * const storage = new MemoizedDataStorage<User>(httpClient);\n * await storage.loadMultipleData('/api/users', { page: 1, limit: 10 });\n * const users = storage.multipleData(); // Array of User data\n * ```\n */\n async loadMultipleData(\n url: string,\n queryParams: Record<string, string | number> = {}\n ): Promise<void> {\n // Skip loading if data is already cached and memoization is enabled\n if (\n !this.#isMemoizationDisabledOnNextRead &&\n this.#multipleData().length !== 0\n ) {\n return;\n }\n\n try {\n this.#isLoading.set(true);\n \n const context = new HttpContext();\n if (this.skipLoadingSpinner) {\n context.set(SkipLoadingSpinner, true);\n }\n\n const data = await firstValueFrom(\n this.httpClient.get<Array<T>>(url, {\n params: queryParams,\n context\n })\n );\n this.#multipleData.set(Array.isArray(data) ? data : []);\n } catch (error) {\n this.#multipleData.set([]);\n throw error;\n } finally {\n this.#isLoading.set(false);\n this.#isMemoizationDisabledOnNextRead = false;\n }\n }\n\n /**\n * Clears all cached data and resets the storage to initial state\n * \n * @example\n * ```typescript\n * const storage = new MemoizedDataStorage<User>(httpClient);\n * await storage.loadSingleData('/api/user/1');\n * storage.clear(); // Clears cached data\n * console.log(storage.singleData()); // null\n * console.log(storage.multipleData()); // []\n * ```\n */\n clear(): void {\n this.#singleData.set(null);\n this.#multipleData.set([]);\n this.#isMemoizationDisabledOnNextRead = false;\n }\n\n /**\n * Checks if single data is currently cached\n * @returns true if single data is cached, false otherwise\n */\n hasSingleData(): boolean {\n return this.#singleData() !== null;\n }\n\n /**\n * Checks if multiple data is currently cached\n * @returns true if multiple data is cached (non-empty array), false otherwise\n */\n hasMultipleData(): boolean {\n return this.#multipleData().length > 0;\n }\n}\n","import { computed, signal } from \"@angular/core\";\nimport { ManipulationType } from \"./types\";\n\n/**\n * A reactive state management class for Angular components using signals\n * Provides common component state properties and computed values\n * \n * @example\n * ```typescript\n * @Component({\n * selector: 'app-user-management',\n * template: `\n * <h2>{{ componentState.componentTitleWithManipulationType() }}</h2>\n * <p-button \n * [loading]=\"componentState.isAnyAjaxOperationRunning()\"\n * [disabled]=\"componentState.isAnyAjaxOperationRunning()\">\n * Save\n * </p-button>\n * `\n * })\n * export class UserManagementComponent {\n * componentState = new ComponentState()\n * .updateComponentTitle('User')\n * .updateCheckBoxSelectionStatus(true);\n * }\n * ```\n */\nexport class ComponentState {\n readonly isAjaxDataIncoming = signal<boolean>(false);\n readonly enableCheckBoxSelection = signal<boolean>(false);\n readonly isSelectableRowEnabled = signal<boolean>(false);\n readonly isAjaxRequestOutgoing = signal<boolean>(false);\n readonly hasMultipleSelection = signal<boolean>(false);\n readonly isCreateOrUpdateDialogOpen = signal<boolean>(false);\n readonly isUpdateDialogOpen = signal<boolean>(false);\n readonly isCreateDialogOpen = signal<boolean>(false);\n readonly manipulationType = signal<ManipulationType>(ManipulationType.Create);\n readonly componentTitle = signal<string>(\"\");\n\n /**\n * Updates the component title\n * @param componentTitle - The new title for the component\n * @returns This instance for method chaining\n */\n updateComponentTitle = (componentTitle: string) => {\n this.componentTitle.set(componentTitle);\n return this;\n };\n\n /**\n * Updates the multiple selection status\n * @param newStatus - Whether multiple selection is enabled\n * @returns This instance for method chaining\n */\n updateMultipleSelectionStatus = (newStatus: boolean) => {\n this.hasMultipleSelection.set(newStatus);\n return this;\n };\n\n /**\n * Updates the checkbox selection status\n * @param newStatus - Whether checkbox selection is enabled\n * @returns This instance for method chaining\n */\n updateCheckBoxSelectionStatus = (newStatus: boolean) => {\n this.enableCheckBoxSelection.set(newStatus);\n return this;\n };\n\n /**\n * Updates the selectable row status\n * @param newStatus - Whether row selection is enabled\n * @returns This instance for method chaining\n */\n updateSelectableRowStatus = (newStatus: boolean) => {\n this.isSelectableRowEnabled.set(newStatus);\n return this;\n };\n\n /**\n * Updates the manipulation type (Create, Update, Delete, View)\n * @param type - The manipulation type\n * @returns This instance for method chaining\n */\n updateManipulationType = (type: ManipulationType) => {\n this.manipulationType.set(type);\n return this;\n };\n\n /**\n * Sets the incoming Ajax data status\n * @param status - Whether Ajax data is incoming\n * @returns This instance for method chaining\n */\n setAjaxDataIncoming = (status: boolean) => {\n this.isAjaxDataIncoming.set(status);\n return this;\n };\n\n /**\n * Sets the outgoing Ajax request status\n * @param status - Whether Ajax request is outgoing\n * @returns This instance for method chaining\n */\n setAjaxRequestOutgoing = (status: boolean) => {\n this.isAjaxRequestOutgoing.set(status);\n return this;\n };\n\n /**\n * Sets the create or update dialog open status\n * @param status - Whether the dialog is open\n * @returns This instance for method chaining\n */\n setCreateOrUpdateDialogOpen = (status: boolean) => {\n this.isCreateOrUpdateDialogOpen.set(status);\n return this;\n };\n\n /**\n * Sets the update dialog open status\n * @param status - Whether the update dialog is open\n * @returns This instance for method chaining\n */\n setUpdateDialogOpen = (status: boolean) => {\n this.isUpdateDialogOpen.set(status);\n return this;\n };\n\n /**\n * Sets the create dialog open status\n * @param status - Whether the create dialog is open\n * @returns This instance for method chaining\n */\n setCreateDialogOpen = (status: boolean) => {\n this.isCreateDialogOpen.set(status);\n return this;\n };\n\n /**\n * Computed signal that combines component title with manipulation type\n */\n readonly componentTitleWithManipulationType = computed(() => {\n return this.manipulationType() + \" \" + this.componentTitle();\n });\n\n /**\n * Computed signal that indicates if component is in update state\n */\n readonly isOnUpdateState = computed(() => {\n return this.manipulationType() === ManipulationType.Update;\n });\n\n /**\n * Computed signal that indicates if component is in create state\n */\n readonly isOnCreateState = computed(() => {\n return this.manipulationType() === ManipulationType.Create;\n });\n\n /**\n * Computed signal that indicates if component is in delete state\n */\n readonly isOnDeleteState = computed(() => {\n return this.manipulationType() === ManipulationType.Delete;\n });\n\n /**\n * Computed signal that indicates if component is in view state\n */\n readonly isOnViewState = computed(() => {\n return this.manipulationType() === ManipulationType.View;\n });\n\n /**\n * Computed signal that indicates if any Ajax operation is currently running\n */\n readonly isAnyAjaxOperationRunning = computed(() => {\n return this.isAjaxDataIncoming() || this.isAjaxRequestOutgoing();\n });\n\n /**\n * Computed signal that indicates if any dialog is open\n */\n readonly isAnyDialogOpen = computed(() => {\n return this.isCreateOrUpdateDialogOpen() || this.isUpdateDialogOpen() || this.isCreateDialogOpen();\n });\n\n /**\n * Resets all state to default values\n * @returns This instance for method chaining\n */\n reset = () => {\n this.isAjaxDataIncoming.set(false);\n this.enableCheckBoxSelection.set(false);\n this.isSelectableRowEnabled.set(false);\n this.isAjaxRequestOutgoing.set(false);\n this.hasMultipleSelection.set(false);\n this.isCreateOrUpdateDialogOpen.set(false);\n this.isUpdateDialogOpen.set(false);\n this.isCreateDialogOpen.set(false);\n this.manipulationType.set(ManipulationType.Create);\n this.componentTitle.set(\"\");\n return this;\n };\n}\n","import { signal } from \"@angular/core\";\n\n/**\n * A generic component data storage class using Angular signals\n * Provides reactive data management for both single objects and arrays\n * \n * @template T The type of data to be stored and managed\n * \n * @example\n * ```typescript\n * interface User {\n * id: number;\n * name: string;\n * email: string;\n * }\n * \n * @Component({\n * selector: 'app-user-list',\n * template: `\n * <!-- Single user display -->\n * @if (dataStorage.singleData(); as user) {\n * <div>\n * <h3>{{ user.name }}</h3>\n * <p>{{ user.email }}</p>\n * </div>\n * }\n * \n * <!-- Multiple users display -->\n * @for (user of dataStorage.multipleData(); track user.id) {\n * <div>{{ user.name }} - {{ user.email }}</div>\n * }\n * `\n * })\n * export class UserListComponent {\n * dataStorage = new ComponentDataStorage<User>();\n * \n * ngOnInit() {\n * // Set initial data\n * this.dataStorage\n * .updateSingleData({ id: 1, name: 'John', email: 'john@example.com' })\n * .updateMultipleData([\n * { id: 1, name: 'John', email: 'john@example.com' },\n * { id: 2, name: 'Jane', email: 'jane@example.com' }\n * ]);\n * }\n * }\n * ```\n */\nexport class ComponentDataStorage<T> {\n readonly singleData = signal<T | null>(null);\n readonly multipleData = signal<Array<T>>([]);\n\n /**\n * Patches multiple data by appending new data to the existing array\n * @param newData - Array of new data to append\n * @returns This instance for method chaining\n * \n * @example\n * ```typescript\n * const storage = new ComponentDataStorage<User>();\n * storage.updateMultipleData([{ id: 1, name: 'John' }]);\n * storage.patchMultipleData([{ id: 2, name: 'Jane' }]);\n * // Result: [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }]\n * ```\n */\n public patchMultipleData(newData: Array<T>) {\n this.multipleData.update((prevData) => {\n return [...prevData, ...newData];\n }); \n\n return this;\n }\n\n /**\n * Patches single data by merging new properties with existing data\n * If no existing data, creates new object with provided data\n * @param newData - Partial data to merge with existing single data\n * @returns This instance for method chaining\n * \n * @example\n * ```typescript\n * const storage = new ComponentDataStorage<User>();\n * storage.updateSingleData({ id: 1, name: 'John', email: 'john@example.com' });\n * storage.patchSingleData({ email: 'john.doe@example.com' });\n * // Result: { id: 1, name: 'John', email: 'john.doe@example.com' }\n * ```\n */\n public patchSingleData(newData: Partial<T>) {\n this.singleData.update((prev) => prev ? { ...prev, ...newData } : { ...newData } as T);\n return this;\n }\n\n /**\n * Replaces the entire multiple data array\n * @param newData - New array of data to replace existing data\n * @returns This instance for method chaining\n */\n public updateMultipleData(newData: Array<T>) {\n this.multipleData.set(newData);\n return this;\n }\n\n /**\n * Replaces the single data object\n * @param newData - New data object or null to replace existing data\n * @returns This instance for method chaining\n */\n public updateSingleData(newData: T | null) {\n this.singleData.set(newData);\n return this;\n }\n\n /**\n * Adds a single item to the multiple data array\n * @param item - Single item to add to the array\n * @returns This instance for method chaining\n */\n public addToMultipleData(item: T) {\n this.multipleData.update(prevData => [...prevData, item]);\n return this;\n }\n\n /**\n * Removes an item from the multiple data array based on a predicate function\n * @param predicate - Function that returns true for items to remove\n * @returns This instance for method chaining\n * \n * @example\n * ```typescript\n * storage.removeFromMultipleData(user => user.id === 1);\n * ```\n */\n public removeFromMultipleData(predicate: (item: T) => boolean) {\n this.multipleData.update(prevData => prevData.filter(item => !predicate(item)));\n return this;\n }\n\n /**\n * Updates an item in the multiple data array based on a predicate function\n * @param predicate - Function that returns true for items to update\n * @param updateFn - Function that returns the updated item\n * @returns This instance for method chaining\n * \n * @example\n * ```typescript\n * storage.updateItemInMultipleData(\n * user => user.id === 1,\n * user => ({ ...user, name: 'Updated Name' })\n * );\n * ```\n */\n public updateItemInMultipleData(predicate: (item: T) => boolean, updateFn: (item: T) => T) {\n this.multipleData.update(prevData => \n prevData.map(item => predicate(item) ? updateFn(item) : item)\n );\n return this;\n }\n\n /**\n * Clears all data (both single and multiple)\n * @returns This instance for method chaining\n */\n public clearAll() {\n this.singleData.set(null);\n this.multipleData.set([]);\n return this;\n }\n\n /**\n * Clears only the single data\n * @returns This instance for method chaining\n */\n public clearSingleData() {\n this.singleData.set(null);\n return this;\n }\n\n /**\n * Clears only the multiple data\n * @returns This instance for method chaining\n */\n public clearMultipleData() {\n this.multipleData.set([]);\n return this;\n }\n\n /**\n * Checks if single data exists (is not null)\n * @returns true if single data exists, false otherwise\n */\n public hasSingleData(): boolean {\n return this.singleData() !== null;\n }\n\n /**\n * Checks if multiple data has items\n * @returns true if multiple data array has items, false if empty\n */\n public hasMultipleData(): boolean {\n return this.multipleData().length > 0;\n }\n\n /**\n * Gets the count of items in multiple data\n * @returns Number of items in the multiple data array\n */\n public getMultipleDataCount(): number {\n return this.multipleData().length;\n }\n\n /**\n * Finds an item in the multiple data array\n * @param predicate - Function that returns true for the item to find\n * @returns The found item or undefined\n */\n public findInMultipleData(predicate: (item: T) => boolean): T | undefined {\n return this.multipleData().find(predicate);\n }\n\n /**\n * Checks if an item exists in the multiple data array\n * @param predicate - Function that returns true for the item to check\n * @returns true if item exists, false otherwise\n */\n public existsInMultipleData(predicate: (item: T) => boolean): boolean {\n return this.multipleData().some(predicate);\n }\n}\n","import { HttpClient, HttpContext } from \"@angular/common/http\";\nimport { DestroyRef, signal } from \"@angular/core\";\nimport {\n catchError,\n debounceTime,\n finalize,\n first,\n mergeMap,\n Observable,\n of,\n Subject,\n Subscription,\n switchMap\n} from \"rxjs\";\nimport { z } from \"zod\";\nimport { SkipLoadingSpinner } from \"./http-context-tokens\";\n\n/**\n * Configuration options for NgSelectHelper\n */\ntype NgSelectHelperOpts = {\n ajaxUrl: string;\n httpClient: HttpClient;\n destroyRef: DestroyRef;\n usePostRequest: boolean;\n limit?: number;\n useCache?: boolean;\n skipLoadingSpinner?: boolean;\n};\n\n/**\n * Reset options for NgSelectHelper\n */\ntype NgSelectHelperResetOpts = {\n resetQueryParams: boolean;\n resetBody: boolean;\n resetCache: boolean;\n};\n\n/**\n * Query parameter type for NgSelectHelper\n */\ntype NgSelectHelperQueryParam = Record<string, string | number | boolean>;\n\n/**\n * Body type for NgSelectHelper POST requests\n */\ntype NgSelectHelperBody =\n | Array<\n | string\n | number\n | boolean\n | null\n | Record<string, string | number | boolean | null>\n >\n | Record<\n string,\n | string\n | number\n | boolean\n | null\n | Array<\n | string\n | number\n | boolean\n | null\n | Record<string, string | number | boolean | null>\n >\n >;\n\n/**\n * Cache key type for internal caching\n */\ntype CacheKey = {\n ajaxUrl: string;\n page: number;\n limit: number;\n searchText: string;\n queryParams: NgSelectHelperQueryParam;\n body: NgSelectHelperBody;\n};\n\n/**\n * Paged data response specifically for ng-select\n */\nexport class NgSelectPagedDataResponse<TData> {\n constructor(\n public readonly payload: Array<TData>,\n public readonly totalCount: number\n ) {}\n}\n\n/**\n * Zod schema for validating ng-select paged response\n */\nexport const NgSelectPagedDataResponseZodSchema = z.object({\n payload: z.any().array(),\n totalCount: z.number()\n});\n\n/**\n * Default reset options\n */\nconst defaultResetOpts: NgSelectHelperResetOpts = {\n resetQueryParams: false,\n resetBody: false,\n resetCache: false\n};\n\n/**\n * NgSelectHelper class for managing ng-select components with HTTP data loading,\n * pagination, caching, and search functionality using Angular signals\n * \n * @template TData The type of data items in the select options\n * \n * @example\n * ```typescript\n * interface User {\n * id: number;\n * name: string;\n * email: string;\n * }\n * \n * @Component({\n * selector: 'app-user-select',\n * template: `\n * <ng-select\n * [items]=\"selectHelper.loadedData().payload\"\n * bindLabel=\"name\"\n * bindValue=\"id\"\n * [loading]=\"selectHelper.isLoading()\"\n * [typeahead]=\"selectHelper.inputSubject\"\n * (open)=\"selectHelper.onOpen()\"\n * (close)=\"selectHelper.onClose()\"\n * (clear)=\"selectHelper.onClear()\"\n * (scrollToEnd)=\"selectHelper.onScrollToEnd()\">\n * </ng-select>\n * `\n * })\n * export class UserSelectComponent implements OnInit {\n * private httpClient = inject(HttpClient);\n * private destroyRef = inject(DestroyRef);\n * \n * selectHelper = NgSelectHelper.create<User>({\n * ajaxUrl: '/api/users',\n * httpClient: this.httpClient,\n * destroyRef: this.destroyRef,\n * usePostRequest: false,\n * limit: 20\n * });\n * \n * ngOnInit() {\n * this.selectHelper.init();\n * }\n * }\n * ```\n */\nexport class NgSelectHelper<TData> {\n constructor(\n private ajaxUrl: string,\n private readonly httpClient: HttpClient,\n private readonly destroyRef: DestroyRef,\n public readonly usePostRequest = false,\n limit: number = 50,\n private readonly useCache: boolean = true,\n private skipLoadingSpinner: boolean = true\n ) {\n this.#originalAjaxUrl = ajaxUrl;\n this.#limit = limit > 0 ? limit : 50;\n this.destroyRef.onDestroy(() => {\n this.#ajaxErrorSubject.complete();\n this.inputSubject.complete();\n this.#loadMoreDataSubject.complete();\n this.#cache.clear();\n if (this.runningApiReq && !this.runningApiReq.closed) {\n this.runningApiReq.unsubscribe();\n }\n });\n }\n\n readonly #cache: Map<string, NgSelectPagedDataResponse<TData>> = new Map();\n readonly #originalAjaxUrl: string;\n #queryParams: NgSelectHelperQueryParam = {};\n #body: NgSelectHelperBody = {};\n #initDone = false;\n #searchText = \"\";\n readonly #limit: number;\n #page = 1;\n #debounceTimeInSec: number = 1;\n #totalCount = -1;\n #isLastApiCallSuccessful = true;\n #limitReached = false;\n\n readonly #loadMoreDataSubject = new Subject<void>();\n\n public readonly inputSubject = new Subject<string>();\n readonly #ajaxErrorSubject = new Subject<Error>();\n public readonly ajaxError$ = this.#ajaxErrorSubject.asObservable();\n readonly #loadedData = signal<NgSelectPagedDataResponse<TData>>(\n new NgSelectPagedDataResponse<TData>([], 0)\n );\n public readonly loadedData = this.#loadedData.asReadonly();\n readonly #isLoading = signal(false);\n public readonly isLoading = this.#isLoading.asReadonly();\n private runningApiReq: Subscription | null = null;\n\n /**\n * Creates a new instance of NgSelectHelper\n * @param options Configuration options\n * @returns New NgSelectHelper instance\n */\n public static create<T>({\n ajaxUrl,\n httpClient,\n destroyRef,\n usePostRequest,\n limit = 50,\n useCache = true,\n skipLoadingSpinner = true\n }: NgSelectHelperOpts): NgSelectHelper<T> {\n return new NgSelectHelper<T>(\n ajaxUrl,\n httpClient,\n destroyRef,\n usePostRequest,\n limit,\n useCache,\n skipLoadingSpinner\n );\n }\n\n /**\n * Sets whether to skip the loading spinner for HTTP requests\n * @param skip Whether to skip the loading spinner\n * @returns This instance for method chaining\n */\n public setSkipLoadingSpinner(skip: boolean): this {\n this.skipLoadingSpinner = skip;\n return this;\n }\n\n /**\n * Sets the debounce time for search input in seconds\n * @param debounceTimeInSecond Debounce time in seconds\n * @returns This instance for method chaining\n */\n public setDebounceTimeInSecond(debounceTimeInSecond: number): this {\n this.#debounceTimeInSec =\n debounceTimeInSecond > 0 ? debounceTimeInSecond : 1;\n return this;\n }\n\n /**\n * Patches the request body (only works with POST requests)\n * @param value Body data to merge\n * @returns This instance for method chaining\n */\n public patchBody(value: NgSelectHelperBody): this {\n if (this.usePostRequest) {\n this.resetAll();\n this.#body = Object.assign(this.#body, value);\n }\n return this;\n }\n\n /**\n * Sets the request body (only works with POST requests)\n * @param newBody New body data\n * @returns This instance for method chaining\n */\n public setBody(newBody: NgSelectHelperBody): this {\n if (this.usePostRequest) {\n this.resetAll();\n this.#body = newBody;\n }\n return this;\n }\n\n /**\n * Clears the internal cache\n * @returns This instance for method chaining\n */\n public clearCache(): this {\n this.#cache.clear();\n return this;\n }\n\n /**\n * Sets route parameters for the URL\n * @param newRouteParam Route parameter to append\n * @returns This instance for method chaining\n */\n public setRouteParam(newRouteParam: string): this {\n const baseUrl = this.#originalAjaxUrl.endsWith(\"/\")\n ? this.#originalAjaxUrl.slice(0, -1)\n : this.#originalAjaxUrl;\n\n let routeParam = newRouteParam.startsWith(\"/\")\n ? newRouteParam.slice(1)\n : newRouteParam;\n\n this.ajaxUrl = `${baseUrl}/${routeParam}`;\n\n return this;\n }\n\n /**\n * Patches query parameters\n * @param value Query parameters to merge\n * @returns This instance for method chaining\n */\n public patchQueryParams(value: NgSelectHelperQueryParam): this {\n this.resetAll();\n this.#queryParams = Object.assign(this.#queryParams, value);\n return this;\n }\n\n /**\n * Removes a query parameter\n * @param key Query parameter key to remove\n * @returns This instance for method chaining\n */\n public removeQueryParam(key: string): this {\n this.resetAll();\n delete this.#queryParams[key];\n return this;\n }\n\n /**\n * Sets query parameters\n * @param newQueryParams New query parameters\n * @returns This instance for method chaining\n */\n public setQueryParams(newQueryParams: NgSelectHelperQueryParam): this {\n this.resetAll();\n this.#queryParams = newQueryParams;\n return this;\n }\n\n /**\n * Handler for ng-select blur event\n */\n public onBlur(): void {\n this.resetAll();\n }\n\n /**\n * Handler for ng-select close event\n */\n public onClose(): void {\n this.resetSearchText();\n if (this.runningApiReq && !this.runningApiReq.closed) {\n this.runningApiReq.unsubscribe();\n this.runningApiReq = null;\n }\n }\n\n /**\n * Handler for ng-select clear event\n */\n public async onClear(): Promise<void> {\n this.resetAll();\n }\n\n /**\n * Handler for ng-select open event\n */\n public onOpen(): void {\n this.#loadMoreDataSubject.next();\n }\n\n /**\n * Handler for ng-select scroll to end event\n */\n public onScrollToEnd(): void {\n if (this.#isLoading()) {\n return;\n }\n this.runProbablePageCounterUpdate();\n this.#loadMoreDataSubject.next();\n }\n\n /**\n * Gets whether the last API call was successful\n */\n public get isLastApiCallSuccessful(): boolean {\n return this.#isLastApiCallSuccessful;\n }\n\n /**\n * Gets whether the limit has been reached\n */\n public get limitReached(): boolean {\n return this.#limitReached;\n }\n\n /**\n * Gets current query parameters\n */\n public get queryParams(): NgSelectHelperQueryParam {\n return this.#queryParams;\n }\n\n /**\n * Gets current request body\n */\n public get body(): NgSelectHelperBody {\n return this.#body;\n }\n\n /**\n * Gets current page number\n */\n public get page(): number {\n return this.#page;\n }\n\n /**\n * Gets total count of available items\n */\n public get totalCount(): number {\n return this.#totalCount;\n }\n\n /**\n * Gets whether initialization is complete\n */\n public get isInitDone(): boolean {\n return this.#initDone;\n }\n\n /**\n * Initializes the NgSelectHelper with event handlers\n * Should be called in ngOnInit or similar lifecycle method\n */\n public init(): void {\n if (this.#initDone) {\n return;\n }\n this.#initDone = true;\n\n // Handle search input with debouncing\n this.inputSubject\n .pipe(\n debounceTime(this.#debounceTimeInSec * 500),\n switchMap((term) => {\n this.resetAll();\n this.#searchText = term;\n return this.loadDataFromApi(this.page, this.#limit, term).pipe(\n catchError(() => of(null))\n );\n })\n )\n .subscribe({\n next: (res) => {\n if (res) {\n this.updateStateOnSuccessfulInitialApiCall(res);\n } else {\n this.updateStateOnFailedApiCall();\n }\n }\n });\n\n // Handle load more requests\n this.#loadMoreDataSubject\n .pipe(\n switchMap(() => {\n if (this.#isLoading()) {\n return of(null);\n }\n\n this.runLimitReachedCheck();\n\n if (this.limitReached) {\n return of(null);\n }\n\n return this.loadDataFromApi(\n this.page,\n this.#limit,\n this.#searchText\n ).pipe(catchError(() => of(null)));\n })\n )\n .subscribe({\n next: (res) => {\n if (res) {\n this.updateStateOnSuccessfulSubsequentApiCall(res);\n } else {\n this.updateStateOnFailedApiCall();\n }\n }\n });\n }\n\n /**\n * Loads data from the API\n * @param page Page number\n * @param limit Items per page\n * @param searchText Search term\n * @returns Observable of paged data response\n */\n private loadDataFromApi(\n page: number,\n limit: number,\n searchText?: string\n ): Observable<NgSelectPagedDataResponse<TData> | null> {\n const queryParams: Record<string, string | number> = { page, limit };\n\n if (searchText) {\n queryParams[\"searchText\"] = searchText;\n }\n\n const key: CacheKey = {\n ajaxUrl: this.ajaxUrl,\n page: page,\n limit: limit,\n searchText: searchText ?? \"\",\n queryParams: { ...queryParams, ...this.#queryParams },\n body: this.#body\n };\n\n let strKey: string | null = null;\n\n if (this.useCache) {\n strKey = JSON.stringify(key);\n const cacheData = this.#cache.get(strKey);\n\n if (cacheData !== undefined) {\n return of(cacheData);\n }\n }\n\n this.#isLoading.set(true);\n\n let req: Observable<NgSelectPagedDataResponse<TData> | null>;\n\n if (this.usePostRequest) {\n req = this.httpClient.post<NgSelectPagedDataResponse<TData>>(\n key.ajaxUrl,\n key.body,\n {\n params: key.queryParams,\n context: new HttpContext().set(SkipLoadingSpinner, this.skipLoadingSpinner)\n }\n );\n } else {\n req = this.httpClient.get<NgSelectPagedDataResponse<TData>>(key.ajaxUrl, {\n params: key.queryParams,\n context: new HttpContext().set(SkipLoadingSpinner, this.skipLoadingSpinner)\n });\n }\n\n return req.pipe(\n first(),\n mergeMap((val) => {\n const result = NgSelectPagedDataResponseZodSchema.safeParse(val);\n if (!result.success) {\n throw new Error(\"Invalid response body for ng-select\");\n }\n if (this.useCache && strKey && val) {\n this.#cache.set(strKey, val);\n }\n return of(val);\n }),\n catchError((error) => {\n this.#ajaxErrorSubject.next(error);\n return of(null);\n }),\n finalize(() => this.#isLoading.set(false))\n );\n }\n\n /**\n * Updates page counter if conditions are met\n */\n private runProbablePageCounterUpdate(): void {\n if (this.isLastApiCallSuccessful && !this.limitReached) {\n this.#page += 1;\n }\n }\n\n /**\n * Checks if the limit has been reached\n */\n private runLimitReachedCheck(): void {\n if (this.totalCount != -1) {\n this.#limitReached = this.#loadedData().payload.length >= this.totalCount;\n }\n }\n\n /**\n * Updates state after successful initial API call\n * @param data Response data\n */\n private updateStateOnSuccessfulInitialApiCall(\n data: NgSelectPagedDataResponse<TData>\n ): void {\n this.#loadedData.set(new NgSelectPagedDataResponse(data.payload, data.totalCount));\n this.#totalCount = data.totalCount;\n this.#isLastApiCallSuccessful = true;\n }\n\n /**\n * Updates state after successful subsequent API call\n * @param data Response data\n */\n private updateStateOnSuccessfulSubsequentApiCall(\n data: NgSelectPagedDataResponse<TData>\n ): void {\n this.#loadedData.update((val) => {\n return new NgSelectPagedDataResponse<TData>(\n [...val.payload, ...data.payload],\n data.totalCount\n );\n });\n\n this.#totalCount = data.totalCount;\n this.#isLastApiCallSuccessful = true;\n }\n\n /**\n * Updates state after failed API call\n */\n private updateStateOnFailedApiCall(): void {\n this.#isLastApiCallSuccessful = false;\n }\n\n /**\n * Resets all state to initial values\n * @param opts Reset options\n */\n public resetAll(opts: NgSelectHelperResetOpts = defaultResetOpts): void {\n // Cancel any running request\n if (this.runningApiReq && !this.runningApiReq.closed) {\n this.runningApiReq.unsubscribe();\n this.runningApiReq = null;\n }\n\n this.#isLastApiCallSuccessful = true;\n this.#page = 1;\n this.#totalCount = -1;\n this.#limitReached = false;\n this.#searchText = \"\";\n\n if (opts.resetCache) {\n this.#cache.clear();\n }\n\n this.#loadedData.set(new NgSelectPagedDataResponse<TData>([], 0));\n this.#isLoading.set(false);\n\n if (opts.resetQueryParams) {\n this.#queryParams = {};\n }\n\n if (opts.resetBody) {\n this.#body = {};\n }\n }\n\n /**\n * Resets search text\n */\n private resetSearchText(): void {\n this.#searchText = \"\";\n }\n}\n","import { DestroyRef } from \"@angular/core\";\nimport { takeUntilDestroyed } from \"@angular/core/rxjs-interop\";\nimport { Observable } from \"rxjs\";\nimport { NgSelectHelper } from \"./ng-select-helper\";\n\n/**\n * Utility function to initialize NgSelect helpers with error handling\n * \n * This function streamlines the initialization process for multiple NgSelect helpers\n * by automatically initializing them and setting up error handling subscriptions.\n * \n * @param helpers$ Observable of NgSelectHelper instances\n * @param destroyRef Angular DestroyRef for automatic cleanup\n * @param onAjaxError Callback function to handle AJAX errors\n * \n * @example\n * ```typescript\n * import { Component, inject, signal } from '@angular/core';\n * import { HttpClient } from '@angular/common/http';\n * import { DestroyRef } from '@angular/core';\n * import { toObservable } from '@angular/core/rxjs-interop';\n * import { NgSelectHelper, initNgSelect } from 'ngx-primeng-toolkit';\n * \n * @Component({\n * selector: 'app-example'\n * })\n * export class ExampleComponent {\n * private readonly httpClient = inject(HttpClient);\n * private readonly destroyRef = inject(DestroyRef);\n * private readonly toastService = inject(ToastService);\n * \n * readonly userSelectHelper = new NgSelectHelper<User>(\n * '/api/users',\n * this.httpClient,\n * this.destroyRef,\n * false, // requiresSearch\n * 50, // pageSize\n * false // isLazyLoad\n * );\n * \n * readonly departmentSelectHelper = new NgSelectHelper<Department>(\n * '/api/departments',\n * this.httpClient,\n * this.destroyRef,\n * true, // requiresSearch\n * 25, // pageSize\n * true // isLazyLoad\n * );\n * \n * readonly ngSelectHelpers = signal([\n * this.userSelectHelper,\n * this.departmentSelectHelper\n * ]);\n * \n * constructor() {\n * initNgSelect(\n * toObservable(this.ngSelectHelpers),\n * this.destroyRef,\n * (err) => this.toastService.showAjaxErrorToast(err)\n * );\n * }\n * }\n * ```\n */\nexport function initNgSelect(\n helpers$: Observable<NgSelectHelper<unknown>[]>,\n destroyRef: DestroyRef,\n onAjaxError: (err: Error) => void\n): void {\n helpers$.pipe(takeUntilDestroyed(destroyRef)).subscribe({\n next: (helpers) => {\n helpers\n .filter((elem) => elem instanceof NgSelectHelper && !elem.isInitDone)\n .forEach((elem) => {\n elem.init();\n elem.ajaxError$\n .pipe(takeUntilDestroyed(destroyRef))\n .subscribe(onAjaxError);\n });\n }\n });\n}\n"],"mappings":"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","names":["ManipulationType","HttpContext","signal","signalState","patchState","firstValueFrom","_uniqueKey","_queryParams","signalState","signal","patchState","firstValueFrom","HttpContext","signal","HttpContext","firstValueFrom","signal","firstValueFrom","HttpContext","signal","signal","signal","HttpContext","signal","z","z","_queryParams","_isLoading","signal","HttpContext"]}