@sd-angular/core 19.0.43 → 19.0.44

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.
@@ -0,0 +1,20 @@
1
+ import { SdTableItem } from '../../models/table-item.model';
2
+ import { SdTableOptionSelector } from '../../models/table-option-selector.model';
3
+ export interface SdSelectionActionKeys {
4
+ /** Key (hash) các action dòng được dùng: action con trước, rồi key action cha khi có ít nhất một con hiện. */
5
+ keys: string[];
6
+ /** Tập con của `keys` thuộc action `isGrouped` (hoặc action cha có con `isGrouped`). */
7
+ grouped: string[];
8
+ }
9
+ /** Tính các action của selector mà dòng được dùng (bỏ action có `hidden` trả về true). Không ghi gì vào dòng. */
10
+ export declare const resolveSelectionActionKeys: <T>(row: SdTableItem<T>, selection?: SdTableOptionSelector<T>) => SdSelectionActionKeys;
11
+ /**
12
+ * Ghi `meta.selector.actions` cho mọi dòng TRƯỚC khi bảng phát danh sách chọn mới (NSP-5934).
13
+ *
14
+ * why: pipe thuần `selectionDisabled` của một dòng so action của dòng đó với action của các dòng đã chọn. Trước đây
15
+ * action của một dòng chỉ được ghi khi ô checkbox của chính dòng đó render (pipe `selectionVisible`). Khi
16
+ * `preserveSelection` khôi phục dòng đã chọn thành object mới sau reload, object đó còn `actions = []` lúc các dòng
17
+ * đứng trên nó render, nên các dòng này bị khoá và pipe thuần không tính lại. Chuẩn bị trước cho mọi dòng thì kết quả
18
+ * không còn phụ thuộc thứ tự render.
19
+ */
20
+ export declare const prepareSelectionActions: <T>(rows: SdTableItem<T>[], selection?: SdTableOptionSelector<T>) => void;
@@ -2571,74 +2571,79 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.21", ngImpo
2571
2571
  }]
2572
2572
  }] });
2573
2573
 
2574
- class SdSelectionVisiblePipe {
2575
- transform = (rowData, selection) => {
2576
- const groupedActions = [];
2577
- rowData.meta.selector.actions = rowData.meta.selector.actions || [];
2578
- if (!selection?.actions?.length) {
2579
- rowData.meta.selector.selectable = true;
2580
- return rowData.meta.selector.selectable;
2581
- }
2582
- for (const action of selection?.actions) {
2583
- if ('children' in action) {
2584
- let flag = false;
2585
- let hasGroup = false;
2586
- for (const child of action.children) {
2587
- const { hidden, isGrouped } = child;
2588
- const key = Utilities.hash(child);
2589
- if (isGrouped) {
2590
- hasGroup = true;
2591
- }
2592
- if (typeof hidden === 'function') {
2593
- if (!hidden(rowData.data)) {
2594
- flag = true;
2595
- rowData.meta.selector.actions.push(key);
2596
- if (isGrouped) {
2597
- groupedActions.push(key);
2598
- }
2599
- }
2600
- }
2601
- else if (!hidden) {
2602
- flag = true;
2603
- rowData.meta.selector.actions.push(key);
2604
- if (isGrouped) {
2605
- groupedActions.push(key);
2606
- }
2607
- }
2608
- }
2609
- if (flag) {
2610
- rowData.meta.selector.actions.push(Utilities.hash(action));
2611
- if (hasGroup) {
2612
- groupedActions.push(Utilities.hash(action));
2613
- }
2614
- }
2574
+ const isShown = (hidden, row) => typeof hidden === 'function' ? !hidden(row.data) : !hidden;
2575
+ /** Tính các action của selector mà dòng được dùng (bỏ action có `hidden` trả về true). Không ghi gì vào dòng. */
2576
+ const resolveSelectionActionKeys = (row, selection) => {
2577
+ const keys = [];
2578
+ const grouped = [];
2579
+ for (const action of selection?.actions ?? []) {
2580
+ if ('children' in action) {
2581
+ let shown = false;
2582
+ let hasGroup = false;
2583
+ for (const child of action.children) {
2584
+ if (child.isGrouped)
2585
+ hasGroup = true;
2586
+ if (!isShown(child.hidden, row))
2587
+ continue;
2588
+ const key = Utilities.hash(child);
2589
+ shown = true;
2590
+ keys.push(key);
2591
+ if (child.isGrouped)
2592
+ grouped.push(key);
2615
2593
  }
2616
- else {
2617
- const { hidden, isGrouped } = action;
2594
+ if (shown) {
2618
2595
  const key = Utilities.hash(action);
2619
- if (typeof hidden === 'function') {
2620
- if (!hidden(rowData.data)) {
2621
- rowData.meta.selector.actions.push(key);
2622
- if (isGrouped) {
2623
- groupedActions.push(key);
2624
- }
2625
- }
2626
- }
2627
- else if (!hidden) {
2628
- rowData.meta.selector.actions.push(key);
2629
- if (isGrouped) {
2630
- groupedActions.push(key);
2631
- }
2632
- }
2596
+ keys.push(key);
2597
+ if (hasGroup)
2598
+ grouped.push(key);
2633
2599
  }
2634
2600
  }
2635
- rowData.meta.selector.selectable = !!rowData.meta.selector.actions?.length;
2636
- if (!rowData.meta.selector.selectable || !groupedActions.length || rowData?.meta.group?.items?.length) {
2637
- return rowData.meta.selector.selectable;
2601
+ else if (isShown(action.hidden, row)) {
2602
+ const key = Utilities.hash(action);
2603
+ keys.push(key);
2604
+ if (action.isGrouped)
2605
+ grouped.push(key);
2606
+ }
2607
+ }
2608
+ return { keys, grouped };
2609
+ };
2610
+ /**
2611
+ * Ghi `meta.selector.actions` cho mọi dòng TRƯỚC khi bảng phát danh sách chọn mới (NSP-5934).
2612
+ *
2613
+ * why: pipe thuần `selectionDisabled` của một dòng so action của dòng đó với action của các dòng đã chọn. Trước đây
2614
+ * action của một dòng chỉ được ghi khi ô checkbox của chính dòng đó render (pipe `selectionVisible`). Khi
2615
+ * `preserveSelection` khôi phục dòng đã chọn thành object mới sau reload, object đó còn `actions = []` lúc các dòng
2616
+ * đứng trên nó render, nên các dòng này bị khoá và pipe thuần không tính lại. Chuẩn bị trước cho mọi dòng thì kết quả
2617
+ * không còn phụ thuộc thứ tự render.
2618
+ */
2619
+ const prepareSelectionActions = (rows, selection) => {
2620
+ if (!selection?.actions?.length)
2621
+ return;
2622
+ for (const row of new Set(rows)) {
2623
+ if (!row.meta.selector)
2624
+ continue;
2625
+ row.meta.selector.actions = resolveSelectionActionKeys(row, selection).keys;
2626
+ }
2627
+ };
2628
+
2629
+ class SdSelectionVisiblePipe {
2630
+ transform = (rowData, selection) => {
2631
+ const selector = rowData.meta.selector;
2632
+ if (!selection?.actions?.length) {
2633
+ selector.actions = selector.actions || [];
2634
+ selector.selectable = true;
2635
+ return selector.selectable;
2636
+ }
2637
+ // why: gán lại thay vì push để key không bị nhân đôi khi bảng đã chuẩn bị trước (prepareSelectionActions).
2638
+ const { keys, grouped } = resolveSelectionActionKeys(rowData, selection);
2639
+ selector.actions = keys;
2640
+ selector.selectable = !!keys.length;
2641
+ if (!selector.selectable || !grouped.length || rowData?.meta.group?.items?.length) {
2642
+ return selector.selectable;
2638
2643
  }
2639
2644
  // Đối với trường hợp grouped, tuy selectable là true nhưng vẫn ẩn đi checkbox
2640
2645
  // nếu các action đều thuộc groupedActions và rowData ko phải là dòng group
2641
- return rowData.meta.selector.actions.some(action => !groupedActions.includes(action));
2646
+ return keys.some(action => !grouped.includes(action));
2642
2647
  };
2643
2648
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.21", ngImport: i0, type: SdSelectionVisiblePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
2644
2649
  static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.21", ngImport: i0, type: SdSelectionVisiblePipe, isStandalone: true, name: "selectionVisible" });
@@ -4777,14 +4782,15 @@ class SdTable {
4777
4782
  };
4778
4783
  #updateSelectedItems = () => {
4779
4784
  const rows = this.#getSelectionRows();
4780
- if (this.#preserveEnabled()) {
4781
- // Sync map theo state visible: add nếu selected, remove nếu deselected.
4782
- // Off-page items giữ nguyên trong map (không bị visit ở đây).
4783
- this.selectedTableItems.set(syncPreservedSelection(rows, this.#preservedSelectedMap));
4784
- }
4785
- else {
4786
- this.selectedTableItems.set(rows.filter(item => item.meta.selector.isSelected));
4787
- }
4785
+ // Sync map theo state visible: add nếu selected, remove nếu deselected.
4786
+ // Off-page items giữ nguyên trong map (không bị visit ở đây).
4787
+ const selected = this.#preserveEnabled()
4788
+ ? syncPreservedSelection(rows, this.#preservedSelectedMap)
4789
+ : rows.filter(item => item.meta.selector.isSelected);
4790
+ // why: dòng đã chọn khôi phục sau reload là object mới chưa có action; chuẩn bị action cho mọi dòng trước khi
4791
+ // phát danh sách chọn để pipe selectionDisabled không khoá nhầm các dòng render trước nó (NSP-5934).
4792
+ prepareSelectionActions([...rows, ...selected], this.tableOption()?.selector);
4793
+ this.selectedTableItems.set(selected);
4788
4794
  this.#ref.detectChanges();
4789
4795
  };
4790
4796
  clearFilter = () => {