@aquera/ngx-smart-table 0.0.16-alpha → 0.0.17-patch-0.1
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.
- package/esm2020/lib/editors/nile-select-editor.mjs +111 -30
- package/fesm2015/aquera-ngx-smart-table.mjs +114 -31
- package/fesm2015/aquera-ngx-smart-table.mjs.map +1 -1
- package/fesm2020/aquera-ngx-smart-table.mjs +110 -29
- package/fesm2020/aquera-ngx-smart-table.mjs.map +1 -1
- package/lib/editors/nile-select-editor.d.ts +4 -0
- package/package.json +1 -1
|
@@ -3678,6 +3678,8 @@ class NileSelectEditor {
|
|
|
3678
3678
|
this.acceptsInitialKeypress = false;
|
|
3679
3679
|
this.eventListeners = [];
|
|
3680
3680
|
this.currentOptions = [];
|
|
3681
|
+
this.trackedValues = []; // Track selected values for virtual scroll
|
|
3682
|
+
this.hasChangeOccurred = false; // Whether a nile-change event has fired
|
|
3681
3683
|
// Handle Observable options
|
|
3682
3684
|
if (isObservable(options.options)) {
|
|
3683
3685
|
this.optionsSubscription = options.options.subscribe(opts => {
|
|
@@ -3721,13 +3723,15 @@ class NileSelectEditor {
|
|
|
3721
3723
|
// Clear container and append select
|
|
3722
3724
|
context.container.innerHTML = '';
|
|
3723
3725
|
context.container.appendChild(this.select);
|
|
3724
|
-
// Focus
|
|
3726
|
+
// Focus the select after render
|
|
3725
3727
|
setTimeout(() => {
|
|
3726
|
-
|
|
3727
|
-
this.select
|
|
3728
|
-
this.select.open = true;
|
|
3728
|
+
try {
|
|
3729
|
+
this.select?.focus();
|
|
3729
3730
|
}
|
|
3730
|
-
|
|
3731
|
+
catch (e) {
|
|
3732
|
+
// Ignore errors
|
|
3733
|
+
}
|
|
3734
|
+
}, 50);
|
|
3731
3735
|
}
|
|
3732
3736
|
/**
|
|
3733
3737
|
* Set the initial value for the select
|
|
@@ -3735,21 +3739,26 @@ class NileSelectEditor {
|
|
|
3735
3739
|
setInitialValue(value) {
|
|
3736
3740
|
if (!this.select)
|
|
3737
3741
|
return;
|
|
3742
|
+
this.hasChangeOccurred = false;
|
|
3738
3743
|
if (this.options.multiple) {
|
|
3739
3744
|
// Handle multiple selection - value should be array
|
|
3740
3745
|
if (Array.isArray(value)) {
|
|
3741
3746
|
this.select.value = value;
|
|
3747
|
+
this.trackedValues = [...value]; // Initialize tracked values
|
|
3742
3748
|
}
|
|
3743
3749
|
else if (value) {
|
|
3744
3750
|
this.select.value = [String(value)];
|
|
3751
|
+
this.trackedValues = [String(value)];
|
|
3745
3752
|
}
|
|
3746
3753
|
else {
|
|
3747
3754
|
this.select.value = [];
|
|
3755
|
+
this.trackedValues = [];
|
|
3748
3756
|
}
|
|
3749
3757
|
}
|
|
3750
3758
|
else {
|
|
3751
3759
|
// Handle single selection
|
|
3752
3760
|
this.select.value = value ? String(value) : '';
|
|
3761
|
+
this.trackedValues = value ? [String(value)] : [];
|
|
3753
3762
|
}
|
|
3754
3763
|
}
|
|
3755
3764
|
/**
|
|
@@ -3833,12 +3842,17 @@ class NileSelectEditor {
|
|
|
3833
3842
|
updateOptions() {
|
|
3834
3843
|
if (!this.select)
|
|
3835
3844
|
return;
|
|
3836
|
-
//
|
|
3837
|
-
|
|
3838
|
-
this.
|
|
3845
|
+
// For virtual scroll mode, just update the data property (no DOM children to clear)
|
|
3846
|
+
if (this.options.enableVirtualScroll) {
|
|
3847
|
+
this.createAndAppendOptions(this.currentOptions);
|
|
3848
|
+
}
|
|
3849
|
+
else {
|
|
3850
|
+
// Standard mode: clear existing nile-option elements first
|
|
3851
|
+
while (this.select.firstChild) {
|
|
3852
|
+
this.select.removeChild(this.select.firstChild);
|
|
3853
|
+
}
|
|
3854
|
+
this.createAndAppendOptions(this.currentOptions);
|
|
3839
3855
|
}
|
|
3840
|
-
// Re-append with new options
|
|
3841
|
-
this.createAndAppendOptions(this.currentOptions);
|
|
3842
3856
|
// Trigger update on the web component
|
|
3843
3857
|
if (this.select.requestUpdate) {
|
|
3844
3858
|
this.select.requestUpdate();
|
|
@@ -3846,11 +3860,22 @@ class NileSelectEditor {
|
|
|
3846
3860
|
}
|
|
3847
3861
|
/**
|
|
3848
3862
|
* Create NileOption elements and append them to the select
|
|
3863
|
+
* When enableVirtualScroll is true, uses data property instead of DOM elements
|
|
3864
|
+
* @see https://nile.aqueralabs.com/select-virtual?theme=enterprise
|
|
3849
3865
|
* @param options - The options to render
|
|
3850
3866
|
*/
|
|
3851
3867
|
createAndAppendOptions(options) {
|
|
3852
3868
|
if (!this.select)
|
|
3853
3869
|
return;
|
|
3870
|
+
// Virtual scroll mode: use data property instead of DOM elements
|
|
3871
|
+
if (this.options.enableVirtualScroll) {
|
|
3872
|
+
const virtualData = options.map(opt => typeof opt === 'string'
|
|
3873
|
+
? { value: opt, label: opt }
|
|
3874
|
+
: { value: opt.value, label: opt.label, disabled: opt.disabled });
|
|
3875
|
+
this.select.data = virtualData;
|
|
3876
|
+
return;
|
|
3877
|
+
}
|
|
3878
|
+
// Standard mode: create nile-option elements
|
|
3854
3879
|
options.forEach(opt => {
|
|
3855
3880
|
const nileOption = document.createElement('nile-option');
|
|
3856
3881
|
// Auto-detect format: string or SelectOption object
|
|
@@ -3899,15 +3924,38 @@ class NileSelectEditor {
|
|
|
3899
3924
|
if (!this.options.multiple) {
|
|
3900
3925
|
const changeHandler = (e) => {
|
|
3901
3926
|
const customEvent = e;
|
|
3902
|
-
|
|
3903
|
-
this.select
|
|
3904
|
-
|
|
3927
|
+
try {
|
|
3928
|
+
if (validateOnSave && this.select && !this.select.checkValidity()) {
|
|
3929
|
+
this.select.reportValidity();
|
|
3930
|
+
return;
|
|
3931
|
+
}
|
|
3932
|
+
}
|
|
3933
|
+
catch (err) {
|
|
3934
|
+
// Ignore validation errors - nile-select internals may not be ready
|
|
3905
3935
|
}
|
|
3906
3936
|
context.onSave(this.parseValue(customEvent.detail.value));
|
|
3907
3937
|
};
|
|
3908
3938
|
this.select.addEventListener('nile-change', changeHandler);
|
|
3909
3939
|
this.eventListeners.push({ event: 'nile-change', handler: changeHandler });
|
|
3910
3940
|
}
|
|
3941
|
+
// For multi-select, track value changes (needed for virtual scroll where value property doesn't update)
|
|
3942
|
+
if (this.options.multiple) {
|
|
3943
|
+
const trackValueHandler = (e) => {
|
|
3944
|
+
const customEvent = e;
|
|
3945
|
+
const newValue = customEvent.detail?.value;
|
|
3946
|
+
if (newValue !== undefined) {
|
|
3947
|
+
this.hasChangeOccurred = true;
|
|
3948
|
+
if (Array.isArray(newValue)) {
|
|
3949
|
+
this.trackedValues = [...newValue];
|
|
3950
|
+
}
|
|
3951
|
+
else {
|
|
3952
|
+
this.trackedValues = newValue ? [newValue] : [];
|
|
3953
|
+
}
|
|
3954
|
+
}
|
|
3955
|
+
};
|
|
3956
|
+
this.select.addEventListener('nile-change', trackValueHandler);
|
|
3957
|
+
this.eventListeners.push({ event: 'nile-change', handler: trackValueHandler });
|
|
3958
|
+
}
|
|
3911
3959
|
// Track if save was already triggered (to prevent double save)
|
|
3912
3960
|
let saveTriggered = false;
|
|
3913
3961
|
// Use mousedown on document to detect clicks outside the select and portal
|
|
@@ -3916,23 +3964,47 @@ class NileSelectEditor {
|
|
|
3916
3964
|
return;
|
|
3917
3965
|
if (!this.select)
|
|
3918
3966
|
return;
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
if
|
|
3922
|
-
|
|
3967
|
+
// Use composedPath to traverse shadow DOM boundaries
|
|
3968
|
+
const path = e.composedPath();
|
|
3969
|
+
// Check if click is inside the select element or any nile-select related elements
|
|
3970
|
+
for (const element of path) {
|
|
3971
|
+
if (!(element instanceof HTMLElement))
|
|
3972
|
+
continue;
|
|
3973
|
+
// Check if it's our select element
|
|
3974
|
+
if (element === this.select) {
|
|
3975
|
+
return;
|
|
3976
|
+
}
|
|
3977
|
+
// Check for nile-select portals (various class names)
|
|
3978
|
+
if (element.classList?.contains('nile-select-portal-append') ||
|
|
3979
|
+
element.classList?.contains('select__listbox') ||
|
|
3980
|
+
element.classList?.contains('select__options') ||
|
|
3981
|
+
element.tagName?.toLowerCase() === 'nile-option' ||
|
|
3982
|
+
element.tagName?.toLowerCase() === 'nile-select') {
|
|
3983
|
+
return;
|
|
3984
|
+
}
|
|
3985
|
+
// Check for any element with nile-select in its class
|
|
3986
|
+
if (element.className && typeof element.className === 'string' &&
|
|
3987
|
+
element.className.includes('nile-select')) {
|
|
3988
|
+
return;
|
|
3989
|
+
}
|
|
3923
3990
|
}
|
|
3924
|
-
//
|
|
3925
|
-
const portals = document.querySelectorAll('.nile-select-portal-append');
|
|
3991
|
+
// Also check portal containers directly
|
|
3992
|
+
const portals = document.querySelectorAll('.nile-select-portal-append, [class*="select__listbox"]');
|
|
3926
3993
|
for (let i = 0; i < portals.length; i++) {
|
|
3927
|
-
if (portals[i].contains(target)) {
|
|
3994
|
+
if (portals[i].contains(e.target)) {
|
|
3928
3995
|
return;
|
|
3929
3996
|
}
|
|
3930
3997
|
}
|
|
3931
3998
|
// Click is outside - save and exit
|
|
3932
3999
|
saveTriggered = true;
|
|
3933
|
-
|
|
3934
|
-
this.select
|
|
3935
|
-
|
|
4000
|
+
try {
|
|
4001
|
+
if (validateOnSave && this.select && !this.select.checkValidity()) {
|
|
4002
|
+
this.select.reportValidity();
|
|
4003
|
+
return;
|
|
4004
|
+
}
|
|
4005
|
+
}
|
|
4006
|
+
catch (err) {
|
|
4007
|
+
// Ignore validation errors - nile-select internals may not be ready
|
|
3936
4008
|
}
|
|
3937
4009
|
context.onSave(this.getCurrentValue());
|
|
3938
4010
|
};
|
|
@@ -4000,19 +4072,28 @@ class NileSelectEditor {
|
|
|
4000
4072
|
}
|
|
4001
4073
|
}
|
|
4002
4074
|
focus() {
|
|
4003
|
-
|
|
4075
|
+
try {
|
|
4076
|
+
this.select?.focus();
|
|
4077
|
+
}
|
|
4078
|
+
catch (e) {
|
|
4079
|
+
// Ignore focus errors - nile-select internals may not be ready
|
|
4080
|
+
}
|
|
4004
4081
|
}
|
|
4005
4082
|
getCurrentValue() {
|
|
4006
4083
|
if (!this.select) {
|
|
4007
4084
|
return (this.options.multiple ? [] : '');
|
|
4008
4085
|
}
|
|
4009
|
-
const value = this.select.value;
|
|
4010
|
-
// Handle multiple selection
|
|
4011
4086
|
if (this.options.multiple) {
|
|
4012
|
-
|
|
4087
|
+
// If a change event fired, always use trackedValues (even if empty = all unchecked).
|
|
4088
|
+
// Only fall back to the component value when no change has occurred yet.
|
|
4089
|
+
let values = this.hasChangeOccurred ? this.trackedValues : this.select.value;
|
|
4090
|
+
if (Array.isArray(values)) {
|
|
4091
|
+
return values.filter((v) => v !== undefined && v !== null && v !== '');
|
|
4092
|
+
}
|
|
4093
|
+
return (values ? [values] : []);
|
|
4013
4094
|
}
|
|
4014
|
-
|
|
4015
|
-
return (Array.isArray(value) ? (value.length > 0 ? value[0] : '') : value);
|
|
4095
|
+
let value = this.hasChangeOccurred ? (this.trackedValues[0] ?? '') : this.select.value;
|
|
4096
|
+
return (Array.isArray(value) ? (value.length > 0 ? value[0] : '') : (value || ''));
|
|
4016
4097
|
}
|
|
4017
4098
|
}
|
|
4018
4099
|
|