Skip to content

Commit 1169d8c

Browse files
committed
feat(material-experimental/mdc-form-field): Add option for dynamic suffix height based on number of hints and errors.
1 parent 9b1fd61 commit 1169d8c

File tree

3 files changed

+100
-1
lines changed

3 files changed

+100
-1
lines changed

src/dev-app/mdc-input/mdc-input-demo.html

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,71 @@ <h4>Textarea</h4>
415415
</mat-card-content>
416416
</mat-card>
417417

418+
<mat-card class="demo-card demo-basic">
419+
<mat-toolbar color="primary">Dynamic Suffix Sizing</mat-toolbar>
420+
<mat-card-content>
421+
<p>
422+
One validation
423+
<mat-form-field appearance="fill" [color]="color" suffixSizing="dynamic">
424+
<mat-label>Fill appearance</mat-label>
425+
<input matInput [(ngModel)]="fillAppearance" required>
426+
<mat-error>This field is required</mat-error>
427+
</mat-form-field>
428+
</p>
429+
430+
<p>
431+
One hint and one validation
432+
<mat-form-field appearance="fill" [color]="color" suffixSizing="dynamic">
433+
<mat-label>Fill appearance</mat-label>
434+
<input matInput [(ngModel)]="fillAppearance" required>
435+
<mat-error>This field is required</mat-error>
436+
<mat-hint>Please type something here</mat-hint>
437+
</mat-form-field>
438+
</p>
439+
440+
<p>
441+
Multiple errors
442+
<mat-form-field appearance="fill" [color]="color" suffixSizing="dynamic">
443+
<mat-label>Fill appearance</mat-label>
444+
<input matInput [(ngModel)]="fillAppearance" required>
445+
<mat-error>AAA</mat-error>
446+
<mat-error>BBB</mat-error>
447+
<mat-error>CCC</mat-error>
448+
</mat-form-field>
449+
</p>
450+
451+
<p>
452+
Multiple hints
453+
<mat-form-field appearance="fill" [color]="color" suffixSizing="dynamic">
454+
<mat-label>Fill appearance</mat-label>
455+
<input matInput>
456+
<mat-hint>aaa</mat-hint>
457+
<mat-hint>bbb</mat-hint>
458+
<mat-hint>ccc</mat-hint>
459+
</mat-form-field>
460+
</p>
461+
462+
<p>
463+
Multiple hints with differing alignment
464+
<mat-form-field appearance="fill" [color]="color" suffixSizing="dynamic">
465+
<mat-label>Fill appearance</mat-label>
466+
<input matInput>
467+
<mat-hint>aaa</mat-hint>
468+
<mat-hint align="end">bbb</mat-hint>
469+
<mat-hint align="end">ccc</mat-hint>
470+
</mat-form-field>
471+
</p>
472+
473+
<p>
474+
No hints or errors
475+
<mat-form-field appearance="fill" [color]="color" suffixSizing="dynamic">
476+
<mat-label>Fill appearance</mat-label>
477+
<input matInput>
478+
</mat-form-field>
479+
</p>
480+
</mat-card-content>
481+
</mat-card>
482+
418483
<mat-card class="demo-card demo-basic">
419484
<mat-toolbar color="primary">Number Inputs</mat-toolbar>
420485
<mat-card-content>

src/material-experimental/mdc-form-field/form-field.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@
7171
</div>
7272

7373
<div class="mat-mdc-form-field-subscript-wrapper mat-mdc-form-field-bottom-align"
74-
[ngSwitch]="_getDisplayedMessages()">
74+
[ngSwitch]="_getDisplayedMessages()"
75+
[style.height.px]="_getDynamicSuffixHeight()">
7576
<div class="mat-mdc-form-field-error-wrapper" *ngSwitchCase="'error'"
7677
[@transitionMessages]="_subscriptAnimationState">
7778
<ng-content select="mat-error"></ng-content>

src/material-experimental/mdc-form-field/form-field.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ export type FloatLabelType = 'always' | 'auto';
6161
/** Possible appearance styles for the form field. */
6262
export type MatFormFieldAppearance = 'fill' | 'outline';
6363

64+
/** Behaviors for how the suffix height is set. */
65+
export type SuffixSizingBehavior = 'fixed' | 'dynamic';
66+
6467
/**
6568
* Represents the default options for the form field that can be configured
6669
* using the `MAT_FORM_FIELD_DEFAULT_OPTIONS` injection token.
@@ -69,6 +72,7 @@ export interface MatFormFieldDefaultOptions {
6972
appearance?: MatFormFieldAppearance;
7073
hideRequiredMarker?: boolean;
7174
floatLabel?: FloatLabelType;
75+
suffixSizing?: SuffixSizingBehavior;
7276
}
7377

7478
/**
@@ -87,6 +91,9 @@ const DEFAULT_APPEARANCE: MatFormFieldAppearance = 'fill';
8791
/** Default appearance used by the form-field. */
8892
const DEFAULT_FLOAT_LABEL: FloatLabelType = 'auto';
8993

94+
/** Default way that the suffix element height is set. */
95+
const DEFAULT_SUFFIX_SIZING: SuffixSizingBehavior = 'fixed';
96+
9097
/**
9198
* Default transform for docked floating labels in a MDC text-field. This value has been
9299
* extracted from the MDC text-field styles because we programmatically modify the docked
@@ -100,6 +107,11 @@ const FLOATING_LABEL_DEFAULT_DOCKED_TRANSFORM = `translateY(-50%)`;
100107
*/
101108
const WRAPPER_HORIZONTAL_PADDING = 16;
102109

110+
/** Height provided for each row of text when using dynamic suffix sizing. */
111+
const SUFFIX_ROW_HEIGHT = 16;
112+
/** Space added to dynamic suffix height if rows of text are present. */
113+
const SUFFIX_ROW_SPACER = 4;
114+
103115
/** Container for form controls that applies Material Design styling and behavior. */
104116
@Component({
105117
selector: 'mat-form-field',
@@ -206,6 +218,15 @@ export class MatFormField
206218
}
207219
private _appearance: MatFormFieldAppearance = DEFAULT_APPEARANCE;
208220

221+
@Input()
222+
get suffixSizing(): SuffixSizingBehavior {
223+
return this._suffixSizing || this._defaults?.suffixSizing || DEFAULT_SUFFIX_SIZING;
224+
}
225+
set suffixSizing(value: SuffixSizingBehavior) {
226+
this._suffixSizing = value || this._defaults?.suffixSizing || DEFAULT_SUFFIX_SIZING;
227+
}
228+
private _suffixSizing: SuffixSizingBehavior = DEFAULT_SUFFIX_SIZING;
229+
209230
/** Text for the form field hint. */
210231
@Input()
211232
get hintLabel(): string {
@@ -604,6 +625,18 @@ export class MatFormField
604625
: 'hint';
605626
}
606627

628+
/** Determines height of suffix when in dynamic suffix sizing mode. */
629+
_getDynamicSuffixHeight(): number | null {
630+
if (this.suffixSizing !== 'dynamic') return null;
631+
632+
const numSuffixRows =
633+
this._getDisplayedMessages() === 'error'
634+
? this._errorChildren.length
635+
: Math.min(this._hintChildren.length, 1);
636+
637+
return numSuffixRows && numSuffixRows * SUFFIX_ROW_HEIGHT + SUFFIX_ROW_SPACER;
638+
}
639+
607640
/** Refreshes the width of the outline-notch, if present. */
608641
_refreshOutlineNotchWidth() {
609642
if (!this._hasOutline() || !this._floatingLabel) {

0 commit comments

Comments
 (0)