4

I have seen a lot of questions about this but none of them solved my issue.

What I have:

Angular 11, Angular Material 8 and a file input like this:

<div class="form-group">
    <input #myInput type="file" formControlName="fi"
                     id="fi" name="fi" (change)="postMethod($event.target.files)">
</div>

What I need:

I need to customize this button's color, text and size.

File input button style

How can I customize it?

3
  • Just style it with css. Commented Jul 25, 2019 at 8:49
  • Have you tried this answer stackoverflow.com/questions/52622061/… Commented Jul 25, 2019 at 8:53
  • 1
    You can read the doc of Angular Material, And if you have any trouble on the implementation, show your effort and your issue to get help. And if you need a specific style you need to do css. Commented Jul 25, 2019 at 8:53

4 Answers 4

6

Finally solved this way (Valid for Angular Material and Bootstrap):

I set 3 separated components:

  1. The button that will be visible (It can be an Angular Material one or a Bootstrap one, as seen below)
  2. The file input
  3. The label that will contain the file name

HTML

<div>
  <button #file class="btn btn-light">Examinate</button>
  <div style="display: inline-block">
      <input #myInput formControlName="file"
      id="file" name="file" (change)="postMethod($event.target.files)" type="file"/>
      <p>{{file}}</p>
  </div>
</div> 

CSS

With CSS I force the input to be overlay the button, and I set the opacity=0 so that the button is visible.

- Button:

float:left; 
position:absolute; 
z-index:-1;

- Input:

opacity: 0; //Not visible
font-size: 0;
//Button dimensions
width: 90px; 
height: 37px; 
float: left; 

- Input (Hover):

cursor: pointer;

- Label:

float: left; 
margin-left: 6px; 
margin-top: 7px;

And this is the final result:

Customized button

Sign up to request clarification or add additional context in comments.

Comments

2

You simply cannot style input type file, the best approach is to create overlay element that will corespond with input type file.

With material you can style pretty much everything that has somthing to do with material, of corse you can add classes from material to custom components but that is not what material is for.

Simple example, you dont want to do that:

<div class="mat-card"></div>

If you can do this:

<mat-card></mat-card>

The same is with input, if you want it to be material style you should create somthing like this:

HTML:

<mat-card class="input-container">
  <button #file mat-flat-button color="primary">Examinar...
      <input multiple (change)="onFileSelected($event)" style="opacity: 0; position:absolute; left:0px; top:0px; width:100%; height:100%;" type="file"/>
  </button>
  {{files|json}}
</mat-card>

TS:

  files: string[] = [];
  onFileSelected(event) {
    if (event.target.files.length > 0) {
      for (let i = 0; i < event.target.files.length; i++) {
        this.files.push(event.target.files[i].name);
        console.log(event.target.files[0].name);
      }
    }
  }

CSS:

.input-container {
  position:relative;
}

Thats a simple example.


But i will still prefer to use some kind of npm package like : https://www.npmjs.com/package/ngx-dropzone

3 Comments

Thanks for the answer. I tried your code but when I click the button, onSubmit() method is triggered instead of opening the file selector which is the behaviour I need for the click event. I guess it is not possible to do what I need.
Well without sample project its hard to say what can cause this problem. But you can check with setting opacity to 1 if input is in right place, without it beeing on top of button it wont work.
Seems that an input can't be inside a button link. Will try to join both with css.
1

You could change the style using css.

input[type=file]::file-selector-button {
  cursor: pointer;
  border: 0;
  padding: 8px;
  background-color: rgb(91, 105, 194);
  border-radius: 8px;
  color: white;
}

input[type=file]::file-selector-button:hover {
  background-color: rgb(54, 61, 115);
}
<div>
  <input
    type="file"
    [accept]="'.csv'"
    multiple/>
  <label>Select file</label>
</div>

Comments

-2

In your css/scss/sass:

#fi {
  background-color: pink;
  ...
}

It is not a good approach to style a single button with Angular Material. If you want to style groups, then i recommend to read this: https://material.angular.io/guide/customizing-component-styles

Edit:

Input elements of type file aren't trivial to style.

Here is a plunkr example how it can work:

.fileContainer {
    overflow: hidden;
    position: relative;
    cursor: pointer;
    background-color: pink;
}

.fileContainer [type=file] {
    cursor: inherit;
    display: block;
    font-size: 999px;
    filter: alpha(opacity=0);
    min-height: 100%;
    min-width: 100%;
    opacity: 0;
    position: absolute;
    right: 0;
    text-align: right;
    top: 0;
}
    <label class="fileContainer">
      File upload
      <input type="file"/>
    </label>

1 Comment

I need to style only the button of the input. Your solution styles the entire input (Incluiding the text in the image above)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.