Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to include a file upload control in an Angular2 reactive form?

For some weird reason, there are just no tutorials or code samples online showing how to use Angular2 Reactive forms with anything more than simple input or select dropdowns.

I need to create a form to let users select their avatar. (Image file)

The following doesn't work. (i.e. The Avatar property never shows any value changes.)

profile.component.html:

               <form [formGroup]="profileForm" novalidate>                                             <div class="row">                              <div class="col-md-4 ">                                  <img src="{{imgUrl}}uploads/avatars/{{getUserAvatar}}" style="width:150px; height:150px;float:left;border-radius:50%;margin-right:25px;margin-left:10px;">                                    <div class="form-group">                                      <label>Update Profile Image</label>                                      <input class="form-control" type="file" formControlName="avatar">                                  </div>                              </div>                              <div class="col-md-8 ">                                  <div class="form-group">                                      <label >Firstname:                                          <input class="form-control" formControlName="firstname">                                      </label>                                  </div>                                  <div class="form-group">                                      <label >Lastname:                                          <input class="form-control" formControlName="lastname">                                      </label>                                  </div>                                  <div class="form-group">                                      <label >Email:                                          <input class="form-control" formControlName="email">                                      </label>                                  </div>                                  <div class="form-group">                                      <label >Password:                                          <input class="form-control" type="password" formControlName="password">                                      </label>                                  </div>                              </div>                          </div>                                     </form>                  <p>Form value: {{ profileForm.value | json }}</p>                  <p>Form status: {{ profileForm.status | json }}</p>

profile.component.ts:

import { Component, OnInit } from '@angular/core';  import { FormBuilder, FormGroup,  Validators } from '@angular/forms';  import {Config} from '../../services/config.service';  import {AuthService} from '../../services/auth.service';  import {User} from '../../models/user.model';    @Component({    selector: 'app-profile',    templateUrl: './profile.component.html',    styleUrls: ['./profile.component.css']  })  export class ProfileComponent implements OnInit {        authUser:User;      profileForm : FormGroup;       constructor(private authService:AuthService, private fb: FormBuilder) {}                createForm() {      this.profileForm = this.fb.group({        firstname:  [this.authUser.firstname, Validators.required ],        lastname: [this.authUser.lastname, Validators.required ],        email: [this.authUser.email, Validators.required ],        avatar: [this.authUser.avatar, Validators.required ],        password:['xxxxxx', Validators.minLength(4)]       });    }    ngOnInit() {      this.authUser = this.authService.getAuthUser();        this.createForm();    } 
like image 755
Tuthmosis Avatar asked Apr 17 '17 02:04

Tuthmosis


People also ask

Can we use two way data binding in Reactive form?

You can use [(ngModel)] with Reactive forms. This will a completely different directive than the one that would be used without the formControlName .

What is the module suppose to be import to make use of angular Reactive forms?

To work with Reactive forms, we must import the ReactiveFormsModule . We usually import it in root module or in a shared module. The ReactiveFormsModule contains all the form directives and constructs for working with angular reactive forms.

What is the module name to be imported to get Reactive form?

To use Reactive forms in your application you need to import ReactiveFormsModule in your parent module.


2 Answers

Simple answer can be found here. https://devblog.dymel.pl/2016/09/02/upload-file-image-angular2-aspnetcore/

The HTML

    <input #fileInput type="file"/>      <button (click)="addFile()">Add</button>

Component.ts

@ViewChild("fileInput") fileInput;  addFile(): void { let fi = this.fileInput.nativeElement; if (fi.files && fi.files[0]) {     let fileToUpload = fi.files[0];     this.uploadService         .upload(fileToUpload)         .subscribe(res => {             console.log(res);         });     } } 

The service.ts

upload(fileToUpload: any) {     let input = new FormData();     input.append("file", fileToUpload);      return this.http.post("/api/uploadFile", input); } 
like image 161
Tuthmosis Avatar answered Oct 07 '22 09:10

Tuthmosis


I'm a bit late to this, but for anyone else that may come here looking for the same solution - This is my file input accessor that can be used with Reactive or Template-driven forms. Demo here.

There's some optional validation provided with it that can be used to check image dimensions and file size, extension, type, which is disabled by default.

npm i file-input-accessor and add the module to your AppModule imports:

import {BrowserModule} from '@angular/platform-browser'; import {FileInputAccessorModule} from "file-input-accessor";  @NgModule({     declarations: [         AppComponent     ],     imports: [         BrowserModule,         FileInputAccessorModule     ],     providers: [],     bootstrap: [AppComponent] }) export class AppModule {} 

Then use your file input like any other input:

<!--Reactive Forms--> <input type="file" multiple [formControl]="someFileControl" /> <input type="file" multiple formControlName="someFileControl" />  <!--Template-driven--> <input type="file" name="file-input" multiple [(ngModel)]="fileList" /> 

You can subscribe to valueChanges property just like any other reactive control.

like image 39
Jon Welker Avatar answered Oct 07 '22 10:10

Jon Welker