1

I want to have 2 form input fields in one row: 1. the first has a fixed with, 1. the second should grow and shrink, but this does not shrink below 180px.

Here is a full stack-blitz example

When you start the app, we see this
enter image description here

There maybe another issue:
I think the 2nd input field should already show the hint text and the horizontal line - but it will only show it when it get's the focus.
Is this the expected behaviour or am I missing something?

Anyway. The main issue is that the 2nd field does not shrink as expected. It will not shrink below 180px:
enter image description here

In the chrome dev-tool I can see that the input element is wrapped with a div class="mat-form-field-infix"> and the class mat-form-field-infix has a fixed width of 180px!

The only workaround that I came up with is to override this width with using ::ng-deep.
You can activate this in the co-input-field.component.scss file of the Stackblitz example

:host ::ng-deep .mat-form-field-infix {
  // width: auto !important;
  width: unset !important;
}

With this workaround the 2nd input shrinks as expected:
enter image description here

But ::ng-deep is deprecated and will be removed.
So what is the right way to make the input shrink as expected?

TmTron
  • 17,012
  • 10
  • 94
  • 142

2 Answers2

7

since .mat-form-field-infix has a fixed width of 180px there is no way of making form field shrink beyond 180px. inevitably .mat-form-field-infix must be overridden.

you can achive the same result with ::ng-deep in a couple of ways;

1.disable view encapsulation for that particular component. However, this approach has a huge drawback that all the styles in your component becomes global so they need to be managed carefully.

@Component({
    selector: 'app-co-input-field',
    templateUrl: './co-input-field.component.html',
    styleUrls: ['./co-input-field.component.scss'],
    encapsulation: ViewEncapsulation.None
})
export class CoInputFieldComponent {}

and then in co-input-field.component.scss you do the following

app-co-input-field {
    .mat-form-field-infix {
      width: auto !important;
    }
    // all other component styles goes in here
    // in order to keep them isolated from global scope
}

2.don't disable view encapsulation. use the element selector of parent component in global styles.

put the following in styles.scss

app-co-input-field {
    .mat-form-field-infix {
      width: auto !important;
    }
    // co-input-field.component.scss still can be used for encapsulated styles
}

3.don't disable view encapsulation. define a global rule for this particular situation.

put the following in styles.scss

.shrinking-mat-form-field {
    .mat-form-field-infix {
      width: auto !important;
    }
}

and apply the .shrinking-mat-form-field class to corresponding element

<mat-form-field style="width: 100%" class="shrinking-mat-form-field">
  <input matInput placeholder="placeholder"  />
  <mat-hint align="end">hint text</mat-hint>
</mat-form-field>

Even though second and third approaches are fundamentally same I personally prefer the third approach in order to make it readable, keep it consistent over the project, have minimal side effects and manage them from a single point.

ysf
  • 4,634
  • 3
  • 27
  • 29
  • [link](https://stackoverflow.com/q/53241725/1041641) to a related question about view-encapsulation to answer why the same css in the global `styles.scss` works differently than in the `component.scss` – TmTron Jun 03 '19 at 09:26
-1
:host ::ng-deep.mat-form-field-appearance-legacy .mat-form-field-infix {
  padding: 0.4375em 0;
  display: flex;
}
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
  • 1
    Please don't post only code as answer, but also provide an explanation what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotes. – Mark Rotteveel Nov 29 '22 at 09:52