@gravitee/ui-particles-angular 17.7.4 → 17.7.5-improve-displayif-disabledif-d7261b3

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.
@@ -3000,15 +3000,8 @@ class GioFormlyJsonSchemaService {
3000
3000
  mappedField.expressions = {
3001
3001
  ...mappedField.expressions,
3002
3002
  hide: field => {
3003
- let parentField = field;
3004
- while (parentField.parent) {
3005
- parentField = parentField.parent;
3006
- }
3007
3003
  try {
3008
- return !displayIf({
3009
- value: parentField.model,
3010
- context,
3011
- });
3004
+ return !displayIf({ field, context });
3012
3005
  }
3013
3006
  catch (e) {
3014
3007
  // Ignore the error and display the field
@@ -3108,15 +3101,8 @@ class GioFormlyJsonSchemaService {
3108
3101
  // if the parent is already disabled there is no need to change anything at the child level
3109
3102
  return false;
3110
3103
  }
3111
- let parentField = field;
3112
- while (parentField.parent) {
3113
- parentField = parentField.parent;
3114
- }
3115
3104
  try {
3116
- const isDisabled = disableIf({
3117
- value: parentField.model,
3118
- context,
3119
- });
3105
+ const isDisabled = disableIf({ field, context });
3120
3106
  // Useful when full form is re-enabled to sync the fromControl enable/disable state
3121
3107
  isDisabled ? field.formControl?.disable({ emitEvent: false }) : field.formControl?.enable({ emitEvent: false });
3122
3108
  return isDisabled;
@@ -3276,18 +3262,90 @@ const getGioIf = (gioIf) => {
3276
3262
  if (isNil($eq) || !isObject($eq)) {
3277
3263
  return undefined;
3278
3264
  }
3279
- return objectToCheck => {
3280
- if (isEmpty(objectToCheck)) {
3265
+ return ({ field, context }) => {
3266
+ if (!field) {
3281
3267
  return false;
3282
3268
  }
3283
3269
  return Object.entries($eq)
3284
3270
  .map(([k, v]) => ({ path: k, eqValue: castArray(v) }))
3285
3271
  .every(({ path, eqValue }) => {
3286
- const value = get(objectToCheck, path);
3272
+ const value = resolveGioIfPath(path, field, context);
3287
3273
  return eqValue.includes(value);
3288
3274
  });
3289
3275
  };
3290
3276
  };
3277
+ /**
3278
+ * Resolves a `displayIf` / `disableIf` path against the form state.
3279
+ *
3280
+ * Path syntax (backward compatible):
3281
+ * - `value.<dotPath>` / `context.<dotPath>` → root model / external context (legacy)
3282
+ * - `./<dotPath>` → current scope (`field.model`)
3283
+ * - `../<dotPath>` (any depth) → walks up the ancestor chain by one
3284
+ * scope per `..`, where a "scope" is an
3285
+ * ancestor whose `model` differs from
3286
+ * the previous one (Formly wrappers that
3287
+ * share the same model are skipped).
3288
+ *
3289
+ * Relative paths let conditions inside an array item (or a sub-object of an item)
3290
+ * reference siblings or item-level fields, which is impossible with `value.` since
3291
+ * the array index of the current row is unknown.
3292
+ */
3293
+ const resolveGioIfPath = (path, field, context) => {
3294
+ if (path === 'value' || path.startsWith('value.')) {
3295
+ const root = getRootModel(field);
3296
+ return path === 'value' ? root : get(root, path.slice('value.'.length));
3297
+ }
3298
+ if (path === 'context' || path.startsWith('context.')) {
3299
+ return path === 'context' ? context : get(context, path.slice('context.'.length));
3300
+ }
3301
+ if (path.startsWith('./') || path.startsWith('../') || path === '.' || path === '..') {
3302
+ let upCount = 0;
3303
+ let rest = path;
3304
+ let consumed = true;
3305
+ while (consumed) {
3306
+ consumed = false;
3307
+ if (rest.startsWith('../')) {
3308
+ upCount++;
3309
+ rest = rest.slice(3);
3310
+ consumed = true;
3311
+ }
3312
+ else if (rest === '..') {
3313
+ upCount++;
3314
+ rest = '';
3315
+ }
3316
+ else if (rest.startsWith('./')) {
3317
+ rest = rest.slice(2);
3318
+ consumed = true;
3319
+ }
3320
+ else if (rest === '.') {
3321
+ rest = '';
3322
+ }
3323
+ }
3324
+ const scope = getModelChain(field)[upCount];
3325
+ return rest === '' ? scope : get(scope, rest);
3326
+ }
3327
+ return undefined;
3328
+ };
3329
+ const getRootModel = (field) => {
3330
+ let cur = field;
3331
+ while (cur.parent)
3332
+ cur = cur.parent;
3333
+ return cur.model;
3334
+ };
3335
+ const getModelChain = (field) => {
3336
+ const chain = [];
3337
+ let cur = field;
3338
+ let last = MODEL_CHAIN_SENTINEL;
3339
+ while (cur) {
3340
+ if (cur.model !== last) {
3341
+ chain.push(cur.model);
3342
+ last = cur.model;
3343
+ }
3344
+ cur = cur.parent;
3345
+ }
3346
+ return chain;
3347
+ };
3348
+ const MODEL_CHAIN_SENTINEL = Symbol('model-chain-sentinel');
3291
3349
 
3292
3350
  /*
3293
3351
  * Copyright (C) 2023 The Gravitee team (http://gravitee.io)