mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
refactor(forms): use when consistently for conditional rules and validators
This commit updates the signal forms API to use a consistent 'when' parameter for conditional rules and validators, replacing direct function arguments.
This commit is contained in:
parent
7745365910
commit
df54e6a7b2
23 changed files with 197 additions and 130 deletions
|
|
@ -15,8 +15,9 @@ import type {FieldContext, LogicFn, PathKind, SchemaPath, SchemaPathRules} from
|
|||
* validation, touched/dirty, or other state of its parent field.
|
||||
*
|
||||
* @param path The target path to add the disabled logic to.
|
||||
* @param logic A reactive function that returns `true` (or a string reason) when the field is disabled,
|
||||
* and `false` when it is not disabled.
|
||||
* @param config Optional configuration object.
|
||||
* - `when`: A reactive function that returns `true` (or a string reason) when the field is disabled,
|
||||
* and `false` when it is not disabled. Can also be a static string reason.
|
||||
* @template TValue The type of value stored in the field the logic is bound to.
|
||||
* @template TPathKind The kind of path the logic is bound to (a root path, child path, or item of an array)
|
||||
*
|
||||
|
|
@ -25,17 +26,17 @@ import type {FieldContext, LogicFn, PathKind, SchemaPath, SchemaPathRules} from
|
|||
*/
|
||||
export function disabled<TValue, TPathKind extends PathKind = PathKind.Root>(
|
||||
path: SchemaPath<TValue, SchemaPathRules.Supported, TPathKind>,
|
||||
logic?: string | NoInfer<LogicFn<TValue, boolean | string, TPathKind>>,
|
||||
config?: {when?: string | NoInfer<LogicFn<TValue, boolean | string, TPathKind>>},
|
||||
): void {
|
||||
assertPathIsCurrent(path);
|
||||
|
||||
const pathNode = FieldPathNode.unwrapFieldPath(path);
|
||||
pathNode.builder.addDisabledReasonRule((ctx) => {
|
||||
let result: boolean | string = true;
|
||||
if (typeof logic === 'string') {
|
||||
result = logic;
|
||||
} else if (logic) {
|
||||
result = logic(ctx as FieldContext<TValue, TPathKind>);
|
||||
if (typeof config?.when === 'string') {
|
||||
result = config.when;
|
||||
} else if (config?.when) {
|
||||
result = config.when(ctx as FieldContext<TValue, TPathKind>);
|
||||
}
|
||||
if (typeof result === 'string') {
|
||||
return {fieldTree: ctx.fieldTree, message: result};
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@ import type {LogicFn, PathKind, SchemaPath, SchemaPathRules} from '../types';
|
|||
* ```
|
||||
*
|
||||
* @param path The target path to add the hidden logic to.
|
||||
* @param logic A reactive function that returns `true` when the field is hidden.
|
||||
* @param config Options object containing the `when` condition.
|
||||
* - `when`: A reactive function that returns `true` when the field is hidden.
|
||||
* @template TValue The type of value stored in the field the logic is bound to.
|
||||
* @template TPathKind The kind of path the logic is bound to (a root path, child path, or item of an array)
|
||||
*
|
||||
|
|
@ -32,10 +33,10 @@ import type {LogicFn, PathKind, SchemaPath, SchemaPathRules} from '../types';
|
|||
*/
|
||||
export function hidden<TValue, TPathKind extends PathKind = PathKind.Root>(
|
||||
path: SchemaPath<TValue, SchemaPathRules.Supported, TPathKind>,
|
||||
logic: NoInfer<LogicFn<TValue, boolean, TPathKind>>,
|
||||
config: {when: NoInfer<LogicFn<TValue, boolean, TPathKind>>},
|
||||
): void {
|
||||
assertPathIsCurrent(path);
|
||||
|
||||
const pathNode = FieldPathNode.unwrapFieldPath(path);
|
||||
pathNode.builder.addHiddenRule(logic);
|
||||
pathNode.builder.addHiddenRule(config.when);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@ import type {LogicFn, PathKind, SchemaPath, SchemaPathRules} from '../types';
|
|||
* the validation, touched/dirty, or other state of its parent field.
|
||||
*
|
||||
* @param path The target path to make readonly.
|
||||
* @param logic A reactive function that returns `true` when the field is readonly.
|
||||
* @param config Optional configuration object.
|
||||
* - `when`: A reactive function that returns `true` when the field is readonly.
|
||||
* @template TValue The type of value stored in the field the logic is bound to.
|
||||
* @template TPathKind The kind of path the logic is bound to (a root path, child path, or item of an array)
|
||||
*
|
||||
|
|
@ -24,10 +25,10 @@ import type {LogicFn, PathKind, SchemaPath, SchemaPathRules} from '../types';
|
|||
*/
|
||||
export function readonly<TValue, TPathKind extends PathKind = PathKind.Root>(
|
||||
path: SchemaPath<TValue, SchemaPathRules.Supported, TPathKind>,
|
||||
logic: NoInfer<LogicFn<TValue, boolean, TPathKind>> = () => true,
|
||||
config?: {when?: NoInfer<LogicFn<TValue, boolean, TPathKind>>},
|
||||
) {
|
||||
assertPathIsCurrent(path);
|
||||
|
||||
const pathNode = FieldPathNode.unwrapFieldPath(path);
|
||||
pathNode.builder.addReadonlyRule(logic);
|
||||
pathNode.builder.addReadonlyRule(config?.when ?? (() => true));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,6 +63,9 @@ export function email<TPathKind extends PathKind = PathKind.Root>(
|
|||
config?: BaseValidatorConfig<string, TPathKind>,
|
||||
) {
|
||||
validate(path, (ctx) => {
|
||||
if (config?.when && !config.when(ctx)) {
|
||||
return undefined;
|
||||
}
|
||||
if (isEmpty(ctx.value())) {
|
||||
return undefined;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,15 +38,18 @@ export function max<TValue extends number | null, TPathKind extends PathKind = P
|
|||
const MAX_MEMO = createMetadataKey<number | undefined>();
|
||||
|
||||
// Memoize the maximum valid value.
|
||||
metadata(path, MAX_MEMO, (ctx) => (typeof maxValue === 'function' ? maxValue(ctx) : maxValue));
|
||||
metadata(path, MAX_MEMO, (ctx) => {
|
||||
if (config?.when && !config.when(ctx)) {
|
||||
return undefined;
|
||||
}
|
||||
return typeof maxValue === 'function' ? maxValue(ctx) : maxValue;
|
||||
});
|
||||
|
||||
// Publish the memoized maximum value for aggregation.
|
||||
metadata(path, MAX_NUMBER, ({state}) => state.metadata(MAX_MEMO)!());
|
||||
|
||||
// Use `MAX_NUMBER` to define the `max` property of the field.
|
||||
metadata(path, MAX, () => MAX_NUMBER as LimitKey<TValue>);
|
||||
|
||||
// Validate that the field value is not greater than the maximum value.
|
||||
validate(path, (ctx) => {
|
||||
const value = ctx.value();
|
||||
if (value === null || Number.isNaN(value)) {
|
||||
|
|
|
|||
|
|
@ -44,9 +44,12 @@ export function maxLength<
|
|||
maxLength: number | LogicFn<TValue, number | undefined, TPathKind>,
|
||||
config?: BaseValidatorConfig<TValue, TPathKind>,
|
||||
) {
|
||||
const MAX_LENGTH_MEMO = metadata(path, createMetadataKey<number | undefined>(), (ctx) =>
|
||||
typeof maxLength === 'number' ? maxLength : maxLength(ctx),
|
||||
);
|
||||
const MAX_LENGTH_MEMO = metadata(path, createMetadataKey<number | undefined>(), (ctx) => {
|
||||
if (config?.when && !config.when(ctx)) {
|
||||
return undefined;
|
||||
}
|
||||
return typeof maxLength === 'number' ? maxLength : maxLength(ctx);
|
||||
});
|
||||
metadata(path, MAX_LENGTH, ({state}) => state.metadata(MAX_LENGTH_MEMO)!());
|
||||
validate(path, (ctx) => {
|
||||
if (isEmpty(ctx.value())) {
|
||||
|
|
|
|||
|
|
@ -38,15 +38,18 @@ export function min<TValue extends number | null, TPathKind extends PathKind = P
|
|||
const MIN_MEMO = createMetadataKey<number | undefined>();
|
||||
|
||||
// Memomize the minimum valid.
|
||||
metadata(path, MIN_MEMO, (ctx) => (typeof minValue === 'function' ? minValue(ctx) : minValue));
|
||||
metadata(path, MIN_MEMO, (ctx) => {
|
||||
if (config?.when && !config.when(ctx)) {
|
||||
return undefined;
|
||||
}
|
||||
return typeof minValue === 'function' ? minValue(ctx) : minValue;
|
||||
});
|
||||
|
||||
// Publish the memoized mininum value for aggregation.
|
||||
metadata(path, MIN_NUMBER, ({state}) => state.metadata(MIN_MEMO)!());
|
||||
|
||||
// Use `MIN_NUMBER` to define the `min` property of the field.
|
||||
metadata(path, MIN, () => MIN_NUMBER as LimitKey<TValue>);
|
||||
|
||||
// Validate that the field value is not less than the minimum value.
|
||||
validate(path, (ctx) => {
|
||||
const value = ctx.value();
|
||||
if (value === null || Number.isNaN(value)) {
|
||||
|
|
|
|||
|
|
@ -44,9 +44,12 @@ export function minLength<
|
|||
minLength: number | LogicFn<TValue, number | undefined, TPathKind>,
|
||||
config?: BaseValidatorConfig<TValue, TPathKind>,
|
||||
) {
|
||||
const MIN_LENGTH_MEMO = metadata(path, createMetadataKey<number | undefined>(), (ctx) =>
|
||||
typeof minLength === 'number' ? minLength : minLength(ctx),
|
||||
);
|
||||
const MIN_LENGTH_MEMO = metadata(path, createMetadataKey<number | undefined>(), (ctx) => {
|
||||
if (config?.when && !config.when(ctx)) {
|
||||
return undefined;
|
||||
}
|
||||
return typeof minLength === 'number' ? minLength : minLength(ctx);
|
||||
});
|
||||
metadata(path, MIN_LENGTH, ({state}) => state.metadata(MIN_LENGTH_MEMO)!());
|
||||
validate(path, (ctx) => {
|
||||
if (isEmpty(ctx.value())) {
|
||||
|
|
|
|||
|
|
@ -33,9 +33,12 @@ export function pattern<TPathKind extends PathKind = PathKind.Root>(
|
|||
pattern: RegExp | LogicFn<string | undefined, RegExp | undefined, TPathKind>,
|
||||
config?: BaseValidatorConfig<string, TPathKind>,
|
||||
) {
|
||||
const PATTERN_MEMO = metadata(path, createMetadataKey<RegExp | undefined>(), (ctx) =>
|
||||
pattern instanceof RegExp ? pattern : pattern(ctx),
|
||||
);
|
||||
const PATTERN_MEMO = metadata(path, createMetadataKey<RegExp | undefined>(), (ctx) => {
|
||||
if (config?.when && !config.when(ctx)) {
|
||||
return undefined;
|
||||
}
|
||||
return pattern instanceof RegExp ? pattern : pattern(ctx);
|
||||
});
|
||||
metadata(path, PATTERN, ({state}) => state.metadata(PATTERN_MEMO)!());
|
||||
validate(path, (ctx) => {
|
||||
if (isEmpty(ctx.value())) {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ export type BaseValidatorConfig<TValue, TPathKind extends PathKind = PathKind.Ro
|
|||
/** A user-facing error message to include with the error. */
|
||||
message?: string | LogicFn<TValue, string, TPathKind>;
|
||||
error?: never;
|
||||
/** A function that receives the `FieldContext` and returns true if the validator should be applied. */
|
||||
when?: NoInfer<LogicFn<TValue, boolean, TPathKind>>;
|
||||
}
|
||||
| {
|
||||
/**
|
||||
|
|
@ -26,6 +28,8 @@ export type BaseValidatorConfig<TValue, TPathKind extends PathKind = PathKind.Ro
|
|||
*/
|
||||
error?: OneOrMany<ValidationError> | LogicFn<TValue, OneOrMany<ValidationError>, TPathKind>;
|
||||
message?: never;
|
||||
/** A function that receives the `FieldContext` and returns true if the validator should be applied. */
|
||||
when?: NoInfer<LogicFn<TValue, boolean, TPathKind>>;
|
||||
};
|
||||
|
||||
/** Gets the length or size of the given value. */
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import {FieldPathNode} from '../../../schema/path_node';
|
|||
import {assertPathIsCurrent} from '../../../schema/schema';
|
||||
import {
|
||||
FieldContext,
|
||||
LogicFn,
|
||||
PathKind,
|
||||
SchemaPath,
|
||||
SchemaPathRules,
|
||||
|
|
@ -107,6 +108,10 @@ export interface AsyncValidatorOptions<
|
|||
* If a field is not given, the error is assumed to apply to the field being validated.
|
||||
*/
|
||||
readonly onSuccess: MapToErrorsFn<TValue, TResult, TPathKind>;
|
||||
/**
|
||||
* A function that receives the field context and returns true if the async validation should be run.
|
||||
*/
|
||||
readonly when?: NoInfer<LogicFn<TValue, boolean, TPathKind>>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -149,6 +154,9 @@ export function validateAsync<TValue, TParams, TResult, TPathKind extends PathKi
|
|||
if (validationState.shouldSkipValidation() || !validationState.syncValid()) {
|
||||
return undefined;
|
||||
}
|
||||
if (opts.when && !opts.when(ctx)) {
|
||||
return undefined;
|
||||
}
|
||||
return opts.params(ctx);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -10,10 +10,11 @@ import {httpResource, HttpResourceOptions, HttpResourceRequest} from '@angular/c
|
|||
import {DebounceTimer, ResourceSnapshot, Signal} from '@angular/core';
|
||||
import {
|
||||
FieldContext,
|
||||
SchemaPath,
|
||||
LogicFn,
|
||||
PathKind,
|
||||
TreeValidationResult,
|
||||
SchemaPath,
|
||||
SchemaPathRules,
|
||||
TreeValidationResult,
|
||||
} from '../../types';
|
||||
import {MapToErrorsFn, validateAsync} from './validate_async';
|
||||
|
||||
|
|
@ -68,6 +69,10 @@ export interface HttpValidatorOptions<TValue, TResult, TPathKind extends PathKin
|
|||
* returns a promise that resolves when the update should proceed.
|
||||
*/
|
||||
readonly debounce?: DebounceTimer<string | HttpResourceRequest | undefined>;
|
||||
/**
|
||||
* A function that receives the field context and returns true if the async validation should be run.
|
||||
*/
|
||||
readonly when?: NoInfer<LogicFn<TValue, boolean, TPathKind>>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -96,5 +101,6 @@ export function validateHttp<TValue, TResult = unknown, TPathKind extends PathKi
|
|||
factory: (request: Signal<any>) => httpResource(request, opts.options),
|
||||
onSuccess: opts.onSuccess,
|
||||
onError: opts.onError,
|
||||
when: opts.when,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,8 +16,10 @@ describe('hidden', () => {
|
|||
const f = form(
|
||||
cat,
|
||||
(p) => {
|
||||
hidden(p, ({value}) => {
|
||||
return value.name === 'hidden-cat';
|
||||
hidden(p, {
|
||||
when: ({value}) => {
|
||||
return value.name === 'hidden-cat';
|
||||
},
|
||||
});
|
||||
},
|
||||
{injector: TestBed.inject(Injector)},
|
||||
|
|
@ -32,8 +34,10 @@ describe('hidden', () => {
|
|||
const f = form(
|
||||
cat,
|
||||
(p) => {
|
||||
hidden(p.name, ({value}) => {
|
||||
return value() === 'hidden-cat';
|
||||
hidden(p.name, {
|
||||
when: ({value}) => {
|
||||
return value() === 'hidden-cat';
|
||||
},
|
||||
});
|
||||
},
|
||||
{injector: TestBed.inject(Injector)},
|
||||
|
|
@ -48,8 +52,10 @@ describe('hidden', () => {
|
|||
const f = form(
|
||||
cat,
|
||||
(p) => {
|
||||
hidden(p, ({value}) => {
|
||||
return value().name === 'hidden-cat';
|
||||
hidden(p, {
|
||||
when: ({value}) => {
|
||||
return value().name === 'hidden-cat';
|
||||
},
|
||||
});
|
||||
},
|
||||
{injector: TestBed.inject(Injector)},
|
||||
|
|
@ -65,8 +71,10 @@ describe('hidden', () => {
|
|||
const f = form(
|
||||
cat,
|
||||
(p) => {
|
||||
hidden(p.name, ({value}) => {
|
||||
return value() === 'hidden-cat';
|
||||
hidden(p.name, {
|
||||
when: ({value}) => {
|
||||
return value() === 'hidden-cat';
|
||||
},
|
||||
});
|
||||
|
||||
validate(p.name, () => {
|
||||
|
|
@ -94,8 +102,10 @@ describe('hidden', () => {
|
|||
const f = form(
|
||||
cat,
|
||||
(p) => {
|
||||
hidden(p.name, ({value}) => {
|
||||
return value() === 'hidden-cat';
|
||||
hidden(p.name, {
|
||||
when: ({value}) => {
|
||||
return value() === 'hidden-cat';
|
||||
},
|
||||
});
|
||||
},
|
||||
{injector: TestBed.inject(Injector)},
|
||||
|
|
|
|||
|
|
@ -254,8 +254,10 @@ describe('Forms compat', () => {
|
|||
const f = compatForm(
|
||||
cat,
|
||||
(p) => {
|
||||
disabled(p, ({value}) => {
|
||||
return value().name === 'disabled-cat';
|
||||
disabled(p, {
|
||||
when: ({value}) => {
|
||||
return value().name === 'disabled-cat';
|
||||
},
|
||||
});
|
||||
},
|
||||
{
|
||||
|
|
@ -286,8 +288,10 @@ describe('Forms compat', () => {
|
|||
const f = compatForm(
|
||||
cat,
|
||||
(p) => {
|
||||
hidden(p, ({value}) => {
|
||||
return value().name === 'hidden-cat';
|
||||
hidden(p, {
|
||||
when: ({value}) => {
|
||||
return value().name === 'hidden-cat';
|
||||
},
|
||||
});
|
||||
},
|
||||
{
|
||||
|
|
@ -717,8 +721,10 @@ describe('Forms compat', () => {
|
|||
return valueOf(path.age) < 8 ? [] : [];
|
||||
});
|
||||
|
||||
readonly(path.name, ({valueOf}) => {
|
||||
return valueOf(path.age) < 8;
|
||||
readonly(path.name, {
|
||||
when: ({valueOf}) => {
|
||||
return valueOf(path.age) < 8;
|
||||
},
|
||||
});
|
||||
|
||||
email(path.name, {
|
||||
|
|
|
|||
|
|
@ -227,7 +227,7 @@ describe('extractValue', () => {
|
|||
signal(model),
|
||||
(p) => {
|
||||
applyEach(p.items, (item) => {
|
||||
disabled(item, ({value}) => value() === 2 || value() === 4);
|
||||
disabled(item, {when: ({value}) => value() === 2 || value() === 4});
|
||||
});
|
||||
},
|
||||
{injector},
|
||||
|
|
@ -242,7 +242,7 @@ describe('extractValue', () => {
|
|||
signal(model),
|
||||
(p) => {
|
||||
applyEach(p.items, (item) => {
|
||||
disabled(item, ({value}) => value() !== 30);
|
||||
disabled(item, {when: ({value}) => value() !== 30});
|
||||
});
|
||||
},
|
||||
{injector},
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ describe('SignalFormControl', () => {
|
|||
|
||||
it('should support disabled via rules', () => {
|
||||
const form = createSignalFormControl(10, (p) => {
|
||||
disabled(p, ({value}) => value() > 15);
|
||||
disabled(p, {when: ({value}) => value() > 15});
|
||||
});
|
||||
|
||||
expect(form.disabled).toBe(false);
|
||||
|
|
@ -656,7 +656,7 @@ describe('SignalFormControl', () => {
|
|||
describe('callback registration', () => {
|
||||
it('should call registered onDisabledChange callback when disabled state changes', () => {
|
||||
const form = createSignalFormControl(10, (p) => {
|
||||
disabled(p, ({value}) => value() > 15);
|
||||
disabled(p, {when: ({value}) => value() > 15});
|
||||
});
|
||||
const callback = jasmine.createSpy('onDisabledChange');
|
||||
|
||||
|
|
@ -674,7 +674,7 @@ describe('SignalFormControl', () => {
|
|||
|
||||
it('should NOT track signals read inside onDisabledChange callback', () => {
|
||||
const form = createSignalFormControl(10, (p) => {
|
||||
disabled(p, ({value}) => value() > 15);
|
||||
disabled(p, {when: ({value}) => value() > 15});
|
||||
});
|
||||
const otherSignal = signal(0);
|
||||
const callback = jasmine.createSpy('onDisabledChange').and.callFake(() => {
|
||||
|
|
|
|||
|
|
@ -288,7 +288,7 @@ describe('FieldNode', () => {
|
|||
b: 2,
|
||||
}),
|
||||
(p) => {
|
||||
hidden(p, () => true);
|
||||
hidden(p, {when: () => true});
|
||||
},
|
||||
{injector: TestBed.inject(Injector)},
|
||||
);
|
||||
|
|
@ -353,7 +353,7 @@ describe('FieldNode', () => {
|
|||
b: 2,
|
||||
}),
|
||||
(p) => {
|
||||
readonly(p, isReadonly);
|
||||
readonly(p, {when: isReadonly});
|
||||
},
|
||||
{injector: TestBed.inject(Injector)},
|
||||
);
|
||||
|
|
@ -537,7 +537,7 @@ describe('FieldNode', () => {
|
|||
b: 2,
|
||||
}),
|
||||
(p) => {
|
||||
hidden(p, () => true);
|
||||
hidden(p, {when: () => true});
|
||||
},
|
||||
{injector: TestBed.inject(Injector)},
|
||||
);
|
||||
|
|
@ -602,7 +602,7 @@ describe('FieldNode', () => {
|
|||
b: 2,
|
||||
}),
|
||||
(p) => {
|
||||
hidden(p, isHidden);
|
||||
hidden(p, {when: isHidden});
|
||||
},
|
||||
{injector: TestBed.inject(Injector)},
|
||||
);
|
||||
|
|
@ -669,11 +669,13 @@ describe('FieldNode', () => {
|
|||
signal({names: [{name: 'Alex'}, {name: 'Miles'}]}),
|
||||
(p) => {
|
||||
applyEach(p.names, (a) => {
|
||||
disabled(a.name, ({value, fieldTreeOf}) => {
|
||||
const el = fieldTreeOf(a);
|
||||
expect(el().value().name).toBe(value());
|
||||
expect([...fieldTreeOf(p).names].findIndex((e: any) => e === el)).not.toBe(-1);
|
||||
return true;
|
||||
disabled(a.name, {
|
||||
when: ({value, fieldTreeOf}) => {
|
||||
const el = fieldTreeOf(a);
|
||||
expect(el().value().name).toBe(value());
|
||||
expect([...fieldTreeOf(p).names].findIndex((e: any) => e === el)).not.toBe(-1);
|
||||
return true;
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
|
|
@ -689,7 +691,7 @@ describe('FieldNode', () => {
|
|||
(p) => {
|
||||
applyEach(p, (a) => {
|
||||
a;
|
||||
disabled(a, ({value}) => value() % 2 === 0);
|
||||
disabled(a, {when: ({value}) => value() % 2 === 0});
|
||||
});
|
||||
},
|
||||
{injector: TestBed.inject(Injector)},
|
||||
|
|
@ -706,7 +708,7 @@ describe('FieldNode', () => {
|
|||
(p) => {
|
||||
applyEach(p, (el) => {
|
||||
// Disabled if even.
|
||||
disabled(el, ({value}) => value() % 2 === 0);
|
||||
disabled(el, {when: ({value}) => value() % 2 === 0});
|
||||
});
|
||||
},
|
||||
{injector: TestBed.inject(Injector)},
|
||||
|
|
@ -802,7 +804,7 @@ describe('FieldNode', () => {
|
|||
const f = form(
|
||||
signal({a: 1, b: 2}),
|
||||
(p) => {
|
||||
disabled(p.a, ({value}) => value() !== 2);
|
||||
disabled(p.a, {when: ({value}) => value() !== 2});
|
||||
},
|
||||
{injector: TestBed.inject(Injector)},
|
||||
);
|
||||
|
|
@ -820,7 +822,7 @@ describe('FieldNode', () => {
|
|||
const f = form(
|
||||
signal({a: 1, b: 2}),
|
||||
(p) => {
|
||||
disabled(p.a, () => 'a cannot be changed');
|
||||
disabled(p.a, {when: () => 'a cannot be changed'});
|
||||
},
|
||||
{injector: TestBed.inject(Injector)},
|
||||
);
|
||||
|
|
@ -838,7 +840,7 @@ describe('FieldNode', () => {
|
|||
const f = form(
|
||||
signal({a: 1, b: 2}),
|
||||
(p) => {
|
||||
disabled(p.a, ({value}) => (value() > 5 ? 'a cannot be changed' : false));
|
||||
disabled(p.a, {when: ({value}) => (value() > 5 ? 'a cannot be changed' : false)});
|
||||
},
|
||||
{injector: TestBed.inject(Injector)},
|
||||
);
|
||||
|
|
@ -861,7 +863,7 @@ describe('FieldNode', () => {
|
|||
const f = form(
|
||||
signal({a: 1, b: 2}),
|
||||
(p) => {
|
||||
disabled(p, () => 'form unavailable');
|
||||
disabled(p, {when: () => 'form unavailable'});
|
||||
},
|
||||
{injector: TestBed.inject(Injector)},
|
||||
);
|
||||
|
|
@ -887,7 +889,7 @@ describe('FieldNode', () => {
|
|||
signal({a: '', b: ''}),
|
||||
(p) => {
|
||||
disabled(p.a);
|
||||
disabled(p.b, 'disabled!');
|
||||
disabled(p.b, {when: 'disabled!'});
|
||||
},
|
||||
{injector: TestBed.inject(Injector)},
|
||||
);
|
||||
|
|
@ -925,7 +927,7 @@ describe('FieldNode', () => {
|
|||
const f = form(
|
||||
signal({a: 1, b: 2}),
|
||||
(p) => {
|
||||
readonly(p.a, ({value}) => value() > 10);
|
||||
readonly(p.a, {when: ({value}) => value() > 10});
|
||||
},
|
||||
{injector: TestBed.inject(Injector)},
|
||||
);
|
||||
|
|
@ -955,7 +957,7 @@ describe('FieldNode', () => {
|
|||
const f = form(
|
||||
signal(''),
|
||||
(p) => {
|
||||
readonly(p, isReadonly);
|
||||
readonly(p, {when: isReadonly});
|
||||
required(p);
|
||||
},
|
||||
{injector: TestBed.inject(Injector)},
|
||||
|
|
@ -1390,7 +1392,7 @@ describe('FieldNode', () => {
|
|||
}
|
||||
|
||||
const addressSchema: SchemaOrSchemaFn<Address> = (p) => {
|
||||
disabled(p.street, () => true);
|
||||
disabled(p.street, {when: () => true});
|
||||
};
|
||||
|
||||
const data = signal<{name: string; address: Address}>({
|
||||
|
|
@ -1430,7 +1432,7 @@ describe('FieldNode', () => {
|
|||
|
||||
it('should resolve predefined schema paths within the local context', () => {
|
||||
const s = schema<{a: string; b: string}>((p) => {
|
||||
disabled(p.b, ({valueOf}) => valueOf(p.a) === 'disable-b');
|
||||
disabled(p.b, {when: ({valueOf}) => valueOf(p.a) === 'disable-b'});
|
||||
});
|
||||
|
||||
const f = form(
|
||||
|
|
@ -1448,7 +1450,7 @@ describe('FieldNode', () => {
|
|||
|
||||
it('should resolve predefined schema paths deeply nested within the schema', () => {
|
||||
const s = schema<{a: string; b: string}>((p) => {
|
||||
disabled(p.b, ({valueOf}) => valueOf(p.a) === 'disable-b');
|
||||
disabled(p.b, {when: ({valueOf}) => valueOf(p.a) === 'disable-b'});
|
||||
});
|
||||
|
||||
const f = form(
|
||||
|
|
@ -1472,9 +1474,11 @@ describe('FieldNode', () => {
|
|||
const f = form(
|
||||
signal(''),
|
||||
(p) => {
|
||||
disabled(p, ({fieldTreeOf}) => {
|
||||
fieldTreeOf(otherP);
|
||||
return true;
|
||||
disabled(p, {
|
||||
when: ({fieldTreeOf}) => {
|
||||
fieldTreeOf(otherP);
|
||||
return true;
|
||||
},
|
||||
});
|
||||
},
|
||||
{injector: TestBed.inject(Injector)},
|
||||
|
|
|
|||
|
|
@ -34,8 +34,10 @@ function isNonNull<T>(t: T): t is NonNullable<T> {
|
|||
describe('recursive schema logic', () => {
|
||||
it('should support recursive logic', () => {
|
||||
const s = schema<TreeData>((p) => {
|
||||
disabled(p.level, ({valueOf}) => {
|
||||
return valueOf(p.level) % 2 === 0;
|
||||
disabled(p.level, {
|
||||
when: ({valueOf}) => {
|
||||
return valueOf(p.level) % 2 === 0;
|
||||
},
|
||||
});
|
||||
applyWhenValue(p.next, isNonNull, s);
|
||||
});
|
||||
|
|
@ -58,11 +60,11 @@ describe('recursive schema logic', () => {
|
|||
|
||||
it('should support co-recursive logic', () => {
|
||||
const s1: Schema<TreeData> = schema((p) => {
|
||||
disabled(p.level, ({valueOf}) => valueOf(p.level) % 2 === 0);
|
||||
disabled(p.level, {when: ({valueOf}) => valueOf(p.level) % 2 === 0});
|
||||
applyWhenValue(p.next, isNonNull, s2);
|
||||
});
|
||||
const s2: Schema<TreeData> = schema((p) => {
|
||||
disabled(p.level, ({valueOf}) => valueOf(p.level) % 2 === 0);
|
||||
disabled(p.level, {when: ({valueOf}) => valueOf(p.level) % 2 === 0});
|
||||
applyWhenValue(p.next, isNonNull, s1);
|
||||
});
|
||||
const f = form<TreeData>(
|
||||
|
|
|
|||
|
|
@ -423,7 +423,7 @@ describe('submit', () => {
|
|||
data,
|
||||
(name) => {
|
||||
// Disable first name when last name is empty.
|
||||
disabled(name.first, ({valueOf}) => valueOf(name.last) === '');
|
||||
disabled(name.first, {when: ({valueOf}) => valueOf(name.last) === ''});
|
||||
},
|
||||
{injector: TestBed.inject(Injector)},
|
||||
);
|
||||
|
|
@ -448,7 +448,7 @@ describe('submit', () => {
|
|||
data,
|
||||
(name) => {
|
||||
// Hide first name when last name is empty.
|
||||
hidden(name.first, ({valueOf}) => valueOf(name.last) === '');
|
||||
hidden(name.first, {when: ({valueOf}) => valueOf(name.last) === ''});
|
||||
},
|
||||
{injector: TestBed.inject(Injector)},
|
||||
);
|
||||
|
|
@ -473,7 +473,7 @@ describe('submit', () => {
|
|||
data,
|
||||
(name) => {
|
||||
// Make first name readonly when last name is empty.
|
||||
readonly(name.first, ({valueOf}) => valueOf(name.last) === '');
|
||||
readonly(name.first, {when: ({valueOf}) => valueOf(name.last) === ''});
|
||||
},
|
||||
{injector: TestBed.inject(Injector)},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ describe('createComponent', () => {
|
|||
const environmentInjector = TestBed.inject(EnvironmentInjector);
|
||||
const control = TestBed.runInInjectionContext(() => {
|
||||
return form(signal('initial value'), (p) => {
|
||||
disabled(p, disabledSignal);
|
||||
disabled(p, {when: disabledSignal});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -324,7 +324,7 @@ describe('field directive', () => {
|
|||
class TestCmp {
|
||||
readonly disabled = signal(false);
|
||||
readonly f = form(signal(''), (p) => {
|
||||
disabled(p, this.disabled);
|
||||
disabled(p, {when: this.disabled});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -359,7 +359,7 @@ describe('field directive', () => {
|
|||
class TestCmp {
|
||||
readonly disabled = signal(false);
|
||||
readonly f = form(signal(false), (p) => {
|
||||
disabled(p, this.disabled);
|
||||
disabled(p, {when: this.disabled});
|
||||
});
|
||||
readonly customControl = viewChild.required(CustomControlDir);
|
||||
}
|
||||
|
|
@ -400,7 +400,7 @@ describe('field directive', () => {
|
|||
class TestCmp {
|
||||
readonly disabled = signal(false);
|
||||
readonly f = form(signal(false), (p) => {
|
||||
disabled(p, this.disabled);
|
||||
disabled(p, {when: this.disabled});
|
||||
});
|
||||
readonly customControl = viewChild.required(BaseControlDir);
|
||||
}
|
||||
|
|
@ -431,7 +431,7 @@ describe('field directive', () => {
|
|||
class TestCmp {
|
||||
readonly disabled = signal(false);
|
||||
readonly f = form(signal(false), (p) => {
|
||||
disabled(p, this.disabled);
|
||||
disabled(p, {when: this.disabled});
|
||||
});
|
||||
readonly customControl = viewChild.required(CustomControl);
|
||||
}
|
||||
|
|
@ -456,7 +456,7 @@ describe('field directive', () => {
|
|||
class TestCmp {
|
||||
readonly disabled = signal(false);
|
||||
readonly f = form(signal(false), (p) => {
|
||||
disabled(p, this.disabled);
|
||||
disabled(p, {when: this.disabled});
|
||||
});
|
||||
readonly customControl = viewChild.required(CustomControl);
|
||||
}
|
||||
|
|
@ -482,7 +482,7 @@ describe('field directive', () => {
|
|||
class TestCmp {
|
||||
readonly disabled = signal(false);
|
||||
readonly f = form(signal(false), (p) => {
|
||||
disabled(p, this.disabled);
|
||||
disabled(p, {when: this.disabled});
|
||||
});
|
||||
readonly customControl = viewChild.required(CustomControl);
|
||||
}
|
||||
|
|
@ -509,7 +509,7 @@ describe('field directive', () => {
|
|||
class TestCmp {
|
||||
readonly disabled = signal(false);
|
||||
readonly f = form(signal(''), (p) => {
|
||||
disabled(p, this.disabled);
|
||||
disabled(p, {when: this.disabled});
|
||||
});
|
||||
readonly dir = viewChild.required(TestDir);
|
||||
}
|
||||
|
|
@ -541,7 +541,7 @@ describe('field directive', () => {
|
|||
class TestCmp {
|
||||
readonly disabled = signal(false);
|
||||
readonly f = form(signal(false), (p) => {
|
||||
disabled(p, this.disabled);
|
||||
disabled(p, {when: this.disabled});
|
||||
});
|
||||
readonly dir = viewChild.required(TestDir);
|
||||
}
|
||||
|
|
@ -620,7 +620,7 @@ describe('field directive', () => {
|
|||
class TestCmp {
|
||||
readonly disabled = signal(false);
|
||||
readonly f = form(signal(''), (p) => {
|
||||
disabled(p, this.disabled);
|
||||
disabled(p, {when: this.disabled});
|
||||
});
|
||||
readonly customControl = viewChild.required(CustomControl);
|
||||
}
|
||||
|
|
@ -663,7 +663,7 @@ describe('field directive', () => {
|
|||
class TestCmp {
|
||||
readonly data = signal('');
|
||||
readonly f = form(this.data, (p) => {
|
||||
disabled(p, () => 'Currently unavailable');
|
||||
disabled(p, {when: () => 'Currently unavailable'});
|
||||
});
|
||||
readonly customControl = viewChild.required(CustomControlDir);
|
||||
}
|
||||
|
|
@ -694,7 +694,7 @@ describe('field directive', () => {
|
|||
class TestCmp {
|
||||
readonly data = signal('');
|
||||
readonly f = form(this.data, (p) => {
|
||||
disabled(p, () => 'Currently unavailable');
|
||||
disabled(p, {when: () => 'Currently unavailable'});
|
||||
});
|
||||
readonly customControl = viewChild.required(CustomControl);
|
||||
}
|
||||
|
|
@ -724,7 +724,7 @@ describe('field directive', () => {
|
|||
class TestCmp {
|
||||
readonly data = signal('');
|
||||
readonly f = form(this.data, (p) => {
|
||||
disabled(p, () => 'Currently unavailable');
|
||||
disabled(p, {when: () => 'Currently unavailable'});
|
||||
});
|
||||
readonly customControl = viewChild.required(CustomControl);
|
||||
}
|
||||
|
|
@ -750,8 +750,10 @@ describe('field directive', () => {
|
|||
class TestCmp {
|
||||
readonly disabled = signal(false);
|
||||
readonly f = form(signal(''), (p) => {
|
||||
disabled(p, () => {
|
||||
return this.disabled() ? 'b' : false;
|
||||
disabled(p, {
|
||||
when: () => {
|
||||
return this.disabled() ? 'b' : false;
|
||||
},
|
||||
});
|
||||
});
|
||||
readonly dir = viewChild.required(TestDir);
|
||||
|
|
@ -790,8 +792,10 @@ describe('field directive', () => {
|
|||
class TestCmp {
|
||||
readonly disabled = signal(false);
|
||||
readonly f = form(signal(''), (p) => {
|
||||
disabled(p, () => {
|
||||
return this.disabled() ? 'b' : false;
|
||||
disabled(p, {
|
||||
when: () => {
|
||||
return this.disabled() ? 'b' : false;
|
||||
},
|
||||
});
|
||||
});
|
||||
readonly dir = viewChild.required(TestDir);
|
||||
|
|
@ -822,7 +826,7 @@ describe('field directive', () => {
|
|||
})
|
||||
class TestCmp {
|
||||
readonly f = form(signal({x: '', y: ''}), (p) => {
|
||||
disabled(p.x, () => 'Currently unavailable');
|
||||
disabled(p.x, {when: () => 'Currently unavailable'});
|
||||
});
|
||||
readonly field = signal(this.f.x);
|
||||
readonly customControl = viewChild.required(CustomControl);
|
||||
|
|
@ -1053,7 +1057,7 @@ describe('field directive', () => {
|
|||
})
|
||||
class TestCmp {
|
||||
readonly f = form(signal(''), (p) => {
|
||||
hidden(p, () => !visible());
|
||||
hidden(p, {when: () => !visible()});
|
||||
});
|
||||
readonly field = signal(this.f);
|
||||
readonly customControl = viewChild.required(CustomControlDir);
|
||||
|
|
@ -1086,7 +1090,7 @@ describe('field directive', () => {
|
|||
})
|
||||
class TestCmp {
|
||||
readonly f = form(signal(''), (p) => {
|
||||
hidden(p, () => !visible());
|
||||
hidden(p, {when: () => !visible()});
|
||||
});
|
||||
readonly field = signal(this.f);
|
||||
readonly customControl = viewChild.required(CustomControl);
|
||||
|
|
@ -1115,7 +1119,7 @@ describe('field directive', () => {
|
|||
})
|
||||
class TestCmp {
|
||||
readonly f = form(signal(''), (p) => {
|
||||
hidden(p, () => !visible());
|
||||
hidden(p, {when: () => !visible()});
|
||||
});
|
||||
readonly field = signal(this.f);
|
||||
readonly customControl = viewChild.required(CustomControl);
|
||||
|
|
@ -1142,7 +1146,7 @@ describe('field directive', () => {
|
|||
class TestCmp {
|
||||
readonly hidden = signal(false);
|
||||
readonly f = form(signal(''), (p) => {
|
||||
hidden(p, this.hidden);
|
||||
hidden(p, {when: this.hidden});
|
||||
});
|
||||
readonly dir = viewChild.required(TestDir);
|
||||
}
|
||||
|
|
@ -1174,7 +1178,7 @@ describe('field directive', () => {
|
|||
class TestCmp {
|
||||
readonly hidden = signal(false);
|
||||
readonly f = form(signal(''), (p) => {
|
||||
hidden(p, this.hidden);
|
||||
hidden(p, {when: this.hidden});
|
||||
});
|
||||
readonly dir = viewChild.required(TestDir);
|
||||
}
|
||||
|
|
@ -1201,7 +1205,7 @@ describe('field directive', () => {
|
|||
})
|
||||
class TestCmp {
|
||||
readonly f = form(signal({x: 'a', y: 'b'}), (p) => {
|
||||
hidden(p.x, () => true);
|
||||
hidden(p.x, {when: () => true});
|
||||
});
|
||||
readonly field = signal(this.f.x);
|
||||
readonly customControl = viewChild.required(CustomControl);
|
||||
|
|
@ -1223,7 +1227,7 @@ describe('field directive', () => {
|
|||
})
|
||||
class TestCmp {
|
||||
readonly f = form(signal(''), (p) => {
|
||||
hidden(p, () => true);
|
||||
hidden(p, {when: () => true});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -1246,7 +1250,7 @@ describe('field directive', () => {
|
|||
})
|
||||
class TestCmp {
|
||||
readonly f = form(signal(''), (p) => {
|
||||
hidden(p, isHidden);
|
||||
hidden(p, {when: isHidden});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -1866,7 +1870,7 @@ describe('field directive', () => {
|
|||
class TestCmp {
|
||||
readonly readonly = signal(true);
|
||||
readonly f = form(signal(''), (p) => {
|
||||
readonly(p, this.readonly);
|
||||
readonly(p, {when: this.readonly});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -1901,7 +1905,7 @@ describe('field directive', () => {
|
|||
class TestCmp {
|
||||
readonly readonly = signal(false);
|
||||
readonly f = form(signal(''), (p) => {
|
||||
readonly(p, this.readonly);
|
||||
readonly(p, {when: this.readonly});
|
||||
});
|
||||
readonly child = viewChild.required(CustomControlDir);
|
||||
}
|
||||
|
|
@ -1932,7 +1936,7 @@ describe('field directive', () => {
|
|||
class TestCmp {
|
||||
readonly readonly = signal(false);
|
||||
readonly f = form(signal(''), (p) => {
|
||||
readonly(p, this.readonly);
|
||||
readonly(p, {when: this.readonly});
|
||||
});
|
||||
readonly customControl = viewChild.required(CustomControl);
|
||||
}
|
||||
|
|
@ -1959,7 +1963,7 @@ describe('field directive', () => {
|
|||
class TestCmp {
|
||||
readonly readonly = signal(false);
|
||||
readonly f = form(signal(''), (p) => {
|
||||
readonly(p, this.readonly);
|
||||
readonly(p, {when: this.readonly});
|
||||
});
|
||||
readonly child = viewChild.required(CustomControl);
|
||||
}
|
||||
|
|
@ -1985,7 +1989,7 @@ describe('field directive', () => {
|
|||
class TestCmp {
|
||||
readonly readonly = signal(false);
|
||||
readonly f = form(signal(''), (p) => {
|
||||
readonly(p, this.readonly);
|
||||
readonly(p, {when: this.readonly});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -2011,7 +2015,7 @@ describe('field directive', () => {
|
|||
class TestCmp {
|
||||
readonly readonly = signal(false);
|
||||
readonly f = form(signal(''), (p) => {
|
||||
readonly(p, this.readonly);
|
||||
readonly(p, {when: this.readonly});
|
||||
});
|
||||
readonly dir = viewChild.required(TestDir);
|
||||
}
|
||||
|
|
@ -2043,7 +2047,7 @@ describe('field directive', () => {
|
|||
class TestCmp {
|
||||
readonly readonly = signal(false);
|
||||
readonly f = form(signal(''), (p) => {
|
||||
readonly(p, this.readonly);
|
||||
readonly(p, {when: this.readonly});
|
||||
});
|
||||
readonly dir = viewChild.required(TestDir);
|
||||
}
|
||||
|
|
@ -4690,7 +4694,7 @@ describe('field directive', () => {
|
|||
`,
|
||||
})
|
||||
class TestCmp {
|
||||
f = form(signal(''), (p) => hidden(p, ({value}) => value() === ''));
|
||||
f = form(signal(''), (p) => hidden(p, {when: ({value}) => value() === ''}));
|
||||
select = viewChild<ElementRef<HTMLSelectElement>>('select');
|
||||
options = ['one', 'two', 'three'];
|
||||
}
|
||||
|
|
@ -4721,7 +4725,7 @@ describe('field directive', () => {
|
|||
`,
|
||||
})
|
||||
class TestCmp {
|
||||
f = form(signal(''), (p) => hidden(p, ({value}) => value() === ''));
|
||||
f = form(signal(''), (p) => hidden(p, {when: ({value}) => value() === ''}));
|
||||
select = viewChild<ElementRef<HTMLSelectElement>>('select');
|
||||
options = ['one', 'two', 'three'];
|
||||
}
|
||||
|
|
@ -4934,7 +4938,7 @@ describe('field directive', () => {
|
|||
myInput = viewChild.required<CustomInput>(CustomInput);
|
||||
data = signal('');
|
||||
f = form(this.data, (p) => {
|
||||
disabled(p, () => 'Currently unavailable');
|
||||
disabled(p, {when: () => 'Currently unavailable'});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -4991,7 +4995,7 @@ describe('field directive', () => {
|
|||
myInput = viewChild.required<CustomInput>(CustomInput);
|
||||
data = signal('');
|
||||
f = form(this.data, (p) => {
|
||||
hidden(p, ({value}) => value() === '');
|
||||
hidden(p, {when: ({value}) => value() === ''});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -5164,7 +5168,7 @@ describe('field directive', () => {
|
|||
model = signal('');
|
||||
f = form(this.model, (p) => {
|
||||
required(p, {message: 'schema error'});
|
||||
disabled(p, ({value}) => (value() === 'disabled' ? 'schema disabled' : false));
|
||||
disabled(p, {when: ({value}) => (value() === 'disabled' ? 'schema disabled' : false)});
|
||||
});
|
||||
disabledReasons = [{message: 'manual disabled'}];
|
||||
errors = [{kind: 'error', message: 'manual error'}];
|
||||
|
|
|
|||
|
|
@ -388,7 +388,7 @@ describe('ControlValueAccessor', () => {
|
|||
})
|
||||
class TestCmp {
|
||||
f = form<string>(signal('test'), (p) => {
|
||||
disabled(p, () => !enabled());
|
||||
disabled(p, {when: () => !enabled()});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -516,7 +516,7 @@ describe('ControlValueAccessor', () => {
|
|||
class App {
|
||||
disabled = signal(false);
|
||||
readonly f = form(signal('test'), (f) => {
|
||||
disabled(f, () => this.disabled());
|
||||
disabled(f, {when: () => this.disabled()});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -622,7 +622,7 @@ describe('ControlValueAccessor', () => {
|
|||
class TestCmp {
|
||||
readonly disabled = signal(false);
|
||||
readonly f = form(signal(''), (p) => {
|
||||
disabled(p, this.disabled);
|
||||
disabled(p, {when: this.disabled});
|
||||
});
|
||||
readonly dir = viewChild.required(TestDir);
|
||||
}
|
||||
|
|
@ -644,7 +644,7 @@ describe('ControlValueAccessor', () => {
|
|||
class TestCmp {
|
||||
readonly disabled = signal(false);
|
||||
readonly f = form(signal(''), (p) => {
|
||||
disabled(p, this.disabled);
|
||||
disabled(p, {when: this.disabled});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -725,8 +725,10 @@ describe('ControlValueAccessor', () => {
|
|||
class TestCmp {
|
||||
readonly disabled = signal(false);
|
||||
readonly f = form(signal(''), (p) => {
|
||||
disabled(p, () => {
|
||||
return this.disabled() ? 'Test reason' : false;
|
||||
disabled(p, {
|
||||
when: () => {
|
||||
return this.disabled() ? 'Test reason' : false;
|
||||
},
|
||||
});
|
||||
});
|
||||
readonly dir = viewChild.required(TestDir);
|
||||
|
|
@ -787,7 +789,7 @@ describe('ControlValueAccessor', () => {
|
|||
class TestCmp {
|
||||
readonly hidden = signal(false);
|
||||
readonly f = form(signal(''), (p) => {
|
||||
hidden(p, this.hidden);
|
||||
hidden(p, {when: this.hidden});
|
||||
});
|
||||
readonly dir = viewChild.required(TestDir);
|
||||
}
|
||||
|
|
@ -923,7 +925,7 @@ describe('ControlValueAccessor', () => {
|
|||
class TestCmp {
|
||||
readonly isReadonly = signal(false);
|
||||
readonly f = form(signal(''), (p) => {
|
||||
readonly(p, this.isReadonly);
|
||||
readonly(p, {when: this.isReadonly});
|
||||
});
|
||||
readonly dir = viewChild.required(TestDir);
|
||||
}
|
||||
|
|
@ -945,7 +947,7 @@ describe('ControlValueAccessor', () => {
|
|||
class TestCmp {
|
||||
readonly isReadonly = signal(false);
|
||||
readonly f = form(signal(''), (p) => {
|
||||
readonly(p, this.isReadonly);
|
||||
readonly(p, {when: this.isReadonly});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ describe('SignalFormControl (web)', () => {
|
|||
readonly signalControl = new SignalFormControl(
|
||||
10,
|
||||
(p) => {
|
||||
disabled(p, ({value}) => value() > 15);
|
||||
disabled(p, {when: ({value}) => value() > 15});
|
||||
},
|
||||
{injector: inject(Injector)},
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in a new issue