Unable to assign a value to the HTMLInputElement's property: The input field can only be set to a filename or an empty string programmatically

When attempting to upload an image, I encountered the error message listed in the question title:

This is my template

<input type="file" formControlName="avatar" accept=".jpg, .jpeg .svg"
   #fileInput (change)="uploadImage($event)" />

<div class="avatar-preview">
  <ng-template #selectedImage>
    <div style.backgroundImage="{{'url('+ imageUrl +')'}}"></div>
  </ng-template>
</div>
<button (click)="fileInput.click()"></button>

And this is my component ts


@ViewChild('fileInput') el: ElementRef;
imageUrl: string = "";

this.profileForm = new FormGroup({
  avatar: new FormControl(null)
});

public uploadImage(event) {
    let reader = new FileReader();
    let file = event.target.files[0];
    if (event.target.files && event.target.files[0]) {
      reader.readAsDataURL(file);
      reader.onload = () => {
        this.imageUrl = reader.result as string;
        this.profileForm.patchValue({
          avatar: reader.result
        });
      }
    }
    this.cd.markForCheck(); 
}

Answer №1

Angular lacks a built-in ControlValueAccessor for handling file inputs. Instead, it utilizes the DefaultValueAccessor, which attempts to write the value of avatar to the control. However, this is not suitable for a FileInputControl.

To resolve this issue, you have two options:

  1. Implement your own ControlValueAccessor and transfer the functionality from your uploadImage function to it.
  2. Remove
    formControlName="avatar"
    and refrain from using reactive forms since you are already managing the events manually.

For example, you can create a directive like the one below (untested, may require adjustments):

@Directive({
  selector: 'input[type=file][formControlName]',
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: FileUploadAccessor,
      multi: true
    }
  ]
})
export class FileUploadAccessor implements ControlValueAccessor {
  private onChange: Function;

  @HostListener('change', ['$event.target.files']) emitFiles( event: FileList ) {
    const file = event && event.item(0);
    this.onChange(file);
  }

  constructor( private host: ElementRef<HTMLInputElement> ) {
  }

  writeValue( value: null ) {
    // clear file input
    this.host.nativeElement.value = '';
  }

  registerOnChange( fn: Function ) {
    this.onChange = fn;
  }

  registerOnTouched( fn: Function ) {
  }

}

If desired, you can also integrate your current processing logic into this directive by modifying the following section:

let reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
  this.onChange(reader.result as string);
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How can we adjust the number of items based on the width of the viewport in Vue.js?

Imagine having a template that showcases a specific number of items, like this: <template> <div> <div v-for="item in items.slice(0, 10)" :key="item" /> </div> </template> How can I adjust the numbe ...

A mistake was made: The template contains errors stating that 'app-my-profile' is an unknown element

I encountered an error message: "Uncaught Error: Template parse errors: 'app-my-profile' is not a known element," while working on setting up my profile service. import { BrowserModule } from '@angular/platform-browser'; import { NgM ...

A guide on transforming a 1-dimensional array into a 2-dimensional matrix layout using Angular

My query revolves around utilizing Template (HTML) within Angular. I am looking for a way to dynamically display an array of objects without permanently converting it. The array consists of objects. kpi: { value: string; header: string; footer: string }[] ...

What is the proper method for submitting a mail form via AJAX without using jQuery?

Currently, I am working on integrating a PHP mail form with AJAX. The aim is to create a straightforward form that collects user information such as phone numbers and sends it to my email address. While I have managed to set up the form to send emails usi ...

Utilizing PHP for Interactive JavaScript Modals

Encountering an issue with my JavaScript. The modal initially functions correctly, but upon clicking it for the second time, two modals appear - one from the previous click and another new one. The stacking of modals continues each time the button is cli ...

What steps can be taken to hide empty items in a list from being shown?

When I map over an array of books to display the titles in a list, I encounter an issue with the initial empty string value for the title. This causes the list to render an empty item initially. Below is my book array: @observable books = [ {title:" ...

csslimit overflow display only left side

I am struggling to implement a drag and drop feature resembling a shopping cart. Unfortunately, the content within the box is concealing the div I want to drag when moving out of the box. Is there a method to display only the content on the left side? Che ...

Unveiling RxJs: The secret to extracting the notifier value using the takeuntil operator

I have a straightforward Rxjs timer set up that runs until a notifier emits a signal, it's pretty basic so far. enum TimerResult = { COMPLETE, ABORTED, SKIPPED }; _notifier: Subject<TimerResult> = new Subject(); notifier$: Observab ...

AngularJS and CodeIgniter collaborating to bring server-side pagination

I am currently working on integrating pagination using AngularJS and CodeIgniter. The current implementation requires fetching all records at once. However, I aim to modify it so that the data can be retrieved one page at a time from the server during run ...

Is it possible to use a combination of pipe, tap, and subscribe in Angular

I am attempting to fetch data using HttpClient in Angular. Here's how my code appears: getData(suffurl: string, id?:number): Observable<any[]> { return this.http.get<any[]>('localhost:5555/DNZ/'+ this.suff_url) .pipe( ...

Hierarchy in CSS: The battle between author and user styling

Following a hierarchy of precedence: User agent declarations User normal declarations Author normal declarations Author important declarations User important declarations The CSS specification distinguishes between author and user: Author. The author s ...

The Fullpage.js embedded in an iframe is experiencing difficulty scrolling on iOS mobile devices

Trying to use Fullpage.js for a website with unique sections on different domains using full-screen iframes. However, encountering issues with scrolling on IOS mobile devices. The first solution rendered the page completely unscrollable: <iframe src=" ...

The back to top feature is malfunctioning when navigating to a new page

I've been working with jQuery Mobile to create some pages and wanted to add a "back to top" element. It's been functioning well, but I've encountered an issue. When I navigate from one page, let's say #sport, back to #restaurants after ...

Concealing a field when the PHP post is devoid of content

On page1.php, there is a form that, upon submission, redirects to page2.php where the selected information is summarized. The code snippet below on page2.php retrieves this information. I am attempting to dynamically hide certain rows if the PHP post is e ...

Issue with Angular 2: Route guard failing to work after browser refresh

Defining these routes in app.module.ts: ... { path: 'mypath', component: MyComponent, canActivate: [RouteGuard] }, { path: '', redirectTo: '/home', pathMatch: 'full' }, { path: '**', redirectTo: '/ho ...

Error message: "Uncaught TypeError in NextJS caused by issues with UseStates and Array

For quite some time now, I've been facing an issue while attempting to map an array in my NextJS project. The particular error that keeps popping up is: ⨯ src\app\delivery\cart\page.tsx (30:9) @ map ⨯ TypeError: Cannot read pr ...

What is the best way to transfer a JavaScript object with string values containing quotes from node.js to the browser?

I have a node/express application and need to send a JavaScript object to the browser. Currently, I achieve this by using JSON.stringify on the object and then embedding it into the HTML: In my Node.js/Express code: var myObject = /* fetched from databas ...

Alter the border color of a bootstrap-div using JavaScript

I need to update the border color of a div element, but I'm encountering issues when using a bootstrap class on the div. Is there a way to change the border color using Javascript? <link href="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/ ...

What is the best way to create a command that updates the status in Discord using discord.js?

I'm currently working on a command for my Discord bot using discord.js. The purpose of this command is to change the bot's status whenever an admin of the server triggers it. I've attempted to create the command, but unfortunately, it's ...

Comparing React-Highcharts to regular Highcharts

Despite my efforts to find information on this topic through search engines, I have come up empty. So, I am turning to you with my question. Can someone explain the distinction between these two NPM packages: https://www.npmjs.com/package/highcharts htt ...