Skip to content

fix(material-experimental/mdc-input): only apply styling when inside a form field #21876

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/material-experimental/mdc-chips/chip-input.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ describe('MDC-based MatChipInput', () => {

it('should set input styling classes', () => {
expect(inputNativeElement.classList).toContain('mat-mdc-input-element');
expect(inputNativeElement.classList).toContain('mat-mdc-form-field-control');
expect(inputNativeElement.classList).toContain('mat-mdc-chip-input');
expect(inputNativeElement.classList).toContain('mdc-text-field__input');
});
Expand Down
13 changes: 10 additions & 3 deletions src/material-experimental/mdc-chips/chip-input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ import {
Input,
OnChanges,
OnDestroy,
Optional,
Output
} from '@angular/core';
import {MatFormField, MAT_FORM_FIELD} from '@angular/material-experimental/mdc-form-field';
import {MatChipsDefaultOptions, MAT_CHIPS_DEFAULT_OPTIONS} from './chip-default-options';
import {MatChipGrid} from './chip-grid';
import {MatChipTextControl} from './chip-text-control';
Expand Down Expand Up @@ -127,9 +129,14 @@ export class MatChipInput implements MatChipTextControl, AfterContentInit, OnCha

constructor(
protected _elementRef: ElementRef<HTMLInputElement>,
@Inject(MAT_CHIPS_DEFAULT_OPTIONS) private _defaultOptions: MatChipsDefaultOptions) {
this.inputElement = this._elementRef.nativeElement as HTMLInputElement;
}
@Inject(MAT_CHIPS_DEFAULT_OPTIONS) private _defaultOptions: MatChipsDefaultOptions,
@Optional() @Inject(MAT_FORM_FIELD) formField?: MatFormField) {
this.inputElement = this._elementRef.nativeElement as HTMLInputElement;

if (formField) {
this.inputElement.classList.add('mat-mdc-form-field-control');
}
}

ngOnChanges() {
this._chipGrid.stateChanges.next();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ $mat-form-field-select-horizontal-end-padding: $mat-form-field-select-arrow-widt
// Remove the native select down arrow and ensure that the native appearance
// does not conflict with the form-field. e.g. Focus indication of the native
// select is undesired since we handle focus as part of the form-field.
select.mat-mdc-input-element {
select.mat-mdc-form-field-control {
-moz-appearance: none;
-webkit-appearance: none;
background-color: transparent;
Expand Down Expand Up @@ -82,7 +82,7 @@ $mat-form-field-select-horizontal-end-padding: $mat-form-field-select-arrow-widt

// Add padding on the end of the native select so that the content does not
// overlap with the Material Design arrow.
.mat-mdc-input-element {
.mat-mdc-form-field-control {
padding-right: $mat-form-field-select-horizontal-end-padding;
[dir='rtl'] & {
padding-right: 0;
Expand All @@ -104,7 +104,7 @@ $mat-form-field-select-horizontal-end-padding: $mat-form-field-select-arrow-widt
$dropdown-icon-color: rgba(mdc-theme-color.prop-value(on-surface), 0.54);
$disabled-dropdown-icon-color: rgba(mdc-theme-color.prop-value(on-surface), 0.38);

select.mat-mdc-input-element {
select.mat-mdc-form-field-control {
// On dark themes we set the native `select` color to some shade of white,
// however the color propagates to all of the `option` elements, which are
// always on a white background inside the dropdown, causing them to blend in.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@

// MDC uses the `subtitle1` level for the input label and value, but the spec shows `body1` as
// the correct level.
.mat-mdc-input-element,
.mat-mdc-form-field-control,
.mat-mdc-form-field label,
.mat-mdc-form-field-text-prefix,
.mat-mdc-form-field-text-suffix {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// Unset the border set by MDC. We move the border (which serves as the Material Design
// text-field bottom line) into its own element. This is necessary because we want the
// bottom-line to span across the whole form-field (including prefixes and suffixes).
.mat-mdc-input-element {
.mat-mdc-form-field-control {
border: none;
}

Expand All @@ -25,8 +25,8 @@
// not work for us since we support arbitrary form field controls which don't necessarily
// use an `input` element. We organize the vertical spacing on the infix container.
.mdc-text-field--no-label:not(.mdc-text-field--textarea)
.mat-mdc-input-element.mdc-text-field__input,
.mat-mdc-text-field-wrapper .mat-mdc-input-element {
.mat-mdc-form-field-control.mdc-text-field__input,
.mat-mdc-text-field-wrapper .mat-mdc-form-field-control {
height: auto;
}

Expand Down
23 changes: 23 additions & 0 deletions src/material-experimental/mdc-input/input.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -896,6 +896,17 @@ describe('MatMdcInput without forms', () => {
expect(formField.classList).toContain('mat-warn');
}));

it('should set a class on the input depending on whether it is in a form field', fakeAsync(() => {
const fixture = createComponent(MatInputInsideOutsideFormField);
fixture.detectChanges();

const inFormField = fixture.nativeElement.querySelector('.inside');
const outsideFormField = fixture.nativeElement.querySelector('.outside');

expect(inFormField.classList).toContain('mat-mdc-form-field-control');
expect(outsideFormField.classList).not.toContain('mat-mdc-form-field-control');
}));

});

describe('MatMdcInput with forms', () => {
Expand Down Expand Up @@ -1800,3 +1811,15 @@ class CustomMatInputAccessor {
class MatInputWithColor {
color: ThemePalette;
}


@Component({
template: `
<mat-form-field>
<input class="inside" matNativeControl>
</mat-form-field>

<input class="outside" matNativeControl>
`
})
class MatInputInsideOutsideFormField {}
10 changes: 7 additions & 3 deletions src/material-experimental/mdc-input/input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,17 @@ import {MatInput as BaseMatInput} from '@angular/material/input';
input[matNativeControl], textarea[matNativeControl]`,
exportAs: 'matInput',
host: {
'class': 'mat-mdc-input-element mdc-text-field__input',
// The BaseMatInput parent class adds `mat-input-element` and `mat-form-field-autofill-control`
// to the CSS classlist, but this should not be added for this MDC equivalent input.
'class': 'mat-mdc-input-element',
// The BaseMatInput parent class adds `mat-input-element`, `mat-form-field-control` and
// `mat-form-field-autofill-control` to the CSS class list, but this should not be added for
// this MDC equivalent input.
'[class.mat-form-field-autofill-control]': 'false',
'[class.mat-input-element]': 'false',
'[class.mat-form-field-control]': 'false',
'[class.mat-input-server]': '_isServer',
'[class.mat-mdc-textarea-input]': '_isTextarea',
'[class.mat-mdc-form-field-control]': '_isInFormField',
'[class.mdc-text-field__input]': '_isInFormField',
// Native input properties that are overwritten by Angular inputs need to be synced with
// the native input element. Otherwise property bindings for those don't work.
'[id]': 'id',
Expand Down
4 changes: 4 additions & 0 deletions src/material/input/input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ export class MatInput extends _MatInputMixinBase implements MatFormFieldControl<
/** Whether the component is a textarea. */
readonly _isTextarea: boolean;

/** Whether the input is inside of a form field. */
readonly _isInFormField: boolean;

/**
* Implemented as part of MatFormFieldControl.
* @docs-private
Expand Down Expand Up @@ -282,6 +285,7 @@ export class MatInput extends _MatInputMixinBase implements MatFormFieldControl<
this._isServer = !this._platform.isBrowser;
this._isNativeSelect = nodeName === 'select';
this._isTextarea = nodeName === 'textarea';
this._isInFormField = !!_formField;

if (this._isNativeSelect) {
this.controlType = (element as HTMLSelectElement).multiple ? 'mat-native-select-multiple' :
Expand Down
1 change: 1 addition & 0 deletions tools/public_api_guard/material/input.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export declare class MatInput extends _MatInputMixinBase implements MatFormField
protected _disabled: boolean;
protected _elementRef: ElementRef<HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement>;
protected _id: string;
readonly _isInFormField: boolean;
readonly _isNativeSelect: boolean;
readonly _isServer: boolean;
readonly _isTextarea: boolean;
Expand Down