@acorex/platform 20.9.0 → 20.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,11 +10,11 @@ import * as i1$3 from '@acorex/platform/workflow';
10
10
  import { AXPWorkflowEventService, AXPWorkflowService, ofType, createWorkFlowEvent, AXPWorkflowAction, AXPWorkflowModule } from '@acorex/platform/workflow';
11
11
  import * as i0 from '@angular/core';
12
12
  import { InjectionToken, inject, Injector, runInInjectionContext, Injectable, ChangeDetectorRef, input, signal, computed, effect, ChangeDetectionStrategy, Component, ElementRef, NgModule, viewChild, Input, afterNextRender, untracked, ViewEncapsulation, viewChildren, linkedSignal, HostBinding, output, EnvironmentInjector, makeEnvironmentProviders } from '@angular/core';
13
- import { cloneDeep, merge, get, castArray, set, orderBy, isNil, isEmpty, isEqual, isObjectLike, isArray, has, isString } from 'lodash-es';
13
+ import { cloneDeep, merge, get, castArray, set, orderBy, defaultTo, isNil, isEmpty, isEqual, isObjectLike, isArray, has, isString } from 'lodash-es';
14
14
  import { Subject, filter, takeUntil } from 'rxjs';
15
15
  import { AXPWidgetsCatalog, resolveActionLook, AXPPlatformScope, extractValue, setSmart, getChangedPaths, isSelectionValueEqual, AXPDataGenerator, AXPSystemActionType } from '@acorex/platform/contracts';
16
16
  import { AXPLayoutBuilderService, LayoutBuilderModule } from '@acorex/platform/layout/builder';
17
- import { AXPDeviceService, AXPExpressionEvaluatorService, AXPContextEvalFactory, AXPBroadcastEventService, applyFilterArray, applySortArray, AXPDistributedEventListenerService, AXHighlightService, AXPDebugService, AXPContextStore, FORM_DIRTY_TRACE_NS, objectKeyValueTransforms, setupPopupFooterKeyboardShortcuts, AXPHookService, AXPComponentSlotModule, AXPColumnWidthService, AXPModuleManifestRegistry, defaultColumnWidthProvider, AXP_COLUMN_WIDTH_PROVIDER, AXP_DATASOURCE_DEFINITION_PROVIDER, AXPModuleManifestsDataSourceDefinition } from '@acorex/platform/core';
17
+ import { AXPDeviceService, AXPExpressionEvaluatorService, AXPContextEvalFactory, AXPBroadcastEventService, applyFilterArray, applySortArray, AXPDistributedEventListenerService, AXHighlightService, AXPColumnWidthService, AXPDebugService, AXPContextStore, FORM_DIRTY_TRACE_NS, objectKeyValueTransforms, setupPopupFooterKeyboardShortcuts, AXPHookService, AXPComponentSlotModule, AXPModuleManifestRegistry, defaultColumnWidthProvider, AXP_COLUMN_WIDTH_PROVIDER, AXP_DATASOURCE_DEFINITION_PROVIDER, AXPModuleManifestsDataSourceDefinition } from '@acorex/platform/core';
18
18
  import { AXPSessionService, AXPPermissionDefinitionsDataSourceDefinition } from '@acorex/platform/auth';
19
19
  import { Router, NavigationStart, ActivatedRoute, RouterModule, ROUTES } from '@angular/router';
20
20
  import { defineCommand, AXP_COMMAND_DEFINITION_CATEGORY_ENTITY } from '@acorex/platform/runtime-contracts';
@@ -1385,9 +1385,6 @@ class PropertyFilter {
1385
1385
  });
1386
1386
  }
1387
1387
  wizardExtraSteps.sort((a, b) => a.order - b.order);
1388
- const pageWizardWidgetNames = wizardExtraSteps
1389
- .filter((s) => s.kind === 'page')
1390
- .map((s) => buildPageComponentWidgetName(s.page));
1391
1388
  const prebuiltRelatedListConfigs = useFormWizard
1392
1389
  ? await Promise.all(wizardExtraSteps
1393
1390
  .filter((s) => s.kind === 'related-list')
@@ -1485,7 +1482,7 @@ class PropertyFilter {
1485
1482
  .submit(this.kind === 'create' ? '@general:actions.create.title' : '@general:actions.apply.title'));
1486
1483
  }
1487
1484
  if (useFormWizard && this.onActionHandler) {
1488
- d.onAction(this.createWizardOnActionWrapper(this.onActionHandler, pageWizardWidgetNames));
1485
+ d.onAction(this.createWizardOnActionWrapper(this.onActionHandler));
1489
1486
  }
1490
1487
  else if (this.onActionHandler) {
1491
1488
  d.onAction(this.onActionHandler);
@@ -1649,11 +1646,14 @@ class PropertyFilter {
1649
1646
  return (await this.expressionEvaluator.evaluate(action, scope));
1650
1647
  }));
1651
1648
  }
1652
- createWizardOnActionWrapper(userHandler, pageWizardWidgetNames = []) {
1649
+ createWizardOnActionWrapper(userHandler) {
1653
1650
  return async (ref) => {
1654
1651
  const action = ref.action();
1655
1652
  if (action === ENTITY_FORM_ACTION_DONE) {
1656
- await syncAllPageComponentWidgets(ref, pageWizardWidgetNames);
1653
+ const pageContinue = await continueActiveEntityFormPageStep(ref);
1654
+ if (!pageContinue.success) {
1655
+ return { keepDialogOpen: true };
1656
+ }
1657
1657
  if (hasPersistedRootId$1(ref.context())) {
1658
1658
  const out = (await userHandler(ref));
1659
1659
  if (out?.success === false) {
@@ -1664,7 +1664,10 @@ class PropertyFilter {
1664
1664
  return { success: true, data: ref.context(), skipValidate: true };
1665
1665
  }
1666
1666
  if (action === ENTITY_FORM_ACTION_NEXT_STEP) {
1667
- await syncAllPageComponentWidgets(ref, pageWizardWidgetNames);
1667
+ const pageContinue = await continueActiveEntityFormPageStep(ref);
1668
+ if (!pageContinue.success) {
1669
+ return { keepDialogOpen: true };
1670
+ }
1668
1671
  await ref.invokeWidget?.(ENTITY_FORM_STEP_WIZARD_NAME, 'next', { setLoading: ref.setLoading });
1669
1672
  return { keepDialogOpen: true };
1670
1673
  }
@@ -1673,7 +1676,7 @@ class PropertyFilter {
1673
1676
  if (out?.success === false) {
1674
1677
  return out;
1675
1678
  }
1676
- const item = out?.data?.item ?? out?.data ?? {};
1679
+ const item = normalizeWizardPersistedRecordPatch(out?.data?.item ?? out?.data ?? {});
1677
1680
  ref.patchContext?.(merge({}, ref.context(), item));
1678
1681
  await ref.invokeWidget?.(ENTITY_FORM_STEP_WIZARD_NAME, 'next', { setLoading: ref.setLoading });
1679
1682
  return merge({}, out, { keepDialogOpen: true });
@@ -2042,10 +2045,27 @@ function hasPersistedRootId$1(context) {
2042
2045
  const raw = context?.id ?? context?._id;
2043
2046
  return (typeof raw === 'string' && raw.length > 0) || (typeof raw === 'number' && !Number.isNaN(raw));
2044
2047
  }
2045
- async function syncAllPageComponentWidgets(ref, widgetNames) {
2046
- for (const name of widgetNames) {
2047
- await ref.invokeWidget?.(name, 'syncContext', {});
2048
+ function normalizeWizardPersistedRecordPatch(data) {
2049
+ if (!data || typeof data !== 'object' || Array.isArray(data)) {
2050
+ return {};
2051
+ }
2052
+ const record = { ...data };
2053
+ const rawId = record['id'] ?? record['_id'];
2054
+ if (rawId != null && record['id'] == null) {
2055
+ record['id'] = rawId;
2056
+ }
2057
+ return record;
2058
+ }
2059
+ async function continueActiveEntityFormPageStep(ref) {
2060
+ const status = (await ref.invokeWidget?.(ENTITY_FORM_STEP_WIZARD_NAME, 'getStatus', {}));
2061
+ const stepId = status?.currentStep?.id;
2062
+ if (!stepId?.startsWith('page-')) {
2063
+ return { success: true };
2048
2064
  }
2065
+ const result = (await ref.invokeWidget?.(`pageComponent_${stepId}`, 'continueWizardStep', {
2066
+ setLoading: ref.setLoading,
2067
+ }));
2068
+ return { success: result?.success !== false };
2049
2069
  }
2050
2070
  function buildEntityFormRelatedStepId(re) {
2051
2071
  const safe = re.entity.replace(/[^a-zA-Z0-9._-]/g, '_');
@@ -4374,6 +4394,7 @@ class AXPEntityListViewColumnViewModel {
4374
4394
  this.title = this.column.title ?? this.property.title;
4375
4395
  this.visible = this.column?.options?.visible ?? true;
4376
4396
  this.sortEnabled = this.property.options?.sort?.enabled;
4397
+ this.width = this.column?.options?.width;
4377
4398
  this.node = computed(() => {
4378
4399
  const widget = this.property.schema.interface;
4379
4400
  return {
@@ -5149,6 +5170,7 @@ class AXPEntityMasterListViewQueryViewModel {
5149
5170
  this.conditions = this.view.conditions;
5150
5171
  this.indexCol = this.view.indexCol;
5151
5172
  this.pageSize = this.view.pageSize;
5173
+ this.visible = this.view.visible;
5152
5174
  }
5153
5175
  }
5154
5176
  class AXPEntityMasterListViewModel {
@@ -5249,6 +5271,24 @@ class AXPEntityMasterListViewModel {
5249
5271
  },
5250
5272
  };
5251
5273
  }
5274
+ /**
5275
+ * Evaluates each view's `visible` expression and updates the filtered view list.
5276
+ */
5277
+ async refreshVisibleViews() {
5278
+ const scope = this.createLogicExpressionScope(null);
5279
+ const evaluated = await Promise.all(this.allViews().map(async (viewModel) => {
5280
+ const visible = viewModel.visible;
5281
+ if (visible === undefined || visible === null || visible === '') {
5282
+ return viewModel;
5283
+ }
5284
+ if (typeof visible === 'boolean') {
5285
+ return visible ? viewModel : null;
5286
+ }
5287
+ const isVisible = await this.expressionEvaluator.evaluate(visible, scope);
5288
+ return isVisible !== false ? viewModel : null;
5289
+ }));
5290
+ this.visibleViews.set(evaluated.filter((viewModel) => viewModel != null));
5291
+ }
5252
5292
  async resolveCommandNameExpression(commandName, data) {
5253
5293
  if (!commandName || !commandName.includes('{{')) {
5254
5294
  return commandName;
@@ -5379,13 +5419,24 @@ class AXPEntityMasterListViewModel {
5379
5419
  return `${resolvedCommand}${suffix}`;
5380
5420
  }
5381
5421
  async setView(viewName = null) {
5422
+ await this.refreshVisibleViews();
5423
+ const availableViews = this.views();
5424
+ if (!availableViews.length) {
5425
+ return;
5426
+ }
5382
5427
  let selectedViewName;
5383
5428
  if (await this.shouldLoadPersistedListState()) {
5384
5429
  const entitySetting = await this.settings.get(this.settingEntityKey);
5385
5430
  selectedViewName = entitySetting?.list?.currentView;
5386
5431
  }
5387
- if (viewName != this.view().name) {
5388
- this.view.set(this.views().find((c) => c.name == (viewName || selectedViewName)) ?? this.views()[0]);
5432
+ const resolvedViewName = viewName ?? selectedViewName;
5433
+ const currentViewName = this.view().name;
5434
+ const currentViewUnavailable = !availableViews.some((v) => v.name === currentViewName);
5435
+ const nextView = availableViews.find((c) => c.name == resolvedViewName) ??
5436
+ (currentViewUnavailable ? availableViews[0] : this.view());
5437
+ const shouldApplyViewState = viewName != currentViewName || nextView.name !== currentViewName || currentViewUnavailable;
5438
+ if (shouldApplyViewState) {
5439
+ this.view.set(nextView);
5389
5440
  this.applyViewSorts();
5390
5441
  this.applyViewColumns();
5391
5442
  this.applyCardFields();
@@ -5428,13 +5479,18 @@ class AXPEntityMasterListViewModel {
5428
5479
  this.listPersistenceMode = null;
5429
5480
  this.events$ = new Subject();
5430
5481
  //****************** Views ******************//
5431
- this.views = computed(() => {
5482
+ this.allViews = computed(() => {
5432
5483
  const views = this.entityDef.interfaces?.master?.list?.views ?? [];
5433
5484
  return views.map((v) => {
5434
5485
  return new AXPEntityMasterListViewQueryViewModel(this.entityDef, this, v);
5435
5486
  });
5487
+ }, ...(ngDevMode ? [{ debugName: "allViews" }] : /* istanbul ignore next */ []));
5488
+ this.visibleViews = signal([], ...(ngDevMode ? [{ debugName: "visibleViews" }] : /* istanbul ignore next */ []));
5489
+ this.views = computed(() => {
5490
+ const visible = this.visibleViews();
5491
+ return visible.length > 0 ? visible : this.allViews();
5436
5492
  }, ...(ngDevMode ? [{ debugName: "views" }] : /* istanbul ignore next */ []));
5437
- this.view = signal(this.views()[0], ...(ngDevMode ? [{ debugName: "view" }] : /* istanbul ignore next */ []));
5493
+ this.view = signal(this.allViews()[0], ...(ngDevMode ? [{ debugName: "view" }] : /* istanbul ignore next */ []));
5438
5494
  this.showRowIndexColumnEnabled = signal(false, ...(ngDevMode ? [{ debugName: "showRowIndexColumnEnabled" }] : /* istanbul ignore next */ []));
5439
5495
  /**
5440
5496
  * Row index column: if the list view defines `indexCol` (true/false), that overrides the user setting;
@@ -5752,10 +5808,11 @@ class AXPEntityMasterListViewModel {
5752
5808
  if (columns && columnVisibilityMap && columnWidthsMap) {
5753
5809
  this.columns.update((prev) => prev
5754
5810
  .map((c) => {
5811
+ const columnKey = c.column?.options?.dataPath ?? c.name;
5755
5812
  return {
5756
5813
  ...c,
5757
- width: columnWidthsMap.get(c.column?.options?.dataPath ?? c.name),
5758
- visible: columnVisibilityMap.get(c.column?.options?.dataPath ?? c.name) ?? c.visible,
5814
+ width: defaultTo(columnWidthsMap.get(columnKey), c.column?.options?.width),
5815
+ visible: columnVisibilityMap.get(columnKey) ?? c.visible,
5759
5816
  };
5760
5817
  }) // Update visibility
5761
5818
  .sort((a, b) => columns.findIndex((col) => col.name === (a.column?.options?.dataPath ?? a.name)) -
@@ -6716,6 +6773,7 @@ class AXPEntityListViewModelFactory {
6716
6773
  await vm.loadFilterDefinitions();
6717
6774
  await vm.loadSortableFields();
6718
6775
  await vm.initializeListPersistence();
6776
+ await vm.refreshVisibleViews();
6719
6777
  return vm;
6720
6778
  }
6721
6779
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPEntityListViewModelFactory, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
@@ -11997,6 +12055,26 @@ function mapEntityColumnToWidgetColumn(entity, column) {
11997
12055
  widget,
11998
12056
  };
11999
12057
  }
12058
+ /**
12059
+ * Applies entity column width (explicit or resolved via {@link AXPColumnWidthService}) to data-list columns.
12060
+ */
12061
+ function applyDataListColumnWidths(columns, columnWidthService) {
12062
+ return columns.map((column) => {
12063
+ const existingWidth = column.width ?? column.widget?.options?.width;
12064
+ if (existingWidth) {
12065
+ return existingWidth === column.width ? column : { ...column, width: String(existingWidth) };
12066
+ }
12067
+ const columnWithWidth = {
12068
+ name: column.name,
12069
+ widget: column.widget ? { type: column.widget.type } : undefined,
12070
+ };
12071
+ const resolvedWidth = columnWidthService.resolveWidth(columnWithWidth);
12072
+ if (!resolvedWidth) {
12073
+ return column;
12074
+ }
12075
+ return { ...column, width: resolvedWidth };
12076
+ });
12077
+ }
12000
12078
  //#endregion
12001
12079
  //#region ---- Include/Exclude Utilities ----
12002
12080
  /**
@@ -12027,6 +12105,7 @@ class AXPEntityListTableService {
12027
12105
  this.commandService = inject(AXPCommandService);
12028
12106
  this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
12029
12107
  this.settings = inject(AXPSettingsService);
12108
+ this.columnWidthService = inject(AXPColumnWidthService);
12030
12109
  this.evaluateExpressions = async (options, data) => {
12031
12110
  if (!options) {
12032
12111
  return {};
@@ -12128,7 +12207,7 @@ class AXPEntityListTableService {
12128
12207
  else {
12129
12208
  baseColumns = getVisibleProperties(entity).map((prop) => mapPropertyToWidgetColumn(prop));
12130
12209
  }
12131
- return applyIncludeExclude(baseColumns, includeColumns, excludeColumns);
12210
+ return applyDataListColumnWidths(applyIncludeExclude(baseColumns, includeColumns, excludeColumns), this.columnWidthService);
12132
12211
  }
12133
12212
  /**
12134
12213
  * Map EntityTableColumn to ListWidgetColumn
@@ -12447,6 +12526,7 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
12447
12526
  this.commandService = inject(AXPCommandService);
12448
12527
  this.eventService = inject(AXPBroadcastEventService);
12449
12528
  this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
12529
+ this.columnWidthService = inject(AXPColumnWidthService);
12450
12530
  this.route = inject(ActivatedRoute);
12451
12531
  this.isMounted = signal(false, ...(ngDevMode ? [{ debugName: "isMounted" }] : /* istanbul ignore next */ []));
12452
12532
  this.entity = signal(null, ...(ngDevMode ? [{ debugName: "entity" }] : /* istanbul ignore next */ []));
@@ -13003,7 +13083,9 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
13003
13083
  })
13004
13084
  .filter((c) => c != null);
13005
13085
  // Apply updated columns to the list widget and refresh
13006
- listInstance.setOptions({ columns: updatedColumns });
13086
+ listInstance.setOptions({
13087
+ columns: applyDataListColumnWidths(updatedColumns, this.columnWidthService),
13088
+ });
13007
13089
  }
13008
13090
  async ngOnInit() {
13009
13091
  super.ngOnInit();
@@ -13370,6 +13452,8 @@ class AXPPageComponentWidgetViewComponent extends AXPBaseWidgetComponent {
13370
13452
  super(...arguments);
13371
13453
  //#region ---- Services & Dependencies ----
13372
13454
  this.deviceService = inject(AXPDeviceService);
13455
+ this.toastService = inject(AXToastService);
13456
+ this.translationService = inject(AXTranslationService);
13373
13457
  this.pageRenderer = viewChild(AXPPageComponentRendererDirective, ...(ngDevMode ? [{ debugName: "pageRenderer" }] : /* istanbul ignore next */ []));
13374
13458
  //#endregion
13375
13459
  //#region ---- Computed Options ----
@@ -13397,7 +13481,6 @@ class AXPPageComponentWidgetViewComponent extends AXPBaseWidgetComponent {
13397
13481
  }
13398
13482
  instance.primaryMenuItems();
13399
13483
  instance.secondaryMenuItems();
13400
- console.log({ primaryMenuItems: instance.primaryMenuItems(), secondaryMenuItems: instance.secondaryMenuItems() });
13401
13484
  untracked(() => this.syncActionsFromPageInstance(instance));
13402
13485
  }, ...(ngDevMode ? [{ debugName: "#syncPageActionsEffect" }] : /* istanbul ignore next */ []));
13403
13486
  }
@@ -13421,6 +13504,15 @@ class AXPPageComponentWidgetViewComponent extends AXPBaseWidgetComponent {
13421
13504
  syncContext: () => {
13422
13505
  self.syncPageComponentIntoFormContext();
13423
13506
  },
13507
+ continueWizardStep: async (callback) => {
13508
+ callback?.setLoading?.(true);
13509
+ try {
13510
+ return await self.runWizardStepContinue();
13511
+ }
13512
+ finally {
13513
+ callback?.setLoading?.(false);
13514
+ }
13515
+ },
13424
13516
  refreshPageActions: () => {
13425
13517
  self.refreshPageActions();
13426
13518
  },
@@ -13454,6 +13546,66 @@ class AXPPageComponentWidgetViewComponent extends AXPBaseWidgetComponent {
13454
13546
  this.pageHostRevision.update((value) => value + 1);
13455
13547
  }
13456
13548
  //#endregion
13549
+ //#region ---- Wizard Step Continue ----
13550
+ /**
13551
+ * Persists the active page step when dirty (footer save action), then merges wizard context.
13552
+ * Used by entity create/update step wizard footer Next/Done.
13553
+ */
13554
+ async runWizardStepContinue() {
13555
+ const instance = this.resolvePageHost();
13556
+ if (!instance) {
13557
+ return { success: true };
13558
+ }
13559
+ const dirty = instance.hasUnsavedChanges?.() ?? false;
13560
+ if (dirty) {
13561
+ const command = this.resolveWizardContinueCommand(instance);
13562
+ if (command.name) {
13563
+ const result = await instance.execute(command);
13564
+ if (isExecuteCommandFailure(result)) {
13565
+ await this.showExecuteFailureToast(result);
13566
+ return { success: false };
13567
+ }
13568
+ }
13569
+ }
13570
+ this.syncPageComponentIntoFormContext();
13571
+ this.pageHostRevision.update((value) => value + 1);
13572
+ return { success: true };
13573
+ }
13574
+ resolveWizardContinueCommand(instance) {
13575
+ const explicit = instance.getWizardStepContinueCommand?.();
13576
+ if (explicit?.name) {
13577
+ return explicit;
13578
+ }
13579
+ const actions = [...instance.primaryMenuItems(), ...instance.secondaryMenuItems()];
13580
+ const continueAction = actions.find((action) => action.visible !== false &&
13581
+ isFooterZoneAction(action) &&
13582
+ getActionPriority(action) === 'primary' &&
13583
+ action.command);
13584
+ return continueAction ? normalizeExecuteCommand(continueAction.command) : { name: '', options: {} };
13585
+ }
13586
+ async showExecuteFailureToast(result) {
13587
+ const rawText = result.message?.text;
13588
+ let content;
13589
+ if (typeof rawText === 'string') {
13590
+ content = rawText.startsWith('@') ? await this.translationService.translateAsync(rawText) : rawText;
13591
+ }
13592
+ else if (rawText) {
13593
+ content = this.translationService.resolve(rawText);
13594
+ }
13595
+ else {
13596
+ content = await this.translationService.translateAsync('@general:messages.generic.error.description');
13597
+ }
13598
+ this.toastService.show({
13599
+ color: 'danger',
13600
+ title: await this.translationService.translateAsync('@general:messages.generic.error.title'),
13601
+ content,
13602
+ location: 'bottom-center',
13603
+ closeButton: true,
13604
+ timeOut: 5000,
13605
+ timeOutProgress: true,
13606
+ });
13607
+ }
13608
+ //#endregion
13457
13609
  //#region ---- Context Sync ----
13458
13610
  /** Merges the mounted page component's wizard payload into the dialog form context. */
13459
13611
  syncPageComponentIntoFormContext() {
@@ -13694,6 +13846,15 @@ function splitToolbarSecondaryActions(primary, secondary) {
13694
13846
  function isHeaderZoneAction(action) {
13695
13847
  return action.zone === 'header';
13696
13848
  }
13849
+ function isFooterZoneAction(action) {
13850
+ return action.zone === 'footer';
13851
+ }
13852
+ function isExecuteCommandFailure(result) {
13853
+ return (!!result &&
13854
+ typeof result === 'object' &&
13855
+ 'success' in result &&
13856
+ result.success === false);
13857
+ }
13697
13858
  function getActionPriority(action) {
13698
13859
  const priority = action.priority;
13699
13860
  return priority === 'secondary' ? 'secondary' : 'primary';
@@ -14824,6 +14985,7 @@ class AXPLookupWidgetSelectComponent extends LookupWidgetLookBase {
14824
14985
  this.allowCreate = input('none', ...(ngDevMode ? [{ debugName: "allowCreate" }] : /* istanbul ignore next */ []));
14825
14986
  this.showItemTooltip = input(false, ...(ngDevMode ? [{ debugName: "showItemTooltip" }] : /* istanbul ignore next */ []));
14826
14987
  this.isItemTruncated = input(true, ...(ngDevMode ? [{ debugName: "isItemTruncated" }] : /* istanbul ignore next */ []));
14988
+ this.textTemplate = input(null, ...(ngDevMode ? [{ debugName: "textTemplate" }] : /* istanbul ignore next */ []));
14827
14989
  //#endregion
14828
14990
  //#region ---- Outputs ----
14829
14991
  this.valueChanged = output();
@@ -14979,7 +15141,7 @@ class AXPLookupWidgetSelectComponent extends LookupWidgetLookBase {
14979
15141
  this.dataSource()?.refresh();
14980
15142
  }
14981
15143
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLookupWidgetSelectComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
14982
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPLookupWidgetSelectComponent, isStandalone: true, selector: "axp-lookup-widget-select", inputs: { entityDef: { classPropertyName: "entityDef", publicName: "entityDef", isSignal: true, isRequired: true, transformFunction: null }, customFilter: { classPropertyName: "customFilter", publicName: "customFilter", isSignal: true, isRequired: true, transformFunction: null }, selectedItems: { classPropertyName: "selectedItems", publicName: "selectedItems", isSignal: true, isRequired: true, transformFunction: null }, displayField: { classPropertyName: "displayField", publicName: "displayField", isSignal: true, isRequired: true, transformFunction: null }, valueField: { classPropertyName: "valueField", publicName: "valueField", isSignal: true, isRequired: true, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: true, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: true, transformFunction: null }, validationRules: { classPropertyName: "validationRules", publicName: "validationRules", isSignal: true, isRequired: true, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, hasClearButton: { classPropertyName: "hasClearButton", publicName: "hasClearButton", isSignal: true, isRequired: false, transformFunction: null }, allowCreate: { classPropertyName: "allowCreate", publicName: "allowCreate", isSignal: true, isRequired: false, transformFunction: null }, showItemTooltip: { classPropertyName: "showItemTooltip", publicName: "showItemTooltip", isSignal: true, isRequired: false, transformFunction: null }, isItemTruncated: { classPropertyName: "isItemTruncated", publicName: "isItemTruncated", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChanged: "valueChanged" }, providers: [
15144
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPLookupWidgetSelectComponent, isStandalone: true, selector: "axp-lookup-widget-select", inputs: { entityDef: { classPropertyName: "entityDef", publicName: "entityDef", isSignal: true, isRequired: true, transformFunction: null }, customFilter: { classPropertyName: "customFilter", publicName: "customFilter", isSignal: true, isRequired: true, transformFunction: null }, selectedItems: { classPropertyName: "selectedItems", publicName: "selectedItems", isSignal: true, isRequired: true, transformFunction: null }, displayField: { classPropertyName: "displayField", publicName: "displayField", isSignal: true, isRequired: true, transformFunction: null }, valueField: { classPropertyName: "valueField", publicName: "valueField", isSignal: true, isRequired: true, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: true, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: true, transformFunction: null }, validationRules: { classPropertyName: "validationRules", publicName: "validationRules", isSignal: true, isRequired: true, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, hasClearButton: { classPropertyName: "hasClearButton", publicName: "hasClearButton", isSignal: true, isRequired: false, transformFunction: null }, allowCreate: { classPropertyName: "allowCreate", publicName: "allowCreate", isSignal: true, isRequired: false, transformFunction: null }, showItemTooltip: { classPropertyName: "showItemTooltip", publicName: "showItemTooltip", isSignal: true, isRequired: false, transformFunction: null }, isItemTruncated: { classPropertyName: "isItemTruncated", publicName: "isItemTruncated", isSignal: true, isRequired: false, transformFunction: null }, textTemplate: { classPropertyName: "textTemplate", publicName: "textTemplate", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChanged: "valueChanged" }, providers: [
14983
15145
  {
14984
15146
  provide: LookupWidgetLookBase,
14985
15147
  useExisting: AXPLookupWidgetSelectComponent,
@@ -14999,6 +15161,7 @@ class AXPLookupWidgetSelectComponent extends LookupWidgetLookBase {
14999
15161
  [multiple]="multipleValue()"
15000
15162
  [showItemTooltip]="showItemTooltip()"
15001
15163
  [isItemTruncated]="isItemTruncated()"
15164
+ [textTemplate]="textTemplate()"
15002
15165
  (onValueChanged)="handleValueChanged($event)"
15003
15166
  >
15004
15167
  @if (hasClearButton()) {
@@ -15038,6 +15201,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
15038
15201
  [multiple]="multipleValue()"
15039
15202
  [showItemTooltip]="showItemTooltip()"
15040
15203
  [isItemTruncated]="isItemTruncated()"
15204
+ [textTemplate]="textTemplate()"
15041
15205
  (onValueChanged)="handleValueChanged($event)"
15042
15206
  >
15043
15207
  @if (hasClearButton()) {
@@ -15076,7 +15240,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
15076
15240
  },
15077
15241
  ],
15078
15242
  }]
15079
- }], propDecorators: { entityDef: [{ type: i0.Input, args: [{ isSignal: true, alias: "entityDef", required: true }] }], customFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "customFilter", required: true }] }], selectedItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedItems", required: true }] }], displayField: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayField", required: true }] }], valueField: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueField", required: true }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: true }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: true }] }], validationRules: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationRules", required: true }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], hasClearButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasClearButton", required: false }] }], allowCreate: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowCreate", required: false }] }], showItemTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "showItemTooltip", required: false }] }], isItemTruncated: [{ type: i0.Input, args: [{ isSignal: true, alias: "isItemTruncated", required: false }] }], valueChanged: [{ type: i0.Output, args: ["valueChanged"] }], selectBox: [{ type: i0.ViewChild, args: ['selectBox', { isSignal: true }] }] } });
15243
+ }], propDecorators: { entityDef: [{ type: i0.Input, args: [{ isSignal: true, alias: "entityDef", required: true }] }], customFilter: [{ type: i0.Input, args: [{ isSignal: true, alias: "customFilter", required: true }] }], selectedItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedItems", required: true }] }], displayField: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayField", required: true }] }], valueField: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueField", required: true }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: true }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: true }] }], validationRules: [{ type: i0.Input, args: [{ isSignal: true, alias: "validationRules", required: true }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], hasClearButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasClearButton", required: false }] }], allowCreate: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowCreate", required: false }] }], showItemTooltip: [{ type: i0.Input, args: [{ isSignal: true, alias: "showItemTooltip", required: false }] }], isItemTruncated: [{ type: i0.Input, args: [{ isSignal: true, alias: "isItemTruncated", required: false }] }], textTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "textTemplate", required: false }] }], valueChanged: [{ type: i0.Output, args: ["valueChanged"] }], selectBox: [{ type: i0.ViewChild, args: ['selectBox', { isSignal: true }] }] } });
15080
15244
 
15081
15245
  class AXPLookupWidgetTagboxComponent extends LookupWidgetLookBase {
15082
15246
  constructor() {
@@ -15614,9 +15778,7 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
15614
15778
  const newValue = this.singleOrMultiple(keys);
15615
15779
  const widgetPath = this.fullPath();
15616
15780
  const savedWidgetValue = widgetPath ? this.contextService.getSavedValue(widgetPath) : undefined;
15617
- const selectionMatchesSaved = this.contextService.isSavedCommitted() &&
15618
- widgetPath != null &&
15619
- isSelectionValueEqual(newValue, savedWidgetValue);
15781
+ const selectionMatchesSaved = this.contextService.isSavedCommitted() && widgetPath != null && isSelectionValueEqual(newValue, savedWidgetValue);
15620
15782
  if (this.expose()) {
15621
15783
  AXPDebugService.instance?.trace(FORM_DIRTY_TRACE_NS, 'lookup-widget', 'setItems expose', () => ({
15622
15784
  path: this.fullPath(),
@@ -15860,6 +16022,7 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
15860
16022
  [selectedItems]="selectedItems"
15861
16023
  [displayField]="displayField"
15862
16024
  [valueField]="valueField"
16025
+ [textTemplate]="textTemplate()"
15863
16026
  [disabled]="disabled"
15864
16027
  [multiple]="multiple"
15865
16028
  [placeholder]="placeholder"
@@ -15910,7 +16073,7 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
15910
16073
  }
15911
16074
  </div>
15912
16075
  }
15913
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPLookupWidgetSelectComponent, selector: "axp-lookup-widget-select", inputs: ["entityDef", "customFilter", "selectedItems", "displayField", "valueField", "disabled", "multiple", "validationRules", "placeholder", "hasClearButton", "allowCreate", "showItemTooltip", "isItemTruncated"], outputs: ["valueChanged"] }, { kind: "component", type: AXPLookupWidgetTagboxComponent, selector: "axp-lookup-widget-tagbox", inputs: ["selectedItems", "displayField", "valueField", "displayFormat", "disabled", "multiple", "isLoading", "validationRules", "placeholder", "hasClearButton", "resolvedCreate", "allowUnselect", "entityDef", "customFilter", "columns", "parentFilters", "rowActions", "onSetLoading"], outputs: ["valueChanged"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
16076
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3$2.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPLookupWidgetSelectComponent, selector: "axp-lookup-widget-select", inputs: ["entityDef", "customFilter", "selectedItems", "displayField", "valueField", "disabled", "multiple", "validationRules", "placeholder", "hasClearButton", "allowCreate", "showItemTooltip", "isItemTruncated", "textTemplate"], outputs: ["valueChanged"] }, { kind: "component", type: AXPLookupWidgetTagboxComponent, selector: "axp-lookup-widget-tagbox", inputs: ["selectedItems", "displayField", "valueField", "displayFormat", "disabled", "multiple", "isLoading", "validationRules", "placeholder", "hasClearButton", "resolvedCreate", "allowUnselect", "entityDef", "customFilter", "columns", "parentFilters", "rowActions", "onSetLoading"], outputs: ["valueChanged"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i3$1.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
15914
16077
  }
15915
16078
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLookupWidgetEditComponent, decorators: [{
15916
16079
  type: Component,
@@ -15928,6 +16091,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
15928
16091
  [selectedItems]="selectedItems"
15929
16092
  [displayField]="displayField"
15930
16093
  [valueField]="valueField"
16094
+ [textTemplate]="textTemplate()"
15931
16095
  [disabled]="disabled"
15932
16096
  [multiple]="multiple"
15933
16097
  [placeholder]="placeholder"