mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
fix(forms): minor cleanup for disabled API (#63318)
* fix(forms): minor cleanup for disabled API rename DisabledReason.reason to DisabledReason.message for consistency with errors, and allow unconditional disabling with message * address feedback
This commit is contained in:
@@ -100,12 +100,12 @@ export class CustomValidationError extends ValidationError {
|
||||
}
|
||||
|
||||
// @public
|
||||
export function disabled<TValue, TPathKind extends PathKind = PathKind.Root>(path: FieldPath<TValue, TPathKind>, logic?: NoInfer<LogicFn<TValue, boolean | string, TPathKind>>): void;
|
||||
export function disabled<TValue, TPathKind extends PathKind = PathKind.Root>(path: FieldPath<TValue, TPathKind>, logic?: string | NoInfer<LogicFn<TValue, boolean | string, TPathKind>>): void;
|
||||
|
||||
// @public
|
||||
export interface DisabledReason {
|
||||
readonly field: Field<unknown>;
|
||||
readonly reason?: string;
|
||||
readonly message?: string;
|
||||
}
|
||||
|
||||
// @public
|
||||
|
||||
@@ -530,7 +530,7 @@ const userSchema = schema<User>((userPath) => {
|
||||
this.usersModel.set([{username: 'newuser', name: 'John Doe'}]);
|
||||
|
||||
this.usersForm[0].username().disabled(); // true
|
||||
this.usersForm[0].username().disabledReasons(); // [{field: this.usersForm[0].username, reason: 'Username cannot be changed'}]
|
||||
this.usersForm[0].username().disabledReasons(); // [{field: this.usersForm[0].username, message: 'Username cannot be changed'}]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -31,23 +31,22 @@ import {addDefaultField} from './validation_errors';
|
||||
*/
|
||||
export function disabled<TValue, TPathKind extends PathKind = PathKind.Root>(
|
||||
path: FieldPath<TValue, TPathKind>,
|
||||
logic: NoInfer<LogicFn<TValue, boolean | string, TPathKind>> = () => true,
|
||||
logic?: string | NoInfer<LogicFn<TValue, boolean | string, TPathKind>>,
|
||||
): void {
|
||||
assertPathIsCurrent(path);
|
||||
|
||||
const pathNode = FieldPathNode.unwrapFieldPath(path);
|
||||
pathNode.logic.addDisabledReasonRule((ctx) => {
|
||||
const result = logic(ctx as FieldContext<TValue, TPathKind>);
|
||||
if (!result) {
|
||||
return undefined;
|
||||
let result: boolean | string = true;
|
||||
if (typeof logic === 'string') {
|
||||
result = logic;
|
||||
} else if (logic) {
|
||||
result = logic(ctx as FieldContext<TValue, TPathKind>);
|
||||
}
|
||||
if (typeof result === 'string') {
|
||||
return {
|
||||
field: ctx.field,
|
||||
reason: result,
|
||||
};
|
||||
return {field: ctx.field, message: result};
|
||||
}
|
||||
return {field: ctx.field};
|
||||
return result ? {field: ctx.field} : undefined;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -72,8 +72,8 @@ export type SubmittedStatus = 'unsubmitted' | 'submitted' | 'submitting';
|
||||
export interface DisabledReason {
|
||||
/** The field that is disabled. */
|
||||
readonly field: Field<unknown>;
|
||||
/** The reason for the disablement. */
|
||||
readonly reason?: string;
|
||||
/** A user-facing message describing the reason for the disablement. */
|
||||
readonly message?: string;
|
||||
}
|
||||
|
||||
/** The absence of an error which indicates a successful validation result. */
|
||||
|
||||
@@ -405,7 +405,7 @@ describe('FieldNode', () => {
|
||||
expect(f.a().disabledReasons()).toEqual([
|
||||
{
|
||||
field: f.a,
|
||||
reason: 'a cannot be changed',
|
||||
message: 'a cannot be changed',
|
||||
},
|
||||
]);
|
||||
});
|
||||
@@ -428,7 +428,7 @@ describe('FieldNode', () => {
|
||||
expect(f.a().disabledReasons()).toEqual([
|
||||
{
|
||||
field: f.a,
|
||||
reason: 'a cannot be changed',
|
||||
message: 'a cannot be changed',
|
||||
},
|
||||
]);
|
||||
});
|
||||
@@ -446,14 +446,37 @@ describe('FieldNode', () => {
|
||||
expect(f().disabledReasons()).toEqual([
|
||||
{
|
||||
field: f,
|
||||
reason: 'form unavailable',
|
||||
message: 'form unavailable',
|
||||
},
|
||||
]);
|
||||
expect(f.a().disabled()).toBe(true);
|
||||
expect(f.a().disabledReasons()).toEqual([
|
||||
{
|
||||
field: f,
|
||||
reason: 'form unavailable',
|
||||
message: 'form unavailable',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should disable unconditionally', () => {
|
||||
const f = form(
|
||||
signal({a: '', b: ''}),
|
||||
(p) => {
|
||||
disabled(p.a);
|
||||
disabled(p.b, 'disabled!');
|
||||
},
|
||||
{injector: TestBed.inject(Injector)},
|
||||
);
|
||||
|
||||
expect(f.a().disabledReasons()).toEqual([
|
||||
{
|
||||
field: f.a,
|
||||
},
|
||||
]);
|
||||
expect(f.b().disabledReasons()).toEqual([
|
||||
{
|
||||
field: f.b,
|
||||
message: 'disabled!',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -439,7 +439,7 @@ describe('control directive', () => {
|
||||
const comp = act(() => TestBed.createComponent(ReadonlyTestCmp)).componentInstance;
|
||||
|
||||
expect(comp.myInput().disabledReasons()).toEqual([
|
||||
{reason: 'Currently unavailable', field: comp.f},
|
||||
{message: 'Currently unavailable', field: comp.f},
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user