Skip to content

Commit

Permalink
feat(material-experimental/mdc-form-field): Add option for dynamic su… (
Browse files Browse the repository at this point in the history
  • Loading branch information
kseamon authored and mmalerba committed Jan 24, 2022
1 parent 4ec34b5 commit 4076820
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 0 deletions.
75 changes: 75 additions & 0 deletions src/dev-app/mdc-input/mdc-input-demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,81 @@ <h4>Textarea</h4>
</mat-card-content>
</mat-card>

<mat-card class="demo-card demo-basic">
<mat-toolbar color="primary">Dynamic Subscript Sizing</mat-toolbar>
<mat-card-content>
<p>
One validation
<mat-form-field appearance="fill" [color]="color" subscriptSizing="dynamic">
<mat-label>Fill appearance</mat-label>
<input matInput [(ngModel)]="fillAppearance" required>
<mat-error>This field is required</mat-error>
</mat-form-field>
</p>

<p>
One very long validation that wraps
<mat-form-field appearance="fill" [color]="color" subscriptSizing="dynamic"
style="width: 212px">
<mat-label>Fill appearance</mat-label>
<input matInput [(ngModel)]="fillAppearance" required>
<mat-error>This field is extremely, very much, absolutely positively required so do not forget it!</mat-error>
</mat-form-field>
</p>

<p>
One hint and one validation
<mat-form-field appearance="fill" [color]="color" subscriptSizing="dynamic">
<mat-label>Fill appearance</mat-label>
<input matInput [(ngModel)]="fillAppearance" required>
<mat-error>This field is required</mat-error>
<mat-hint>Please type something here</mat-hint>
</mat-form-field>
</p>

<p>
Multiple errors
<mat-form-field appearance="fill" [color]="color" subscriptSizing="dynamic">
<mat-label>Fill appearance</mat-label>
<input matInput [(ngModel)]="fillAppearance" required>
<mat-error>AAA</mat-error>
<mat-error>BBB</mat-error>
<mat-error>CCC</mat-error>
</mat-form-field>
</p>

<p>
Multiple hints
<mat-form-field appearance="fill" [color]="color" subscriptSizing="dynamic">
<mat-label>Fill appearance</mat-label>
<input matInput>
<mat-hint>aaa</mat-hint>
<mat-hint>bbb</mat-hint>
<mat-hint>ccc</mat-hint>
</mat-form-field>
</p>

<p>
Multiple hints with differing alignment
<mat-form-field appearance="fill" [color]="color" subscriptSizing="dynamic">
<mat-label>Fill appearance</mat-label>
<input matInput>
<mat-hint>aaa</mat-hint>
<mat-hint align="end">bbb</mat-hint>
<mat-hint align="end">ccc</mat-hint>
</mat-form-field>
</p>

<p>
No hints or errors
<mat-form-field appearance="fill" [color]="color" subscriptSizing="dynamic">
<mat-label>Fill appearance</mat-label>
<input matInput>
</mat-form-field>
</p>
</mat-card-content>
</mat-card>

<mat-card class="demo-card demo-basic">
<mat-toolbar color="primary">Number Inputs</mat-toolbar>
<mat-card-content>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,23 @@
padding: 0 mdc-textfield-variables.$padding-horizontal;
}

.mat-mdc-form-field-subscript-dynamic-size {
.mat-mdc-form-field-hint-wrapper,
.mat-mdc-form-field-error-wrapper {
position: static;
}
}

.mat-mdc-form-field-bottom-align::before {
content: '';
display: inline-block;
height: 16px;
}

.mat-mdc-form-field-bottom-align.mat-mdc-form-field-subscript-dynamic-size::before {
content: unset;
}

.mat-mdc-form-field-hint-end {
order: 1;
}
Expand Down
1 change: 1 addition & 0 deletions src/material-experimental/mdc-form-field/form-field.html
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
</div>

<div class="mat-mdc-form-field-subscript-wrapper mat-mdc-form-field-bottom-align"
[class.mat-mdc-form-field-subscript-dynamic-size]="subscriptSizing === 'dynamic'"
[ngSwitch]="_getDisplayedMessages()">
<div class="mat-mdc-form-field-error-wrapper" *ngSwitchCase="'error'"
[@transitionMessages]="_subscriptAnimationState">
Expand Down
21 changes: 21 additions & 0 deletions src/material-experimental/mdc-form-field/form-field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ export type FloatLabelType = 'always' | 'auto';
/** Possible appearance styles for the form field. */
export type MatFormFieldAppearance = 'fill' | 'outline';

/** Behaviors for how the subscript height is set. */
export type SubscriptSizing = 'fixed' | 'dynamic';

/**
* Represents the default options for the form field that can be configured
* using the `MAT_FORM_FIELD_DEFAULT_OPTIONS` injection token.
Expand All @@ -69,6 +72,7 @@ export interface MatFormFieldDefaultOptions {
appearance?: MatFormFieldAppearance;
hideRequiredMarker?: boolean;
floatLabel?: FloatLabelType;
subscriptSizing?: SubscriptSizing;
}

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

/** Default way that the suffix element height is set. */
const DEFAULT_SUBSCRIPT_SIZING: SubscriptSizing = 'fixed';

/**
* Default transform for docked floating labels in a MDC text-field. This value has been
* extracted from the MDC text-field styles because we programmatically modify the docked
Expand Down Expand Up @@ -206,6 +213,20 @@ export class MatFormField
}
private _appearance: MatFormFieldAppearance = DEFAULT_APPEARANCE;

/**
* Whether the form field should reserve space for one line of hint/error text (default)
* or to have the spacing grow from 0px as needed based on the size of the hint/error content.
* Note that when using dynamic sizing, layout shifts will occur when hint/error text changes.
*/
@Input()
get subscriptSizing(): SubscriptSizing {
return this._subscriptSizing || this._defaults?.subscriptSizing || DEFAULT_SUBSCRIPT_SIZING;
}
set subscriptSizing(value: SubscriptSizing) {
this._subscriptSizing = value || this._defaults?.subscriptSizing || DEFAULT_SUBSCRIPT_SIZING;
}
private _subscriptSizing: SubscriptSizing = DEFAULT_SUBSCRIPT_SIZING;

/** Text for the form field hint. */
@Input()
get hintLabel(): string {
Expand Down
55 changes: 55 additions & 0 deletions src/material-experimental/mdc-input/input.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
MatFormField,
MatFormFieldAppearance,
MatFormFieldModule,
SubscriptSizing,
} from '@angular/material-experimental/mdc-form-field';
import {MatIconModule} from '@angular/material/icon';
import {By} from '@angular/platform-browser';
Expand Down Expand Up @@ -1406,6 +1407,47 @@ describe('MatFormField default options', () => {
expect(fixture.componentInstance.formField.hideRequiredMarker).toBe(true);
expect(fixture.componentInstance.formField.appearance).toBe('outline');
});

it('defaults subscriptSizing to false', () => {
const fixture = createComponent(MatInputWithSubscriptSizing);
fixture.detectChanges();

const subscriptElement = fixture.nativeElement.querySelector(
'.mat-mdc-form-field-subscript-wrapper',
);

expect(fixture.componentInstance.formField.subscriptSizing).toBe('fixed');
expect(subscriptElement.classList.contains('mat-mdc-form-field-subscript-dynamic-size')).toBe(
false,
);

fixture.componentInstance.sizing = 'dynamic';
fixture.detectChanges();

expect(fixture.componentInstance.formField.subscriptSizing).toBe('dynamic');
expect(subscriptElement.classList.contains('mat-mdc-form-field-subscript-dynamic-size')).toBe(
true,
);
});

it('changes the default value of subscriptSizing', () => {
const fixture = createComponent(MatInputWithSubscriptSizing, [
{
provide: MAT_FORM_FIELD_DEFAULT_OPTIONS,
useValue: {
subscriptSizing: 'dynamic',
},
},
]);

fixture.detectChanges();
expect(fixture.componentInstance.formField.subscriptSizing).toBe('dynamic');
expect(
fixture.nativeElement
.querySelector('.mat-mdc-form-field-subscript-wrapper')
.classList.contains('mat-mdc-form-field-subscript-dynamic-size'),
).toBe(true);
});
});

function configureTestingModule(
Expand Down Expand Up @@ -1815,6 +1857,19 @@ class MatInputWithAppearance {
appearance: MatFormFieldAppearance;
}

@Component({
template: `
<mat-form-field [subscriptSizing]="sizing">
<mat-label>My Label</mat-label>
<input matInput placeholder="Placeholder" required>
</mat-form-field>
`,
})
class MatInputWithSubscriptSizing {
@ViewChild(MatFormField) formField: MatFormField;
sizing: SubscriptSizing;
}

@Component({
template: `
<mat-form-field>
Expand Down

0 comments on commit 4076820

Please sign in to comment.