Skip to content

Commit 4076820

Browse files
kseamonmmalerba
authored andcommittedJan 24, 2022
feat(material-experimental/mdc-form-field): Add option for dynamic su… (#24241)
1 parent 4ec34b5 commit 4076820

File tree

5 files changed

+163
-0
lines changed

5 files changed

+163
-0
lines changed
 

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

+75
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,81 @@ <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 Subscript Sizing</mat-toolbar>
420+
<mat-card-content>
421+
<p>
422+
One validation
423+
<mat-form-field appearance="fill" [color]="color" subscriptSizing="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 very long validation that wraps
432+
<mat-form-field appearance="fill" [color]="color" subscriptSizing="dynamic"
433+
style="width: 212px">
434+
<mat-label>Fill appearance</mat-label>
435+
<input matInput [(ngModel)]="fillAppearance" required>
436+
<mat-error>This field is extremely, very much, absolutely positively required so do not forget it!</mat-error>
437+
</mat-form-field>
438+
</p>
439+
440+
<p>
441+
One hint and one validation
442+
<mat-form-field appearance="fill" [color]="color" subscriptSizing="dynamic">
443+
<mat-label>Fill appearance</mat-label>
444+
<input matInput [(ngModel)]="fillAppearance" required>
445+
<mat-error>This field is required</mat-error>
446+
<mat-hint>Please type something here</mat-hint>
447+
</mat-form-field>
448+
</p>
449+
450+
<p>
451+
Multiple errors
452+
<mat-form-field appearance="fill" [color]="color" subscriptSizing="dynamic">
453+
<mat-label>Fill appearance</mat-label>
454+
<input matInput [(ngModel)]="fillAppearance" required>
455+
<mat-error>AAA</mat-error>
456+
<mat-error>BBB</mat-error>
457+
<mat-error>CCC</mat-error>
458+
</mat-form-field>
459+
</p>
460+
461+
<p>
462+
Multiple hints
463+
<mat-form-field appearance="fill" [color]="color" subscriptSizing="dynamic">
464+
<mat-label>Fill appearance</mat-label>
465+
<input matInput>
466+
<mat-hint>aaa</mat-hint>
467+
<mat-hint>bbb</mat-hint>
468+
<mat-hint>ccc</mat-hint>
469+
</mat-form-field>
470+
</p>
471+
472+
<p>
473+
Multiple hints with differing alignment
474+
<mat-form-field appearance="fill" [color]="color" subscriptSizing="dynamic">
475+
<mat-label>Fill appearance</mat-label>
476+
<input matInput>
477+
<mat-hint>aaa</mat-hint>
478+
<mat-hint align="end">bbb</mat-hint>
479+
<mat-hint align="end">ccc</mat-hint>
480+
</mat-form-field>
481+
</p>
482+
483+
<p>
484+
No hints or errors
485+
<mat-form-field appearance="fill" [color]="color" subscriptSizing="dynamic">
486+
<mat-label>Fill appearance</mat-label>
487+
<input matInput>
488+
</mat-form-field>
489+
</p>
490+
</mat-card-content>
491+
</mat-card>
492+
418493
<mat-card class="demo-card demo-basic">
419494
<mat-toolbar color="primary">Number Inputs</mat-toolbar>
420495
<mat-card-content>

‎src/material-experimental/mdc-form-field/_form-field-subscript.scss

+11
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,23 @@
2323
padding: 0 mdc-textfield-variables.$padding-horizontal;
2424
}
2525

26+
.mat-mdc-form-field-subscript-dynamic-size {
27+
.mat-mdc-form-field-hint-wrapper,
28+
.mat-mdc-form-field-error-wrapper {
29+
position: static;
30+
}
31+
}
32+
2633
.mat-mdc-form-field-bottom-align::before {
2734
content: '';
2835
display: inline-block;
2936
height: 16px;
3037
}
3138

39+
.mat-mdc-form-field-bottom-align.mat-mdc-form-field-subscript-dynamic-size::before {
40+
content: unset;
41+
}
42+
3243
.mat-mdc-form-field-hint-end {
3344
order: 1;
3445
}

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

+1
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
</div>
7272

7373
<div class="mat-mdc-form-field-subscript-wrapper mat-mdc-form-field-bottom-align"
74+
[class.mat-mdc-form-field-subscript-dynamic-size]="subscriptSizing === 'dynamic'"
7475
[ngSwitch]="_getDisplayedMessages()">
7576
<div class="mat-mdc-form-field-error-wrapper" *ngSwitchCase="'error'"
7677
[@transitionMessages]="_subscriptAnimationState">

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

+21
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 subscript height is set. */
65+
export type SubscriptSizing = '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+
subscriptSizing?: SubscriptSizing;
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_SUBSCRIPT_SIZING: SubscriptSizing = '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
@@ -206,6 +213,20 @@ export class MatFormField
206213
}
207214
private _appearance: MatFormFieldAppearance = DEFAULT_APPEARANCE;
208215

216+
/**
217+
* Whether the form field should reserve space for one line of hint/error text (default)
218+
* or to have the spacing grow from 0px as needed based on the size of the hint/error content.
219+
* Note that when using dynamic sizing, layout shifts will occur when hint/error text changes.
220+
*/
221+
@Input()
222+
get subscriptSizing(): SubscriptSizing {
223+
return this._subscriptSizing || this._defaults?.subscriptSizing || DEFAULT_SUBSCRIPT_SIZING;
224+
}
225+
set subscriptSizing(value: SubscriptSizing) {
226+
this._subscriptSizing = value || this._defaults?.subscriptSizing || DEFAULT_SUBSCRIPT_SIZING;
227+
}
228+
private _subscriptSizing: SubscriptSizing = DEFAULT_SUBSCRIPT_SIZING;
229+
209230
/** Text for the form field hint. */
210231
@Input()
211232
get hintLabel(): string {

‎src/material-experimental/mdc-input/input.spec.ts

+55
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
MatFormField,
3333
MatFormFieldAppearance,
3434
MatFormFieldModule,
35+
SubscriptSizing,
3536
} from '@angular/material-experimental/mdc-form-field';
3637
import {MatIconModule} from '@angular/material/icon';
3738
import {By} from '@angular/platform-browser';
@@ -1406,6 +1407,47 @@ describe('MatFormField default options', () => {
14061407
expect(fixture.componentInstance.formField.hideRequiredMarker).toBe(true);
14071408
expect(fixture.componentInstance.formField.appearance).toBe('outline');
14081409
});
1410+
1411+
it('defaults subscriptSizing to false', () => {
1412+
const fixture = createComponent(MatInputWithSubscriptSizing);
1413+
fixture.detectChanges();
1414+
1415+
const subscriptElement = fixture.nativeElement.querySelector(
1416+
'.mat-mdc-form-field-subscript-wrapper',
1417+
);
1418+
1419+
expect(fixture.componentInstance.formField.subscriptSizing).toBe('fixed');
1420+
expect(subscriptElement.classList.contains('mat-mdc-form-field-subscript-dynamic-size')).toBe(
1421+
false,
1422+
);
1423+
1424+
fixture.componentInstance.sizing = 'dynamic';
1425+
fixture.detectChanges();
1426+
1427+
expect(fixture.componentInstance.formField.subscriptSizing).toBe('dynamic');
1428+
expect(subscriptElement.classList.contains('mat-mdc-form-field-subscript-dynamic-size')).toBe(
1429+
true,
1430+
);
1431+
});
1432+
1433+
it('changes the default value of subscriptSizing', () => {
1434+
const fixture = createComponent(MatInputWithSubscriptSizing, [
1435+
{
1436+
provide: MAT_FORM_FIELD_DEFAULT_OPTIONS,
1437+
useValue: {
1438+
subscriptSizing: 'dynamic',
1439+
},
1440+
},
1441+
]);
1442+
1443+
fixture.detectChanges();
1444+
expect(fixture.componentInstance.formField.subscriptSizing).toBe('dynamic');
1445+
expect(
1446+
fixture.nativeElement
1447+
.querySelector('.mat-mdc-form-field-subscript-wrapper')
1448+
.classList.contains('mat-mdc-form-field-subscript-dynamic-size'),
1449+
).toBe(true);
1450+
});
14091451
});
14101452

14111453
function configureTestingModule(
@@ -1815,6 +1857,19 @@ class MatInputWithAppearance {
18151857
appearance: MatFormFieldAppearance;
18161858
}
18171859

1860+
@Component({
1861+
template: `
1862+
<mat-form-field [subscriptSizing]="sizing">
1863+
<mat-label>My Label</mat-label>
1864+
<input matInput placeholder="Placeholder" required>
1865+
</mat-form-field>
1866+
`,
1867+
})
1868+
class MatInputWithSubscriptSizing {
1869+
@ViewChild(MatFormField) formField: MatFormField;
1870+
sizing: SubscriptSizing;
1871+
}
1872+
18181873
@Component({
18191874
template: `
18201875
<mat-form-field>

0 commit comments

Comments
 (0)
Please sign in to comment.