All Components

Forms Support

You can use the Upload in template-driven or reactive forms.

The component supports the required built-in Angular validation and builds on top of that with custom restrictions for file extensions, minimum, and maximum file size.

Template-Driven Forms

The template-driven forms enable you to bind the Upload to the model by using the ngModel directive.

The following example demonstrates how to utilize the required validation and the restrictions configuration option. With these settings in place, the form will become valid when an image file is successfully uploaded.

import { Component } from '@angular/core';
import { FileInfo, FileRestrictions } from '@progress/kendo-angular-upload';

@Component({
  selector: 'my-upload',
  template: `
  <div class="example-config">
    <p>Valid: {{ myForm.valid }}</p>
    <p>Submitted: {{ myForm.submitted }}</p>
  </div>
  <form #myForm="ngForm" novalidate (ngSubmit)="save(myForm.value, myForm.valid)" class="example-wrapper">
    <div class="container-fluid">
      <div class="row">
        <div class="col-xs-12 col-sm-6">
          <label style="display: block; margin: .8em 0 .2em">Username:</label>
          <input type="text" name="uName" #uName="ngModel" [(ngModel)]="userName" required minlength="4" class="k-textbox" style="width: 100%" />
          <p style="color: red; font-size: .8em; margin-top: .5em;" [hidden]="uName.valid || (uName.pristine && !myForm.submitted)">Username is required and should be minimum 4 characters.</p>
          <label style="display: block; margin: .8em 0 .2em">Avatar:</label>
          <kendo-upload required
            name="myUpload" #myUpload="ngModel"
            [saveUrl]="uploadSaveUrl"
            [removeUrl]="uploadRemoveUrl"
            [restrictions]="myRestrictions"
            [(ngModel)]="userImages">
          </kendo-upload>
          <p style="color: red; font-size: .8em; margin-top: .5em;" [hidden]="myUpload.valid || (myUpload.pristine && !myForm.submitted)">Uploading an avatar is required.</p>
          <button type="submit" class="k-button k-primary" style="margin: 1em 0;">Submit</button>
        </div>
      </div>
    </div>
  </form>
  `
})
export class UploadComponent {
  uploadSaveUrl: string = "saveUrl";
  uploadRemoveUrl: string = "removeUrl";

  public myRestrictions: FileRestrictions = {
    allowedExtensions: ["jpg", "jpeg", "png"]
  };

  public userName: string;
  public userImages: Array<FileInfo>;

  save(value: any, valid: boolean) {
    if (valid) {
      console.log("Everything is OK!");
    }
  }
}
import { Component, Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpProgressEvent, HttpEventType, HttpResponse } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/delay';
import 'rxjs/add/observable/of';
import 'rxjs/add/observable/concat';

@Component({
    selector: 'my-app',
    template: `<my-upload></my-upload>`
})
export class AppComponent {
}

@Injectable()
export class UploadInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (req.url === "saveUrl") {
      let events: Observable<HttpEvent<any>>[] = [0, 30, 60, 100].map((x) => Observable.of(<HttpProgressEvent>{
        type: HttpEventType.UploadProgress,
        loaded: x,
        total: 100
      }).delay(1000));

      const success = Observable.of(new HttpResponse({ status: 200 })).delay(1000);
      events.push(success);

      return Observable.concat(...events);
    }

    if (req.url === "removeUrl") {
        return Observable.of(new HttpResponse({ status: 200 }));
    }

    return next.handle(req);
  }
}
import { enableProdMode, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { UploadModule } from '@progress/kendo-angular-upload';
import { AppComponent }   from './app.component';
import { UploadComponent }  from './upload.component';
import { FormsModule } from '@angular/forms';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

@NgModule({
  imports:      [ BrowserModule, HttpClientModule, UploadModule, FormsModule, BrowserAnimationsModule ],
  declarations: [ AppComponent, UploadComponent ],
  bootstrap:    [ AppComponent ]
})

export class AppModule { }

enableProdMode();

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule);

Reactive Forms

The FormGroup provides a way to render reactive forms. For more details, refer to the Angular Documentation.

The following example demonstrates how to use the Upload in a reactive form.

import { Component, OnInit } from '@angular/core';
import { FileInfo, FileRestrictions } from '@progress/kendo-angular-upload';
import { FormBuilder, FormGroup, Validators } from "@angular/forms";

@Component({
  selector: 'my-upload',
  template: `
  <div class="example-config">
    <p>Valid: {{ myForm.valid }}</p>
    <p>Submitted: {{ submitted }}</p>
  </div>
  <form [formGroup]="myForm" novalidate (ngSubmit)="save(myForm.value, myForm.valid)">
    <div class="container-fluid">
      <div class="row">
        <div class="col-xs-12 col-sm-6">
          <label style="display: block; margin: .8em 0 .2em">Username:</label>
          <input type="text" formControlName="uName" class="k-textbox" style="width: 100%" />
          <p style="color: red; font-size: .8em; margin-top: .5em;" [hidden]="myForm.controls.uName.valid || (myForm.controls.uName.pristine && !submitted)">Username is required and should be minimum 4 characters.</p>
          <label style="display: block; margin: .8em 0 .2em">Avatar:</label>
          <kendo-upload
            formControlName="myUpload"
            [saveUrl]="uploadSaveUrl"
            [removeUrl]="uploadRemoveUrl"
            [restrictions]="myRestrictions">
          </kendo-upload>
          <p style="color: red; font-size: .8em; margin-top: .5em;" [hidden]="myForm.controls.myUpload.valid || (myForm.controls.myUpload.pristine && !submitted)">Uploading an avatar is required.</p>
          <button type="submit" class="k-button k-primary" style="margin: 1em 0;">Submit</button>
        </div>
      </div>
    </div>
  </form>
  `
})
export class UploadComponent implements OnInit {
  uploadSaveUrl: string = "saveUrl";
  uploadRemoveUrl: string = "removeUrl";

  public userName: string;
  public userImages: Array<any>;
  public myForm: FormGroup;
  public submitted: boolean = false;
  public myRestrictions: FileRestrictions = {
    allowedExtensions: ["jpg", "jpeg", "png"]
  };

  constructor(private fb: FormBuilder) { }

  ngOnInit() {
    this.myForm = this.fb.group({
      uName: [this.userName, [Validators.required, Validators.minLength(4)]],
      myUpload: [this.userImages, [Validators.required]]
    })

    this.myForm.valueChanges.subscribe(data => this.onValueChanged(data));
  }

  onValueChanged(data?: any) {
    //handle model changes
  }

  save(value: any, valid: boolean) {
    this.submitted = true;

    if (valid) {  
      console.log("Everything is OK!");
    }
  }
}
import { Component, Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpProgressEvent, HttpEventType, HttpResponse } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/delay';
import 'rxjs/add/observable/of';
import 'rxjs/add/observable/concat';

@Component({
    selector: 'my-app',
    template: `<my-upload></my-upload>`
})
export class AppComponent {
}

@Injectable()
export class UploadInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (req.url === "saveUrl") {
      let events: Observable<HttpEvent<any>>[] = [0, 30, 60, 100].map((x) => Observable.of(<HttpProgressEvent>{
        type: HttpEventType.UploadProgress,
        loaded: x,
        total: 100
      }).delay(1000));

      const success = Observable.of(new HttpResponse({ status: 200 })).delay(1000);
      events.push(success);

      return Observable.concat(...events);
    }

    if (req.url === "removeUrl") {
        return Observable.of(new HttpResponse({ status: 200 }));
    }

    return next.handle(req);
  }
}
import { enableProdMode, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { UploadModule } from '@progress/kendo-angular-upload';
import { AppComponent }   from './app.component';
import { HttpClientModule } from '@angular/common/http';
import { UploadComponent }  from './upload.component';
import { ReactiveFormsModule } from '@angular/forms';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

@NgModule({
  imports:      [ BrowserModule, HttpClientModule, UploadModule, ReactiveFormsModule, BrowserAnimationsModule ],
  declarations: [ AppComponent, UploadComponent ],
  bootstrap:    [ AppComponent ]
})

export class AppModule { }

enableProdMode();

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule);
In this article