Search results

Form Support in Angular Uploader component

The uploader component works with HTML form like default file input. The following configuration is must to make the uploader work inside the form.

*   `saveUrl` and `removeUrl` must be null.
*   `autoUpload` must be disabled.
*   `name` attribute must be added in input element.

The selected or dropped files are received as a collection in form action when the form is submitted. The form action handles the server-side operations that manage the file upload process. When you reset the form, the file list and data will be cleared.

Source
Preview
app.component.ts
app.module.ts
main.ts
import { Component, ViewChild } from '@angular/core';
import { EmitType } from '@syncfusion/ej2-base';
import { Dialog } from '@syncfusion/ej2-popups';
import { FormValidator, FormValidatorModel } from '@syncfusion/ej2-inputs';
/**
 * Default Uploader Default Component
 */
@Component({
    selector: 'app-root',
    templateUrl: 'formsupport.html',
    styleUrls: ['formsupport.css']
})
export class AppComponent {
    @ViewChild('Dialog')
    public Dialog: DialogComponent;
     public width: string = '335px';
     public visible: boolean = false;
     public content: string = 'Your details has been updated successfully, Thank you';
     public target: string = '#control_wrapper';
     public isModal: boolean = true;
     public animationSettings: object = {
            effect: 'Zoom'
        }
     public options: object = {
            rules: {
            'name': {
                required: true
            },
            'email': {
                required: true
            },
            'upload': {
                required: true
            }
            }
        }

        @ViewChild('formElement') element: any;

        ngAfterViewInit() {
          let formObject: FormValidator = new FormValidator(this.element.nativeElement, this.options);
        // validate all input elements in the form
            }

     browseClick() {
        document.getElementsByClassName('e-file-select-wrap')[0].querySelector('button').click(); return false;
      }
    Submit() {
            this.onFormSubmit();
    }
    public onFileSelect: EmitType<Object> = (args: any) => {
        let inputElement: HTMLInputElement  = document.getElementById('upload') as HTMLInputElement;
        inputElement.value = args.filesData[0].name;
    }

    // Close the modal Dialog on overlay click
    public overlayClick(): void {
        this.Dialog.hide();
    }

    public onFormSubmit(): void {
    let formObject: FormValidator = new FormValidator("#form1", this.options);
    let formStatus: Boolean = formObject.validate();
    if (formStatus) {
       formObject.element.reset();
        this.Dialog.show();
    }
    }
}
import { AppComponent } from './app.component';
import { HttpModule, JsonpModule } from '@angular/http';
import { BrowserModule } from '@angular/platform-browser';
import 'rxjs/add/operator/map';
import { NgModule, ModuleWithProviders, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { FormsModule }   from '@angular/forms';
import { UploaderModule } from '@syncfusion/ej2-angular-inputs';
import { DialogModule } from '@syncfusion/ej2-angular-popups';

/**
 * Module
 */
@NgModule({
    imports: [
        UploaderModule, DialogModule, FormsModule, HttpModule, JsonpModule, BrowserModule
    ],
    declarations: [AppComponent],
    bootstrap: [AppComponent]
})
export class AppModule {
}
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';

enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);

Template-driven forms

By using ngModel directive, you can bind the model to the uploader in template-driven forms. For more details, refer to the Angular Documentation

The following sample demonstrates how to render uploader component with required validation inside the template-driven forms.

Source
Preview
app.component.ts
app.module.ts
main.ts
index.css
import { Component, OnInit, ViewChild } from '@angular/core';
import { DialogComponent } from '@syncfusion/ej2-angular-popups';
import { EmitType } from '@syncfusion/ej2-base';

@Component({
  selector: 'app-root',
  template: `<div class="control-section">
        <div class="col-lg-12">
          <h4 class="form-title">Photo Contest</h4>
        <div class="control_wrapper" id="control_wrapper" style="margin: 10px auto;">
            <form id="template_driven" #userForm="ngForm" novalidate>
                <div class="form-group" style="padding-top: 11px;">
                    <div class="e-float-input">
                        <input type="text" id="name" #nameval='ngModel' name="name" required ngModel>
                        <span class="e-float-line"></span>
                        <label class="e-float-text e-label-top" for="name">Name</label>
                        <div *ngIf="(nameval.invalid && (nameval.dirty || nameval.touched))">
                            <div class="e-error" *ngIf="nameval.errors.required">
                                * Enter your name
                            </div>
                        </div>
                    </div>
                </div>
                  <div class="form-group" style="padding-top: 11px;">
                      <div class="e-float-input upload-area">
                          <input type="text" id="upload" #uploadval='ngModel' [(ngModel)]="uploadInput" readonly name="upload" required ngModel>
                          <button id="browse" class="e-control e-btn e-info" (click)='browseClick()'>Browse...</button>
                          <span class="e-float-line"></span>
                          <label class="e-float-text e-label-top" for="upload">Choose a file</label>
                          <div *ngIf="(uploadval.invalid && (uploadval.dirty || uploadval.touched))">
                              <div class="e-error" *ngIf="uploadval.errors.required">
                                  * Select a file
                              </div>
                          </div>
                      </div>
                      <ejs-uploader #defaultupload id='fileupload' allowedExtensions="image/*" [autoUpload]=false [multiple]='multiple' (selected)='onFileSelect($event)'></ejs-uploader>
                  </div>

                  <div class="form-group" style="padding-top: 11px;">
                    <div class="submitBtn">
                        <button class="submit-btn e-btn" id="submit-btn" [disabled]="userForm.invalid" type="reset" (click)= "Submit()">Submit</button>
                        <div class="desc"><span>*This button is not a submit type and the form submit handled from externally.</span></div>
                    </div>
                  </div>
          </form>
          <ejs-dialog id="confirmationDialog" #Dialog [buttons]='dlgButtons' [animationSettings]='animationSettings' [header]='formHeader' [showCloseIcon]='showCloseIcon' [content]='content'  [target]='target' [width]='width' [visible]="visible" [isModal]="isModal" >
          </ejs-dialog>
    </div>
  </div>
</div>`
})
export class AppComponent  {
  @ViewChild('Dialog')
  public dialogObj: DialogComponent;
  public width: string = '335px';
  public visible: boolean = false;
  public multiple: boolean = false;
  public showCloseIcon: Boolean = true;
  public formHeader: string = 'Success';
  public content: string = 'Your details have been updated successfully, Thank you.';
  public target: string = '#control_wrapper';
  public isModal: boolean = true;
  public animationSettings: object = {
    effect: 'Zoom'
  };
  public uploadInput: string = '';
  public dlgBtnClick: EmitType<object> = () => {
    this.dialogObj.hide();
  }
  public dlgButtons: Object[] = [{ click: this.dlgBtnClick.bind(this), buttonModel: { content: 'Ok', isPrimary: true } }];
    @ViewChild('formElement') element: any;

  public browseClick() {
     document.getElementsByClassName('e-file-select-wrap')[0].querySelector('button').click(); return false;
   }
   public Submit(): void {
    this.onFormSubmit();
  }
 public onFileSelect: EmitType<Object> = (args: any) => {
  this.uploadInput = args.filesData[0].name;
 }

 public onFormSubmit(): void {
   this.dialogObj.show();
 }
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { ButtonModule } from '@syncfusion/ej2-angular-buttons';
import { DialogModule } from '@syncfusion/ej2-angular-popups';
import { UploaderModule } from '@syncfusion/ej2-angular-inputs';


@NgModule({
  imports:      [ BrowserModule, FormsModule, DialogModule, UploaderModule, ButtonModule, ReactiveFormsModule ],
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app.module';

platformBrowserDynamic().bootstrapModule(AppModule).then(ref => {
  // Ensure Angular destroys itself on hot reloads.
  if (window['ngRef']) {
    window['ngRef'].destroy();
  }
  window['ngRef'] = ref;

  // Otherwise, log the boot error
}).catch(err => console.error(err));
#container {
  visibility: hidden;
}

#loader {
  color: #008cff;
  height: 40px;
  left: 45%;
  position: absolute;
  top: 45%;
  width: 30%;
}.control_wrapper {
  max-width: 500px;
  min-width: 245px;
  margin: auto;
}
.address-field {
resize: none;
}

.e-error {
  padding-top: 7px;
}

#control_wrapper {
max-width: 500px;
margin: auto;
border: 0.5px solid #BEBEBE;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.36);
padding: 1% 4% 0%;
background: #f9f9f9;
}
.highcontrast #control_wrapper {
background: #000000;
}
#template_driven .upload-area {
width: 100%;
}
#template_driven .form-group .submit-btn {
margin-top: 15px;
position: relative;            
}
#template_driven .form-group .desc {
margin: 2% 23% 0% 18%;
}
@media only screen and (max-width: 500px) {
  #template_driven .form-group .submitBtn .desc {
  margin: 12px;
}
}
#template_driven .form-group .submitBtn {
position: relative;        
text-align: center;
}
.bootstrap #template_driven .form-group .submit-btn {
margin-left: 8px;          
}
.e-bigger.material #template_driven .form-group .submit-btn {
margin-left: -7px;          
}
.fabric #template_driven .form-group .submit-btn, .highcontrast #template_driven .form-group .submit-btn {
margin-left: -11px;          
}
.e-bigger.fabric #template_driven .form-group .submit-btn, .e-bigger.highcontrast #template_driven .form-group .submit-btn {
margin-left: -25px;          
}
.e-bigger.bootstrap #template_driven .form-group .submit-btn {
margin-left: -8px;          
}
.success .successmsg {
border: 0.5px solid green;
padding: 10%;
color: green;
}
form#template_driven {
position: relative;
top: 14%;
}
.material #template_driven .form-group .e-upload, #template_driven .form-group .e-upload {
display: none;
}
#template_driven .upload-area button#browse {
float: right;
margin-top: -28px;
}
.fabric #template_driven .upload-area button#browse,
.highcontrast #template_driven .upload-area button#browse {
  float: right;
  margin-top: -32px;
  }
  .bootstrap #template_driven .upload-area button#browse {
  float: right;
  margin-top: -35px;
  }
  .fabric.e-bigger #template_driven .upload-area button#browse,
.highcontrast.e-bigger #template_driven .upload-area button#browse,
.bootstrap.e-bigger #template_driven .upload-area button#browse {
    margin-top: -40px;
  }
  .material.e-bigger #template_driven .upload-area button#browse {  
    margin-top: -36px;
    }
  .b
#template_driven .form-group .e-float-input.upload-area .e-float-line, .material .e-float-input.upload-area .e-float-line {  
  width: 70%;
  margin-top: initial;
}
#template_driven .form-group .upload-area input {
width: 70%;
}

@media (min-width: 250px) and (max-width: 500px) {
#control_wrapper.control_wrapper {
  padding: 1% 4% 12%;
}
}
@media (max-width: 300px) {
#control_wrapper.control_wrapper {
  padding: 1% 4% 15%;
}
}
.bootstrap #template_driven .form-group .upload-area {
 background: transparent;
}
.form-title {
text-align: center;
}

Reactive forms

You can render the uploader component inside the reactive forms. The reactive forms rendered with the help of FormGroup. For more details, refer to the Angular Documentation

The following sample demonstrates how to render uploader component with required validation inside the reactive forms.

Source
Preview
app.component.ts
app.module.ts
field-error-display.component.ts
main.ts
index.css
import { Component, Inject, OnInit, ViewChild } from '@angular/core';
import { FormGroup, FormBuilder, Validators, FormControl } from '@angular/forms';
import { EmitType } from '@syncfusion/ej2-base';
import { DialogComponent } from '@syncfusion/ej2-angular-popups';

@Component({
  selector: 'app-root',
  template: `<div class="control-section">
    <div class="col-lg-12">
      <h4 class="form-title">Photo Contest</h4>
        <div class="control_wrapper" id="control_wrapper" style="margin: 25px auto;">
          <form id="reactive" [formGroup]="form">
              <div class="form-group" style="padding-top: 11px;">
                  <div class="e-float-input">
                      <input type="text" id="name" name="name" class="required" formControlName="name">
                      <span class="e-float-line"></span>
                      <label class="e-float-text e-label-top" for="name">Name</label>
                  </div>
                  <app-field-error-display [displayError]="isFieldValid('name')" errorMsg="* Please Enter your name">
                  </app-field-error-display>
              </div>
              <div class="form-group" style="padding-top: 11px;">
                  <div class="e-float-input upload-area">
                      <input type="text" id="upload" name="upload" [(ngModel)]="uploadInput" readonly formControlName="upload" class="required">
                      <button id="browse" class="e-control e-btn e-info" (click)='browseClick()'>Browse...</button>
                      <span class="e-float-line"></span>
                      <label class="e-float-text e-label-top" for="upload">Choose a file</label>
                  </div>
                  <app-field-error-display [displayError]="isFieldValid('upload')" errorMsg="* Select any file">
                  </app-field-error-display>
                  <ejs-uploader #defaultupload id='fileupload' allowedExtensions="image/*" [autoUpload]=false [multiple]='multiple' (selected)='onFileSelect($event)'></ejs-uploader>
              </div>
              <div class="form-group" style="padding-top: 11px;">
                <div class="submitBtn">
                  <button class="submit-btn e-btn" id="submit-btn" [disabled]="form.invalid" (click)= "Submit()">Submit</button>
                  <div class="desc"><span>*This button is not a submit type and the form submit handled from externally.</span></div>
                </div>
              </div>
          </form>
          <ejs-dialog id="confirmationDialog" #Dialog [buttons]='dlgButtons' [animationSettings]='animationSettings' [header]='formHeader' [showCloseIcon]='showCloseIcon' [content]='content'  [target]='target' [width]='width' [visible]="visible" [isModal]="isModal" >
          </ejs-dialog>
      </div>
    </div>
</div>`
})
export class AppComponent  {
    @ViewChild('Dialog')
    public dialogObj: DialogComponent;
    public form: FormGroup;
    public width: string = '335px';
    public visible: boolean = false;
    public multiple: boolean = false;
    public showCloseIcon: Boolean = true;
    public formHeader: string = 'Success';
    public content: string = 'Your details have been updated successfully, Thank you.';
    public target: string = '#control_wrapper';
    public isModal: boolean = true;
    public animationSettings: any = {
          effect: 'Zoom'
      };
   private formSumitAttempt: boolean;
   public dlgBtnClick: EmitType<object> = () => {
    this.dialogObj.hide();
  }
  public dlgButtons: Object[] = [{ click: this.dlgBtnClick.bind(this), buttonModel: { content: 'Ok', isPrimary: true } }];
  public uploadInput: string = '';
  public browseClick() {
      document.getElementsByClassName('e-file-select-wrap')[0].querySelector('button').click(); return false;
    }
  public Submit(): void {
    this.onFormSubmit();
  }
  public onFileSelect: EmitType<Object> = (args: any) => {
    this.uploadInput = args.filesData[0].name;
  }

  public onFormSubmit(): void {
    this.formSumitAttempt = true;
    if (this.form.valid) {
      this.dialogObj.show();
      this.form.reset();
    } else {
      this.validateAllFormFields(this.form);
    }
  }

  constructor(@Inject(FormBuilder) public formBuilder: FormBuilder) {}

  ngOnInit() {
    this.form = this.formBuilder.group({
      name: [null, Validators.required],
      upload: [null, Validators.required],
    });
  }

  isFieldValid(field: string) {
    return ((!this.form.get(field).valid && this.form.get(field).touched) ||
    (this.form.get(field).untouched && this.formSumitAttempt));
  }

  validateAllFormFields(formGroup: FormGroup) {
    Object.keys(formGroup.controls).forEach(field => {
      const control = formGroup.get(field);
      if (control instanceof FormControl) {
        control.markAsTouched({ onlySelf: true });
      } else if (control instanceof FormGroup) {
        this.validateAllFormFields(control);
      }
    });
  }
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { UploaderModule } from '@syncfusion/ej2-angular-inputs';
import { ButtonModule } from '@syncfusion/ej2-angular-buttons';
import { DialogModule } from '@syncfusion/ej2-angular-popups';
import { FieldErrorDisplayComponent } from './field-error-display.component';
/**
 * Module
 */
@NgModule({
  imports:      [ BrowserModule, FormsModule, DialogModule, UploaderModule, ButtonModule, ReactiveFormsModule ],
  declarations: [ AppComponent, FieldErrorDisplayComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }
import { Component, Input, ViewEncapsulation } from '@angular/core';

@Component({
  selector: 'app-field-error-display',
  styleUrls: ['field-error-display.component.css'],
  encapsulation: ViewEncapsulation.None,
  template: `<div *ngIf="displayError" >
                <div class="e-error">
                  {{ errorMsg }}
                </div>
              </div>`
})
export class FieldErrorDisplayComponent {

  @Input() errorMsg: string;
  @Input() displayError: boolean;

}
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { AppModule } from './app.module';

platformBrowserDynamic().bootstrapModule(AppModule).then(ref => {
  // Ensure Angular destroys itself on hot reloads.
  if (window['ngRef']) {
    window['ngRef'].destroy();
  }
  window['ngRef'] = ref;

  // Otherwise, log the boot error
}).catch(err => console.error(err));
#container {
  visibility: hidden;
}
#loader {
  color: #008cff;
  height: 40px;
  left: 45%;
  position: absolute;
  top: 45%;
  width: 30%;
}
.control_wrapper {
  max-width: 500px;
  min-width: 245px;
  margin: auto;
}
.address-field {
resize: none;
}
#control_wrapper {
  max-width: 500px;
  margin: auto;
  border: 0.5px solid #BEBEBE;
  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.36);
  padding: 1% 4% 0%;
  background: #f9f9f9;
}
.highcontrast #control_wrapper {
background: #000000;
}
#reactive .form-group .upload-area {
width: 100%;
}
.e-error {
padding-top:3px;
}
#reactive .form-group .submit-btn {
margin-top: 15px;
position: relative;            
}
#reactive .form-group .submitBtn .desc {
margin: 2% 23% 0% 18%;
}
@media only screen and (max-width: 500px) {
#reactive .form-group .submitBtn .desc {
  margin: 12px;
}
}
#reactive .form-group .submitBtn {
position: relative;        
text-align: center;
}
.bootstrap #reactive .form-group .submit-btn {
margin-left: 8px;          
}
.e-bigger.material #reactive .form-group .submit-btn {
margin-left: -7px;          
}
.fabric #reactive .form-group .submit-btn, .highcontrast #reactive .form-group .submit-btn {
margin-left: -11px;          
}
.e-bigger.fabric #reactive .form-group .submit-btn, .e-bigger.highcontrast #reactive .form-group .submit-btn {
margin-left: -25px;          
}
.e-bigger.bootstrap #reactive .form-group .submit-btn {
margin-left: -8px;          
}
.success .successmsg {
border: 0.5px solid green;
padding: 10%;
color: green;
}
form#reactive {
position: relative;
top: 14%;
}
.material #reactive .form-group .e-upload, #reactive .form-group .e-upload {
display: none;
}
#reactive .upload-area button#browse {
float: right;
margin-top: -28px;
}
.material.e-bigger #reactive .upload-area button#browse {  
  margin-top: -36px;
  }
.fabric #reactive .upload-area button#browse,
.highcontrast #reactive .upload-area button#browse {
  float: right;
  margin-top: -32px;
  }
.fabric.e-bigger #reactive .upload-area button#browse,
.highcontrast.e-bigger #reactive .upload-area button#browse,
.bootstrap.e-bigger #reactive .upload-area button#browse {
    margin-top: -40px;
  }
  .bootstrap #reactive .upload-area button#browse {
  float: right;
  margin-top: -35px;
  }  
#reactive .form-group .e-float-input.upload-area .e-float-line, .material .e-float-input.upload-area .e-float-line {  
  width: 70%;
  margin-top: initial;
}
#reactive .form-group .upload-area input {
width: 70%;
}

@media (min-width: 250px) and (max-width: 500px) {
#control_wrapper.control_wrapper {
  padding: 1% 4% 12%;
}
}
@media (max-width: 300px) {
#control_wrapper.control_wrapper {
  padding: 1% 4% 15%;
}
}
.bootstrap #reactive .form-group .upload-area {
 background: transparent;
}
.form-title {
text-align: center;
}