How to implement a Material Designed <input type='file'> field built on "MudBlazor"?
Tags: blazor, dotnet, mudblazor, materialdesign
Published: 2021-03-27 14:11:15

# Prologue

This article describes a technic of "Blazor" Web application programming - that is a framework for building web apps in C#.

There are some UI component libraries that can use to implement  Blazor application that is Material Designed.

One of the libraries which I prefer is **"MudBlazor"**.

{% github https://github.com/Garderoben/MudBlazor no-readme %}

"MudBlazor" provides many useful components for developers.
However, "MudBlazor" doesn't provide a file picker component (it means "MudBlazor" version of a `<input type='file'>` HTML element).

![fig001](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e0k6ozb9fglxlpvnc6st.png)

So I started to implement a Material Designed file picker component built on the "MudBlazor".

# Basic concept

To implement a file picker component that has a customized appearance, we can use a `<label>` element for this purpose.

A `<label>` element can be associated with a `<input type='file'>` element by it's Id, like this:

```html
<input type='file' id='foo' />
<label for='foo'>Chose File</label>
```

On the HTML page above, a file picker dialog will be opened when a user clicks the "Choose File" label **even if the `<input type='file'>` element is invisible**.

![movie-001](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6sddm2jmw69gytjvyj1p.gif) 

That's all of the basic concepts.

I will show the story that I improved this HTML code to be what I want to make it to be in the following sections.

# Make the appearance of the label to be Material Designed button

At first, we have to use a `<InputFile>` official Blazor component instead of a native `<input type='file'>` HTML element to integrate with our C# code.

And, we have to hide the `<InputFile>` component because we will build a customized appearance by ourselves.

```html
<!-- 👇 Use this component to integrate with C# code, -->
<!--    and hide it. -->
<InputFile Id='foo' style="display:none;" />
<label for='foo'>CLICK ME!</label>
```

Next, I want to make the appearance of the label to be a Material Designed button.

What I have to do to do this is very easy. 
It just applies CSS classes that are provided by "MudBlazor".

I applied the CSS classes below to the label.

- mud-button-root 
- mud-button 
- mud-button-filled 
- mud-button-filled-primary 
- mud-button-filled-size-medium 
- mud-ripple

```html
...
<label ... class="mud-button-root mud-button mud-button-filled mud-button-filled-primary mud-button-filled-size-medium mud-ripple">
  Choose File
</label>
```

After doing this, we can see the label on the browser but the appearance of the label became the same with a `<MudButton>` component.

![fig003](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/414lxz1ej3k3vzvl0x3o.png) 

# Add an element like an input field

Next, I want to display an element that has a similar appearance to a `<MudTextField>` component to show a picked file name, like native `<input type='file'>` HTML element.

For to do this, we have to markup 3 parts of the bellow.

- The caption field to display the title of this file picker field.
- The field like a read-only `<input>` element to display a picked file name.
- The help text field displays some helpful text such as validation error messages.

I'll explain the details of the above step by step in the following sections.


## Markup the caption field

To implement the caption field that has the same appearance as the other "MudBlazor" component such as the `<MudTextField>` component, we can use the `<MudText>` component with the `Type` property is `Typo.caption`.

```html
<MudText Typo="Typo.caption">
    Avatar picture file
</MudText>
```

![fig004](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kx58ohk6zlskmq7ux2fd.png)

## Markup the field that resembles an input element to display a picked file name

This is just a field "like" an input element, is not real `<input>` HTML element, because the user can't input any keystrokes in this field.

Therefore I implemented this field by using a normal `<label>` HTML element with custom CSS styling applied to make it resemble a `<MudInput>` component.

One of the important points to do this is, how to set the color of the underline of this element same with `<MudInput>` 's it.

Fortunately, "MudBlazor" exposes its theme colors as standard ["CSS variables"](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties).

So I could apply the same color with "MudBlazor" to my custom `<label>` element by CSS code as below.

```css
.selected-file-name {
  border-bottom: solid 1px var(--mud-palette-lines-inputs);
}
```

![fig005](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/73mhrkhqxl2oetxa3gyh.png)
 
This is a standard way of general Web application programming and markup.

## Markup the help text field

We can markup the help text field in the same way.

Wa have to do to markup the help text field is just apply CSS class that is provided by "MudBlazor", like this:

```html
<div class="mud-input-helper-text">
    Max allowed file size is 512KB.
</div>
```

![fig006](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6j40izbuzyfeb1gxiow9.png)
 
If we have to display the help text field as an error message,  apply the `--mud-palette-error` CSS variable for the text color of the field.

# It was completed!

Finally, we created the Material Designed file picker component that has a similar appearance with a `<MudTextField>` component.

![movie-002](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ztzeq7saju97oxztfn9i.gif)
 
All of the code of this article is published on my GitHub repository (follow the URL below).

{% github https://github.com/sample-by-jsakamoto/MudBlazorInputFile/ no-readme %} 

# Notice

Unfortunately, this component doesn't accept any manipulations from a keyboard unlikely normal `<input type='file'>` HTML element.

And also, it doesn't accept drag & drop a file.

If you have to implement the above features, I have no idea at this time.
I think I can do it by "ClickJacking", but I do not want to recommend it because it is a dirty hack.

# Conclusion

"MudBlazor" is exposing its parameters such as size information, theme colors, as CSS variables - it is Web standard way.

So we can implement a component that has the same appearance as the other "MudBlazor"'s components by referring to those CSS variables.

_Learn, Practice, Share!_