@dereekb/dbx-form 13.11.1 → 13.11.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.
|
@@ -6,7 +6,7 @@ import { isPast, addSeconds, startOfDay, addMinutes, addDays, isBefore } from 'd
|
|
|
6
6
|
import { map, of, shareReplay, switchMap, first, exhaustMap, catchError, delay, filter, combineLatest, distinctUntilChanged, BehaviorSubject, Subject, startWith, throttleTime, scan, timer, merge, EMPTY, skip, debounceTime, combineLatestWith, interval, tap, withLatestFrom, mergeMap } from 'rxjs';
|
|
7
7
|
import * as i1$2 from '@dereekb/dbx-core';
|
|
8
8
|
import { DbxActionContextStoreSourceInstance, cleanLockSet, cleanSubscription, completeOnDestroy, cleanWithLockSet, GetValuePipe, DateDistancePipe, TimeDistancePipe, DbxInjectionComponent, mergeDbxInjectionComponentConfigs } from '@dereekb/dbx-core';
|
|
9
|
-
import { makeIsModifiedFunctionObservable, asObservable, LockSet, filterMaybe, switchMapFilterMaybe, scanCount, errorOnEmissionsInPeriod, asObservableFromGetter,
|
|
9
|
+
import { makeIsModifiedFunctionObservable, asObservable, LockSet, filterMaybe, switchMapFilterMaybe, scanCount, errorOnEmissionsInPeriod, asObservableFromGetter, maybeValueFromObservableOrValue, valueFromFinishedLoadingState, switchMapMaybeDefault, skipAllInitialMaybe, successResult, startWithBeginLoading, skipUntilTimeElapsedAfterLastEmission, mapLoadingStateResults, isLoadingStateWithDefinedValue, isLoadingStateLoading, beginLoading, mapLoadingStateValueWithOperator, loadingStateContext, distinctUntilHasDifferentValues, SimpleLoadingContext, listLoadingStateContext, mapIsListLoadingStateWithEmptyValue, isLoadingStateInLoadingState, asyncPusherCache } from '@dereekb/rxjs';
|
|
10
10
|
import { toObservable, toSignal, rxResource } from '@angular/core/rxjs-interop';
|
|
11
11
|
import { BooleanStringKeyArrayUtility, iterablesAreSetEquivalent, filterUndefinedValues, filterMaybeArrayValues, filterUniqueValues, areEqualPOJOValuesUsingPojoFilter, NOOP_MODIFIER, asArray, mergeArrays, filterNullAndUndefinedValues, objectHasNoKeys, mapMaybeFunction, isWebsiteUrlWithPrefix, websiteUrlDetails, transformStringFunction, US_STATE_CODE_STRING_REGEX, ZIP_CODE_STRING_REGEX, LAT_LNG_PATTERN, transformNumberFunction, DOLLAR_AMOUNT_PRECISION, stripObject, getValueFromGetter, asGetter, dateFromMinuteOfDay, dateToMinuteOfDay, isISO8601DayStringStart, mapIdentityFunction, isDate, MS_IN_MINUTE, isMonthDaySlashDate, filterFromPOJO, TIME_UNIT_SHORT_LABEL_MAP, timeUnitToMilliseconds, ALL_TIME_UNITS, minutesToHoursAndMinutes, millisecondsToTimeUnit, hoursAndMinutesToTimeUnit, isE164PhoneNumber as isE164PhoneNumber$1, isValidPhoneExtensionNumber, e164PhoneNumberExtensionPair, e164PhoneNumberFromE164PhoneNumberExtensionPair, mergeArraysIntoArray, convertMaybeToArray, lastValue, filterEmptyArrayValues, setContainsAllValues, addToSetCopy, setsAreEquivalent, makeValuesGroupMap, sortByStringFunction, separateValues, isSelectedDecisionFunctionFactory, readKeysFrom, hasDifferentValues, capitalizeFirstLetter, objectIsEmpty, mergeObjectsFunction, filterFromPOJOFunction, mergeObjects, addPlusPrefixToNumber, searchStringFilterFunction, caseInsensitiveFilterByIndexOfDecisionFactory, arrayToMap, firstValue, cachedGetter, makeGetter, asDecisionFunction, TIME_UNIT_LABEL_MAP, HAS_WEBSITE_DOMAIN_NAME_REGEX, KeyValueTypleValueFilter, valuesFromPOJO, allObjectsAreEqual, isNumberDivisibleBy, nearestDivisibleValues, concatArrays } from '@dereekb/util';
|
|
12
12
|
import * as i1 from '@angular/forms';
|
|
@@ -1166,6 +1166,11 @@ function isEmptyFormValue(val) {
|
|
|
1166
1166
|
* from a form value object. Also removes keys whose values become empty objects
|
|
1167
1167
|
* `{}` after recursive stripping.
|
|
1168
1168
|
*
|
|
1169
|
+
* Arrays are recursed into so that empties inside nested objects are stripped,
|
|
1170
|
+
* but array length and item indices are preserved — primitive empty values
|
|
1171
|
+
* (e.g. `NaN`, `''`) inside an array stay in place, since shifting indices would
|
|
1172
|
+
* change the semantics of chip/list-style array fields.
|
|
1173
|
+
*
|
|
1169
1174
|
* This normalizes ng-forge output to match ngx-formly behavior, where the model
|
|
1170
1175
|
* only includes keys that have been explicitly set by the user.
|
|
1171
1176
|
*
|
|
@@ -1176,6 +1181,9 @@ function isEmptyFormValue(val) {
|
|
|
1176
1181
|
*
|
|
1177
1182
|
* stripEmptyForgeValues({ section: { a: "", b: "" } })
|
|
1178
1183
|
* // → {}
|
|
1184
|
+
*
|
|
1185
|
+
* stripEmptyForgeValues({ items: [{ amount: NaN, name: 'a' }, { amount: 5 }] })
|
|
1186
|
+
* // → { items: [{ name: 'a' }, { amount: 5 }] }
|
|
1179
1187
|
* ```
|
|
1180
1188
|
*
|
|
1181
1189
|
* @param value - The form value object to clean
|
|
@@ -1183,18 +1191,24 @@ function isEmptyFormValue(val) {
|
|
|
1183
1191
|
*/
|
|
1184
1192
|
function stripEmptyForgeValues(value) {
|
|
1185
1193
|
let result;
|
|
1186
|
-
if (value == null || typeof value !== 'object' ||
|
|
1194
|
+
if (value == null || typeof value !== 'object' || value instanceof Date) {
|
|
1187
1195
|
result = value;
|
|
1188
1196
|
}
|
|
1197
|
+
else if (Array.isArray(value)) {
|
|
1198
|
+
result = value.map((item) => stripEmptyForgeValues(item));
|
|
1199
|
+
}
|
|
1189
1200
|
else {
|
|
1190
1201
|
const stripped = {};
|
|
1191
1202
|
for (const [key, val] of Object.entries(value)) {
|
|
1192
1203
|
if (isEmptyFormValue(val)) {
|
|
1193
1204
|
continue;
|
|
1194
1205
|
}
|
|
1195
|
-
if (typeof val === 'object' && !
|
|
1206
|
+
if (typeof val === 'object' && !(val instanceof Date)) {
|
|
1196
1207
|
const cleaned = stripEmptyForgeValues(val);
|
|
1197
|
-
if (
|
|
1208
|
+
if (Array.isArray(cleaned)) {
|
|
1209
|
+
stripped[key] = cleaned;
|
|
1210
|
+
}
|
|
1211
|
+
else if (cleaned != null && Object.keys(cleaned).length > 0) {
|
|
1198
1212
|
stripped[key] = cleaned;
|
|
1199
1213
|
}
|
|
1200
1214
|
}
|
|
@@ -1236,7 +1250,7 @@ class DbxForgeFormContext {
|
|
|
1236
1250
|
*/
|
|
1237
1251
|
stripInternalKeys = true;
|
|
1238
1252
|
/**
|
|
1239
|
-
* When true (default), keys whose values are empty (`null`, `undefined`,
|
|
1253
|
+
* When true (default), keys whose values are empty (`null`, `undefined`, `""`, or `NaN`)
|
|
1240
1254
|
* are stripped from the form value before emission. This normalizes ng-forge output
|
|
1241
1255
|
* to match ngx-formly behavior, where the model only includes keys that have been
|
|
1242
1256
|
* explicitly set by the user.
|
|
@@ -1323,7 +1337,7 @@ class DbxForgeFormContext {
|
|
|
1323
1337
|
_isValid = new BehaviorSubject(false);
|
|
1324
1338
|
_setValue = new BehaviorSubject(undefined);
|
|
1325
1339
|
_reset = new BehaviorSubject(new Date());
|
|
1326
|
-
_internalConfig$ = this._config.pipe(
|
|
1340
|
+
_internalConfig$ = this._config.pipe(scan((acc, config) => {
|
|
1327
1341
|
let result;
|
|
1328
1342
|
if (config) {
|
|
1329
1343
|
if (acc?.input !== config) {
|
|
@@ -1337,8 +1351,8 @@ class DbxForgeFormContext {
|
|
|
1337
1351
|
result = undefined;
|
|
1338
1352
|
}
|
|
1339
1353
|
return result;
|
|
1340
|
-
}, undefined),
|
|
1341
|
-
config$ = this._internalConfig$.pipe(filterMaybe(), map(({ config }) => config),
|
|
1354
|
+
}, undefined), shareReplay(1));
|
|
1355
|
+
config$ = this._internalConfig$.pipe(filterMaybe(), map(({ config }) => config), shareReplay(1));
|
|
1342
1356
|
/**
|
|
1343
1357
|
* Form event stream that restarts on each reset, mirroring the formly form's
|
|
1344
1358
|
* switchMap-on-reset pattern. This ensures that each resetForm() produces a fresh
|
|
@@ -1577,7 +1591,7 @@ class DbxForgeFormComponent {
|
|
|
1577
1591
|
_disabledSub = cleanSubscription();
|
|
1578
1592
|
dynamicForm = viewChild(DynamicForm, ...(ngDevMode ? [{ debugName: "dynamicForm" }] : /* istanbul ignore next */ []));
|
|
1579
1593
|
formValue = signal({}, { ...(ngDevMode ? { debugName: "formValue" } : /* istanbul ignore next */ {}), equal: (a, b) => _forgeFormValueEqual(a, b, this._context) });
|
|
1580
|
-
configSignal = toSignal(this._context.config
|
|
1594
|
+
configSignal = toSignal(this._context.config$, { initialValue: undefined });
|
|
1581
1595
|
_changesCount = signal(0, ...(ngDevMode ? [{ debugName: "_changesCount" }] : /* istanbul ignore next */ []));
|
|
1582
1596
|
_lastResetAt = signal(new Date(), ...(ngDevMode ? [{ debugName: "_lastResetAt" }] : /* istanbul ignore next */ []));
|
|
1583
1597
|
_isReset = signal(true, ...(ngDevMode ? [{ debugName: "_isReset" }] : /* istanbul ignore next */ []));
|
|
@@ -1996,8 +2010,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.11", ngImpo
|
|
|
1996
2010
|
class DbxFormLoggerDirective {
|
|
1997
2011
|
form = inject(DbxForm, { host: true });
|
|
1998
2012
|
constructor() {
|
|
1999
|
-
cleanSubscription(this.form.stream
|
|
2000
|
-
console.log('dbxFormLogger - stream: ', event);
|
|
2013
|
+
cleanSubscription(combineLatest([this.form.getValue(), this.form.stream$]).subscribe(([currentValue, event]) => {
|
|
2014
|
+
console.log('dbxFormLogger - stream: ', { currentValue, event });
|
|
2001
2015
|
}));
|
|
2002
2016
|
}
|
|
2003
2017
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.11", ngImport: i0, type: DbxFormLoggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
@@ -8105,8 +8119,8 @@ class DbxForgeValueSelectionFieldComponent {
|
|
|
8105
8119
|
addClearOptionSignal = computed(() => this.props()?.addClearOption, ...(ngDevMode ? [{ debugName: "addClearOptionSignal" }] : /* istanbul ignore next */ []));
|
|
8106
8120
|
addClearOption$ = toObservable(this.addClearOptionSignal).pipe(distinctUntilChanged());
|
|
8107
8121
|
inputOptionsSignal = computed(() => this.props()?.options, ...(ngDevMode ? [{ debugName: "inputOptionsSignal" }] : /* istanbul ignore next */ []));
|
|
8108
|
-
inputOptions$ = toObservable(this.inputOptionsSignal).pipe(
|
|
8109
|
-
resolvedOptions$ = combineLatest([this.inputOptions$, this.addClearOption$]).pipe(
|
|
8122
|
+
inputOptions$ = toObservable(this.inputOptionsSignal).pipe(maybeValueFromObservableOrValue());
|
|
8123
|
+
resolvedOptions$ = combineLatest([this.inputOptions$, this.addClearOption$]).pipe(map(([options, addClearOption]) => resolveForgeSelectionOptions(options ?? [], addClearOption ?? false)));
|
|
8110
8124
|
resolvedOptionsSignal = toSignal(this.resolvedOptions$);
|
|
8111
8125
|
multipleSignal = computed(() => this.props()?.multiple ?? false, ...(ngDevMode ? [{ debugName: "multipleSignal" }] : /* istanbul ignore next */ []));
|
|
8112
8126
|
effectiveAppearance = computed(() => this.props()?.appearance ?? this.materialConfig?.appearance ?? 'outline', ...(ngDevMode ? [{ debugName: "effectiveAppearance" }] : /* istanbul ignore next */ []));
|