diff --git a/src/components-examples/material/input/index.ts b/src/components-examples/material/input/index.ts index 272bcfb1b565..1d9710df9d46 100644 --- a/src/components-examples/material/input/index.ts +++ b/src/components-examples/material/input/index.ts @@ -1,6 +1,7 @@ export {InputClearableExample} from './input-clearable/input-clearable-example'; export {InputErrorStateMatcherExample} from './input-error-state-matcher/input-error-state-matcher-example'; export {InputErrorsExample} from './input-errors/input-errors-example'; +export {InputErrorsSignalFormExample} from './input-errors-signal-form/input-errors-signal-form-example'; export {InputFormExample} from './input-form/input-form-example'; export {InputHintExample} from './input-hint/input-hint-example'; export {InputOverviewExample} from './input-overview/input-overview-example'; diff --git a/src/components-examples/material/input/input-errors-signal-form/input-errors-signal-form-example.css b/src/components-examples/material/input/input-errors-signal-form/input-errors-signal-form-example.css new file mode 100644 index 000000000000..08fa67536b1f --- /dev/null +++ b/src/components-examples/material/input/input-errors-signal-form/input-errors-signal-form-example.css @@ -0,0 +1,9 @@ +.example-form { + min-width: 150px; + max-width: 500px; + width: 100%; +} + +.example-full-width { + width: 100%; +} diff --git a/src/components-examples/material/input/input-errors-signal-form/input-errors-signal-form-example.html b/src/components-examples/material/input/input-errors-signal-form/input-errors-signal-form-example.html new file mode 100644 index 000000000000..f43d845919a0 --- /dev/null +++ b/src/components-examples/material/input/input-errors-signal-form/input-errors-signal-form-example.html @@ -0,0 +1,12 @@ +
+ + Email + + @if (emailForm().getError('email') && !emailForm().getError('required')) { + Please enter a valid email address + } + @if (emailForm().getError('required')) { + Email is required + } + +
diff --git a/src/components-examples/material/input/input-errors-signal-form/input-errors-signal-form-example.ts b/src/components-examples/material/input/input-errors-signal-form/input-errors-signal-form-example.ts new file mode 100644 index 000000000000..313c9c1b8f6c --- /dev/null +++ b/src/components-examples/material/input/input-errors-signal-form/input-errors-signal-form-example.ts @@ -0,0 +1,21 @@ +import {Component, signal} from '@angular/core'; +import {MatInputModule} from '@angular/material/input'; +import {MatFormFieldModule} from '@angular/material/form-field'; +import {email, form, FormField, required} from '@angular/forms/signals'; + +/** + * @title Input with error messages (signal form) + */ +@Component({ + selector: 'input-errors-signal-form-example', + templateUrl: 'input-errors-signal-form-example.html', + styleUrl: 'input-errors-signal-form-example.css', + imports: [MatFormFieldModule, MatInputModule, FormField], +}) +export class InputErrorsSignalFormExample { + private _emailModel = signal(''); + + protected emailForm = form(this._emailModel, schemaPath => { + (required(schemaPath), email(schemaPath)); + }); +} diff --git a/src/components-examples/material/input/input-errors/input-errors-example.ts b/src/components-examples/material/input/input-errors/input-errors-example.ts index 09313a037151..cf2296e92d3c 100644 --- a/src/components-examples/material/input/input-errors/input-errors-example.ts +++ b/src/components-examples/material/input/input-errors/input-errors-example.ts @@ -4,7 +4,7 @@ import {MatInputModule} from '@angular/material/input'; import {MatFormFieldModule} from '@angular/material/form-field'; /** - * @title Input with error messages + * @title Input with error messages (reactive form) */ @Component({ selector: 'input-errors-example', diff --git a/src/material/input/input.md b/src/material/input/input.md index db811dbf68d5..5bc65709328c 100644 --- a/src/material/input/input.md +++ b/src/material/input/input.md @@ -30,6 +30,10 @@ be used with `matNativeControl`: * url * week +### Use with Angular Forms + +`matInput` is compatible with `@angular/forms` and supports `FormField`, `FormsModule`, and `ReactiveFormsModule`. + ### Form field features There are a number of `` features that can be used with any `` or @@ -53,11 +57,20 @@ with your `matNativeControl`. By default, these error messages are shown when th the user has interacted with (touched) the element or the parent form has been submitted. If you wish to override this behavior (e.g. to show the error as soon as the invalid control is dirty or when a parent form group is invalid), you can use the `errorStateMatcher` property of the -`matNativeControl`. The property takes an instance of an `ErrorStateMatcher` object. An `ErrorStateMatcher` +`matNativeControl`. The property takes an instance of an `ErrorStateMatcher` object. + +For reactive forms, an `ErrorStateMatcher` must implement a single method `isErrorState` which takes the `FormControl` for this `matNativeControl` as well as the parent form and returns a boolean indicating whether errors should be shown. (`true` indicating that they should be shown, and `false` indicating that they should not.) +For signal forms, an `ErrorStateMatcher` +must still implement the method `isErrorState` for backwards compatability with the reactive forms API, +but it can be fullfilled with `isErrorState() {return false}`. +Then the custom matcher can implement `isSignalErrorState`, which takes the `Field` for this +`matNativeControl` as well as the parent form and returns a boolean indicating whether errors +should be shown. (`true` indicating that they should be shown, and `false` indicating that they should not.) + A global error state matcher can be specified by setting the `ErrorStateMatcher` provider. This