I'm trying to use Kendo Angular Upload but when I check the data being sent to the server in Google Chrome DevTools, the property rawFile, which I beleive is the one responsible to actually retrieve the file data, is always empty as the attachment indicates.
Here's my HTML:
<form class='content' novalidate [formGroup]="edicaoForm"> <div class="k-i-loading" *ngIf="loading"></div> <div class="row"></div> <div class="clear-fix mt-4"></div> <div class="row"> <div class="col-sm-12"> <div class="col-sm-4 pull-left"> <label [for]="logomarca">Logo</label> <kendo-uploaddropzone zoneId="myZone">Somente arquivos do tipo JPG, JPEG, PNG e SVG são permitidos.</kendo-uploaddropzone> <kendo-upload zoneId="myZone" [saveField]="logomarca" [saveUrl]="uploadLogoURL" [chunkable]="false" [restrictions]="restrictions" #logomarca [multiple]="false" [autoUpload]="true" formControlName="logomarca" ngDefaultControl> <kendo-upload-messages select="Selecionar arquivo" uploadSelectedFiles="Enviar arquivo" clearSelectedFiles="Cancelar seleção de arquivo" dropFilesHere="Solte arquivos aqui para carregar" invalidFileExtension="Tipo de arquivo não permitido." remove="Remover" cancel="Cancelar" fileStatusUploaded="Arquivo carregado com sucesso." externalDropFilesHere="Arraste e solte arquivos aqui para carregar" resume="Concluir" pause="Pausar" headerStatusUploaded="Concluído" headerStatusUploading="Carregando..." headerStatusPaused="Pausado" fileStatusFailed="Falha ao carregar arquivo."></kendo-upload-messages> </kendo-upload> </div> <div class="row"> <div class="col-sm-6" [ngClass]="{'has-error': displayMessages.empresaId }"> <label>Empresa</label> <div> <kendo-combobox [data]="empresasData" [allowCustom]="false" [placeholder]="'Empresa'" [textField]="'nomeFantasia'" [valueField]="'gid'" [filterable]="true" class="w-100" formControlName="empresaId" (filterChange)="empresaHandleFilter($event)" (open)="empresaHandleOpen()" required [suggest]="true" [valuePrimitive]="true" (blur)="blur('empresaId')"></kendo-combobox> <span class="text-danger" *ngIf="displayMessages.empresaId"> <p [innerHTML]="displayMessages.empresaId"></p> </span> </div> </div> <div class="col-sm-6" [ngClass]="{'has-error': displayMessages.codigo }"> <label>Código</label> <div> <input kendoTextBox [placeholder]="'Código'" maxlength="30" class="w-100" formControlName="codigo" /> <span class="text-danger" *ngIf="displayMessages.codigo"> <p [innerHTML]="displayMessages.codigo"></p> </span> </div> </div> </div> <div class="clear-fix mt-4"></div> <div class="row"> <div class="col-sm-6" [ngClass]="{'has-error': displayMessages.descricao }"> <label>Descrição</label> <div> <input kendoTextBox [placeholder]="'Descrição'" class="w-100" formControlName="descricao" /> <span class="text-danger" *ngIf="displayMessages.descricao"> <p [innerHTML]="displayMessages.descricao"></p> </span> </div> </div> <div class="col-sm-6" [ngClass]="{'has-error': displayMessages.nomeFantasia }"> <label>Nome Fantasia</label> <div> <input kendoTextBox [placeholder]="'Nome Fantasia'" class="w-100" formControlName="nomeFantasia" /> <span class="text-danger" *ngIf="displayMessages.nomeFantasia"> <p [innerHTML]="displayMessages.nomeFantasia"></p> </span> </div> </div> </div> <div class="clear-fix mt-4"></div> <div class="row"> <div class="col-sm-6 pull-left" [ngClass]="{'has-error': displayMessages.tipoIdentificacao }"> <label>Tipo de identificação</label> <kendo-combobox [data]="tiposDeIdentificacao" [allowCustom]="false" [placeholder]="'Tipo de Identificação'" [textField]="'descricao'" [valueField]="'valor'" [filterable]="true" class="w-100" [valuePrimitive]="true" formControlName="tipoIdentificacao" (blur)="blur('tipoIdentificacao')"></kendo-combobox> <span class="text-danger" *ngIf="displayMessages.tipoIdentificacao"> <p [innerHTML]="displayMessages.tipoIdentificacao"></p> </span> </div> <div class="col-sm-6 pull-left" [ngClass]="{'has-error': displayMessages.numeroDocumento }"> <label>Número Documento</label> <div> <input kendoTextBox [placeholder]="'Número Documento'" maxlength="18" class="w-100" (keyup)="maskInputCpfCnpj()" formControlName="numeroDocumento" /> <span class="text-danger" *ngIf="displayMessages.numeroDocumento"> <p [innerHTML]="displayMessages.numeroDocumento"></p> </span> </div> </div> </div> </div> </div> <div class="clear-fix mt-4"></div> <div class="row"> <div class="col-sm-12"> <div class="col-sm-4 pull-left" [ngClass]="{'has-error': displayMessages.inscricaoMunicipal }"> <label>Inscrição Municipal</label> <div> <input kendoTextBox [placeholder]="'Inscrição Municipal'" maxlength="20" class="w-100" formControlName="inscricaoMunicipal" /> <span class="text-danger" *ngIf="displayMessages.inscricaoMunicipal"> <p [innerHTML]="displayMessages.inscricaoMunicipal"></p> </span> </div> </div> <div class="col-sm-4 pull-left" [ngClass]="{'has-error': displayMessages.inscricaoEstadual }"> <label>Inscrição Estadual</label> <div> <input kendoTextBox [placeholder]="'Inscrição Estadual'" maxlength="20" class="w-100" formControlName="inscricaoEstadual" /> <span class="text-danger" *ngIf="displayMessages.inscricaoEstadual"> <p [innerHTML]="displayMessages.inscricaoEstadual"></p> </span> </div> </div> <div class="col-sm-4 pull-left" [ngClass]="{'has-error': displayMessages.cnaeId }"> <label>CNAE</label> <div> <kendo-combobox [data]="cnaesData" [allowCustom]="false" [placeholder]="'CNAE'" [textField]="'descricao'" [valueField]="'gid'" [filterable]="true" (filterChange)="cnaeHandleFilter($event)" (open)="cnaeHandleOpen()" [suggest]="true" class="w-100" formControlName="cnaeId" [valuePrimitive]="true" (blur)="blur('cnaeId')"></kendo-combobox> <span class="text-danger" *ngIf="displayMessages.cnaeId"> <p [innerHTML]="displayMessages.cnaeId"></p> </span> </div> </div> </div> </div> <div class="clear-fix mt-4"></div> <div class="row"> <div class="col-sm-12"> <div class="col-sm-4 pull-left" [ngClass]="{'has-error': displayMessages.email }"> <label>E-mail</label> <div> <input kendoTextBox [placeholder]="'E-mail'" class="w-100" formControlName="email" /> <span class="text-danger" *ngIf="displayMessages.email"> <p [innerHTML]="displayMessages.email"></p> </span> </div> </div> <div class="col-sm-4 pull-left" [ngClass]="{'has-error': displayMessages.site }"> <label>Site</label> <div> <input kendoTextBox [placeholder]="'Site'" class="w-100" formControlName="site" /> <span class="text-danger" *ngIf="displayMessages.site"> <p [innerHTML]="displayMessages.site"></p> </span> </div> </div> <div class="col-sm-4 pull-left" [ngClass]="{'has-error': displayMessages.dataRegistro }"> <label>Data Registro</label> <div> <kendo-datepicker [(value)]="dataRegistro" [placeholder]="'Data Registro'" [format]="'dd/MM/yyyy'" [navigation]="false" [weekNumber]="true" class="w-100" formControlName="dataRegistro"> </kendo-datepicker> <span class="text-danger" *ngIf="displayMessages.dataRegistro"> <p [innerHTML]="displayMessages.dataRegistro"></p> </span> </div> </div> </div> </div> <div class="clear-fix mt-4"></div> <div class="row"> <div class="col-sm-12"> <div class="col-sm-4 pull-left"> <div class="col-sm-6 pull-left" style="padding-left: 2px;" [ngClass]="{'has-error': displayMessages.bloqueada }"> <input type="checkbox" id="bloqueada" class="k-checkbox" formControlName="bloqueada" [checked]="false"> <label class="k-checkbox-label" for="bloqueada">Bloqueada</label> </div> <div class="col-sm-6 pull-left" [ngClass]="{'has-error': displayMessages.matriz }"> <input type="checkbox" id="matriz" class="k-checkbox" formControlName="matriz" [checked]="false"> <label class="k-checkbox-label" for="matriz">Matriz</label> </div> </div> </div> </div> <div class="clear-fix mt-4"></div> <div class="row"> <div class="col-sm-12"> <div class="col-sm-12"> <label [for]="observacao">Observação</label> <kendo-textbox-container class="w-100" style="padding-top: 4px;"> <textarea kendoTextArea formControlName="observacao" #observacao></textarea> </kendo-textbox-container> <span class="text-danger" *ngIf="displayMessages.observacao"> <p [innerHTML]="displayMessages.observacao"></p> </span> </div> </div> </div> <div class="clear-fix mt-4"></div> <div class="col-sm-12 mt-2"> <button kendoButton [icon]="'save'" class="pull-left btn-primary btn-sm" (click)="atualizar()" [disabled]='!edicaoForm.valid'>Salvar</button> <button kendoButton [icon]="'delete'" class="pull-right btn-danger btn-sm ml-1" (click)="excluir()">Excluir</button> <button kendoButton [icon]="'close'" class="pull-right btn-secondary btn-sm" (click)="sendFormStatus()">Fechar</button> </div></form><app-alert (alertStatus)="alertEvent($event)" [openedAlert]="openedAlert" [title]="title" [message]="message"></app-alert>Here's my angular component:
import { Component, OnChanges, AfterViewInit, Input, Output, EventEmitter, ElementRef, ViewChildren } from '@angular/core';import { FormGroup, FormControlName, FormBuilder, Validators } from '@angular/forms';import { FormValidator } from '../../../utils/form-validator';import { NotificationService } from '@progress/kendo-angular-notification';import { IntlService } from '@progress/kendo-angular-intl';import { EstabelecimentosService } from '../../services/estabelecimentos.service';import { Estabelecimento } from '../../models/estabelecimento';import { Observable, forkJoin } from 'rxjs';import 'rxjs/add/observable/fromEvent';import 'rxjs/add/observable/merge';import { Cnae } from '../../../cnae/models/cnae';import { CnaeService } from '../../../cnae/services/cnae.service';import { Empresa } from '../../../empresas/models/empresa';import { EmpresasService } from '../../../empresas/services/empresas.service';import { Utils } from '../../../utils/utils';import { FileRestrictions } from '@progress/kendo-angular-upload';import { environment } from '../../../../environments/environment';@Component({ selector: 'app-edit-estabelecimento', templateUrl: './edit-estabelecimento.component.html', styleUrls: ['../index/index-estabelecimento.component.css', './edit-estabelecimento.component.css']})export class EditEstabelecimentoComponent implements AfterViewInit, OnChanges { @Input() habilitarView: boolean; @Input() estabelecimentoId: string; @Output() formStatus = new EventEmitter<boolean>(); @Output() editedItem = new EventEmitter<Estabelecimento>(); public message: string = ''; public title: string = ''; public openedAlert: boolean = false; public loading: boolean = false; private estabelecimentoDescricao: string; public estabelecimento: Estabelecimento; public cnaesData: Cnae[] = []; public cnaesSource: Cnae[] = []; public empresasData: Empresa[] = []; public empresasSource: Empresa[] = []; edicaoForm: FormGroup; formValidator: FormValidator; validationMessages: { [key: string]: { [key: string]: string } }; displayMessages: { [key: string]: string } = {}; dataRegistro: any = null; @ViewChildren(FormControlName, { read: ElementRef }) formInputElements: ElementRef[]; public tiposDeIdentificacao: Array<{ descricao: string, valor: number }> = [{ descricao: 'Pessoa Jurídica', valor: 1 }, { descricao: 'Pessoa Física', valor: 2 }]; uploadLogoURL: string = `${environment.url}imagens/estabelecimento/${this.estabelecimentoId}/logo`; public restrictions: FileRestrictions = { allowedExtensions: ['jpg', 'jpeg', 'png', 'svg'], maxFileSize: 5242880 }; constructor(private readonly fb: FormBuilder, private readonly utils: Utils, private readonly empresasService: EmpresasService, private readonly cnaeServices: CnaeService, private readonly estabelecimentosService: EstabelecimentosService, private readonly intl: IntlService, private readonly notificationService: NotificationService) { } ngAfterViewInit(): void { let controlBlurs: Observable<any>[] = this.formInputElements .map((formControl: ElementRef) => Observable.fromEvent(formControl.nativeElement, 'blur')); Observable.merge(...controlBlurs).subscribe(() => { this.displayMessages = this.formValidator.processMessages(this.edicaoForm); }); } ngOnChanges(): void { this.loading = true; this.validationMessages = { codigo: { required: 'Informe o código' }, descricao: { required: 'Informe a descrição' }, tipoIdentificacao: { required: 'Informe o tipo de identificação' }, nomeFantasia: { required: 'Informe o nome fantasia ' }, numeroDocumento: { required: 'Informe o número do documento' }, inscricaoEstadual: { required: 'Informe o número de inscrição estadual' }, inscricaoMunicipal: { required: 'Informe o número de inscrição municipal' }, email: { required: 'Informe o email' }, site: { required: 'Informe o site' }, dataRegistro: { required: 'Informe a data do registro' }, observacao: { required: 'Preencha a observação' }, empresaId: { required: 'Informe a Empresa' }, cnaeId: { required: '' } }; this.edicaoForm = this.fb.group({ codigo: ['', [Validators.required]], descricao: ['', [Validators.required]], tipoIdentificacao: [0, [Validators.required]], nomeFantasia: ['', [Validators.required]], numeroDocumento: ['', [Validators.required]], inscricaoEstadual: ['', []], inscricaoMunicipal: ['', []], email: ['', []], site: ['', []], bloqueada: ['', []], dataRegistro: ['', []], observacao: ['', []], matriz: ['', []], empresaId: ['', [Validators.required]], cnaeId: ['', []], logomarca: ['', []] }); this.formValidator = new FormValidator(this.validationMessages); forkJoin(this.estabelecimentosService.getEstabelencimento(this.estabelecimentoId), this.empresasService.getAll(), this.cnaeServices.getAll()).subscribe(response => { this.estabelecimento = new Estabelecimento(); this.estabelecimento.gid = this.estabelecimentoId; response[0]['data'].numeroDocumento = this.utils.convertToCpfCnpj(response[0]['data'].numeroDocumento); this.preencherForm(response[0]['data']); this.empresasSource = response[1]['data']; this.formValidator.preencherCombo(this.edicaoForm, 'empresaId', this.empresasData = response[1]['data']); this.cnaesSource = response[2]['data']; this.formValidator.preencherCombo(this.edicaoForm, 'cnaeId', this.cnaesData = response[2]['data']); }); } preencherForm(estabelecimento: any): void { this.estabelecimentoDescricao = estabelecimento.descricao; if (estabelecimento.cnae == [] || estabelecimento.cnae == undefined || estabelecimento.cnae == null) { estabelecimento.cnae = Object.assign({}); } if (!estabelecimento.logomarca) { estabelecimento.logomarca = Object.assign({}); } this.edicaoForm.patchValue({ codigo: estabelecimento.codigo, descricao: estabelecimento.descricao, tipoIdentificacao: estabelecimento.tipoIdentificacao, nomeFantasia: estabelecimento.nomeFantasia, numeroDocumento: estabelecimento.numeroDocumento, inscricaoEstadual: estabelecimento.inscricaoEstadual, inscricaoMunicipal: estabelecimento.inscricaoMunicipal, email: estabelecimento.email, site: estabelecimento.site, dataRegistro: this.intl.parseDate(estabelecimento.dataRegistro), bloqueada: estabelecimento.bloqueada, matriz: estabelecimento.matriz, observacao: estabelecimento.observacao, empresaId: estabelecimento.empresa.gid, cnaeId: estabelecimento.cnae.gid, logomarca: estabelecimento.logomarca }); this.loading = false; } sendFormStatus() { this.habilitarView = false; this.formStatus.emit(this.habilitarView); } atualizar() { this.loading = true; if (this.edicaoForm.dirty && this.edicaoForm.valid) { const estabelecimento = Object.assign({}, this.estabelecimento, this.edicaoForm.value); if (estabelecimento.cnaeId != [] && estabelecimento.cnaeId != undefined && estabelecimento.cnaeId != null) { estabelecimento.cnae = new Cnae(); estabelecimento.cnae.gid = estabelecimento.cnaeId; } else { estabelecimento.cnae = null; } estabelecimento.empresa = new Empresa(); estabelecimento.empresa.gid = estabelecimento.empresaId; estabelecimento.numeroDocumento = this.utils.removeCaracter(estabelecimento.numeroDocumento); this.estabelecimentosService.atualizar(estabelecimento).subscribe(success => { this.onSuccess(success, 'Atualizado'); }, error => { this.onError(error); }); } } excluir() { this.title = 'Atenção'; this.message = `Você deseja realmente excluir o estabelecimento "${this.estabelecimentoDescricao}"?`; this.openedAlert = true; this.loading = true; } alertEvent($event: boolean) { this.openedAlert = false; $event == false ? this.loading = false : true; if ($event == true) { this.estabelecimentosService.excluir(this.estabelecimentoId).subscribe(success => { this.onSuccess(success, 'Excluído'); this.habilitarView = false; this.formStatus.emit(this.habilitarView); }, error => { this.onError(error); }); } } onSuccess(success: any, acao: string): any { this.notificationService.show({ content: `${acao} com sucesso!`, animation: { type: 'slide', duration: 800 }, cssClass: 'button-notification', position: { horizontal: 'center', vertical: 'bottom' }, type: { style: 'success', icon: true }, hideAfter: 1000 }); this.editedItem.emit(success); this.loading = false; } onError(error: any): any { this.notificationService.show({ content: `Ocorreu um erro: ${error.message}.`, animation: { type: 'slide', duration: 800 }, cssClass: 'button-notification', position: { horizontal: 'center', vertical: 'bottom' }, type: { style: 'error', icon: true }, closable: true }); this.loading = false; } maskInputCpfCnpj() { let estabelecimento = Object.assign({}, this.estabelecimento, this.edicaoForm.value); this.edicaoForm.patchValue({ numeroDocumento: estabelecimento.numeroDocumento = this.utils.convertToCpfCnpj(estabelecimento.numeroDocumento) }); } blur(item: string) { if (this.edicaoForm.controls[item].value === '' || this.edicaoForm.controls[item].value === undefined || this.edicaoForm.controls[item].value === null) { this.displayMessages[item] = this.validationMessages[item].required } else { delete this.displayMessages[item]; } } empresaHandleOpen() { this.empresasData = JSON.parse(JSON.stringify(this.empresasSource)); } empresaHandleFilter(value: string) { if (value) { this.empresasData = this.empresasSource.filter((s) => s.nomeFantasia.toLocaleLowerCase().includes(value.toLocaleLowerCase())); } } cnaeHandleOpen() { this.cnaesData = JSON.parse(JSON.stringify(this.cnaesSource)); } cnaeHandleFilter(value: string) { if (value) { this.cnaesData = this.cnaesSource.filter((s) => s.codigo.toLocaleLowerCase().includes(value.toLocaleLowerCase())); } }}