I am unclear how the kendo upload communicates with the server to get the progress indicator. In my application the progress indicator always goes from directly from 0% to complete regardless of file size. I have the S3Helper on the server logging status but I don't know how to make that status known to the client.
Upload Service
using Microsoft.AspNetCore.Cors;using Microsoft.AspNetCore.Identity;using Microsoft.AspNetCore.Mvc;using Microsoft.AspNetCore.Mvc.Rendering;using Microsoft.Extensions.Configuration;using Microsoft.Extensions.Logging;using Microsoft.Extensions.Options;using Newtonsoft.Json;using Newtonsoft.Json.Linq;using System.Threading;using System.Threading.Tasks;using ARLNService.Helpers;using ARLNService.Models;using ARLNService.Services;using System;using Microsoft.AspNetCore.Authentication;using Microsoft.AspNetCore.Authorization;using System.Collections.Generic;using Microsoft.AspNetCore.Http;using System.IO;using OfficeOpenXml;using System.Linq;using System.Data.SqlClient;namespace ARLNService.Controllers{ [EnableCors("MyPolicy")] [ApiController] [ApiVersionNeutral] [Route("api/[controller]/[action]")] public class UploadFilesController : Controller { private readonly IConfiguration _configuration; private readonly ARLNServiceContext _db; public UploadFilesController( IConfiguration configuration, ARLNServiceContext db) { _configuration = configuration; _db = db; } [HttpPost] public async Task<IActionResult> UploadFile(IList<IFormFile> files) { String bucket = _configuration["AWS:bucket"]; String accessKey = _configuration["AWS:AWS_ACCESS_KEY_ID"]; System.DateTime thisDay = System.DateTime.Now; // I'm getting file inside Request object var file = this.Request.Form.Files[0]; // create unique file name for prevent the mess var fileName = Guid.NewGuid() + file.FileName; string userName = this.Request.Form["userName"].ToString(); Upload upload = new Upload(); upload.fileName = fileName; upload.uploadDate = thisDay; upload.userName = userName; upload.originalFileName = file.FileName; _db.Set<Upload>().Add(upload); _db.SaveChanges(); var fileResponse = await S3Service.UploadObject(file, fileName, bucket, fileName, userName); Upload uploadUpdate = _db.Uploads.FirstOrDefault(c => c.fileName == fileName); if (fileResponse.success == true) { uploadUpdate.uploadStatus = "Uploaded"; _db.SaveChanges(); return Ok(); } else { uploadUpdate.uploadStatus = "Upload Failed"; _db.SaveChanges(); return BadRequest("Failed to upload file"); } } }}
Helper function for S3
using System;using System.IO;using System.Threading.Tasks;using Amazon.S3;using Amazon.S3.Model;using ARLNService.Models;using Microsoft.AspNetCore.Http;using System.Collections.Generic;using System.Security.Cryptography;using Microsoft.AspNetCore.Mvc;using Amazon.S3.Transfer;namespace ARLNService.Helpers{ public class S3Service { public async static Task<UploadFile> UploadObject(IFormFile file, String fileName, String bucket, String accessKey, String userName) { // connecting to the client var client = new AmazonS3Client(); // get the file and convert it to the byte[] byte[] fileBytes = new Byte[file.Length]; file.OpenReadStream().Read(fileBytes, 0, Int32.Parse(file.Length.ToString())); try { using (System.IO.MemoryStream filestream = new System.IO.MemoryStream(fileBytes)) { using (Amazon.S3.Transfer.TransferUtility tranUtility = new Amazon.S3.Transfer.TransferUtility(client)) { var request = new TransferUtilityUploadRequest { BucketName = bucket, Key = accessKey, InputStream = filestream }; request.Metadata.Add("userName", userName); request.UploadProgressEvent += new EventHandler<UploadProgressArgs> (uploadRequest_UploadPartProgressEvent); await tranUtility.UploadAsync(request); } } return new UploadFile { success = true, fileName = fileName }; } catch (Exception e) { return new UploadFile { success = false, fileName = fileName }; } } static void uploadRequest_UploadPartProgressEvent(object sender, UploadProgressArgs e) { // Process event. Console.WriteLine("{0}/{1}", e.TransferredBytes, e.TotalBytes); } }}
Angular Component
<div class="filters " (click)="activate()"> <div class="confirmMessage"> <p>Choose select file to upload a .csv file.</p> </div> <div class="dropdownSection"> <kendo-upload #myUpload="kendoUpload" [saveUrl]="uploadSaveUrl" (upload)="uploadEventHandler($event)" (success)="loadItems($event)" [removeUrl]="uploadRemoveUrl" [restrictions]="myRestrictions" [multiple]="false" [accept]="acceptString"> <kendo-upload-messages select="Select file..."> </kendo-upload-messages> </kendo-upload> <br /> </div></div><div class="clearfix"></div>
Angular code
import { Component, OnDestroy, OnInit, Output, EventEmitter, ChangeDetectorRef, Injector, ViewEncapsulation } from '@angular/core';import { FormControl } from "@angular/forms";import { Subscription } from 'rxjs/Subscription';import { IPageInfo, IMetadata, IEntry, IRootObject } from '../../models/eipMessage';import { DataService } from '../../shared/data.services';import { UtilService } from '../../shared/util.service';import { UtilityService } from '../../shared/utility.service';import { ErrorMessageService } from '../../shared/error-message.service';import { GlobalService } from '../../shared/global.service';import { MatDatepicker, MatDatepickerInput, MatDatepickerToggle } from '@angular/material';import * as _ from 'lodash';import { FileRestrictions, UploadEvent, FileState } from '@progress/kendo-angular-upload';import { environment } from '../../../environments/environment';import { Observable, of, concat } from 'rxjs';import { delay } from 'rxjs/operators';@Component({ selector: 'uploads-file-select', templateUrl: 'uploads-file-select.component.html', styleUrls: ['uploads-file-select.component.scss']})export class UploadsFileSelectComponent implements OnInit, OnDestroy { public acceptString = ".txt, .csv"; public uploadSaveUrl = environment.serviceUrl + "api/UploadFiles/UploadFile"; // should represent an actual API endpoint myRestrictions: FileRestrictions = { allowedExtensions: ['.csv', '.txt'] }; @Output() fileUploaded = new EventEmitter(); constructor(private utilityService: UtilityService, private dataService: DataService, private errMsgService: ErrorMessageService, private injector: Injector, private changeRef: ChangeDetectorRef, private utilService: UtilService, private globalService: GlobalService) { } uploadEventHandler(e: UploadEvent) { e.data = { userName: "tester@lab.com" }; } public remove(upload, uid: string) { console.log("remove" + uid); upload.removeFilesByUid(uid); } public loadItems(event) { console.log("load itemas"); this.fileUploaded.emit(); } ngOnInit() { } ngOnDestroy() { } activate() { };}
When I scroll a virtually scrolling grid then a pageEvent does not always fire. I often see this if I have a scrolled down grid and then quickly scroll to the top with a flick on the mouse (apple magic mouse).
Debugging this, it appears that the PageChangeEvent does not fire for the last change event. When scrolling to the top I often do not get an event that corresponds to the (skip: 0) position. This leads to a grid which is scrolled to the top but does not show any content because the slicing of the data shows record below the currently shown slice.
I have be able to replicate (with some difficulty) this behaviour in the remote data example here:
https://www.telerik.com/kendo-angular-ui/components/grid/scroll-modes/virtual/#toc-virtual-scrolling
Have you seen this behaviour and/or do you have fix/workaround for this behaviour?

I am using angular material to style buttons in my application. I am not clear on how to make the kendo upload button style adhere to the site defaults/or replace it with a custom button that does.
The following html. shows two buttons. See attached image, the bottom button appears in the desired format for our like our site defaults. Additionally, I am not clear on how to change the default text of the upload button.
<div class="filters " (click)="activate()"> <div class="dropdownSection"> <kendo-upload [saveUrl]="uploadSaveUrl" [removeUrl]="uploadRemoveUrl"> </kendo-upload> <br /> <button class="btn btn-primary btn-round simple" id="btnSelectFiles">Select Files</button> </div> </div> <div class="clearfix"></div>Hello,
I would like to have horizontal scroll if the content is bigger than a certain size, and otherwise the grid takes the 100% width. At the moment, if I set width for all columns the grid does not take the full width, and If I don't it won't have horizontal scroll.
So, I thought one way to reach this aim is to have a possibility to set min-width for columns, but it seems there is no such feature.
Thanks,
Mojtaba
Hi !
I have to locate Save-button for saving created new record in table in toolbar of the Grid.
<kendo-grid
..........
(edit)="editHandler($event)"
(cancel)="cancelHandler($event)"
(save)="saveHandler($event)"
(remove)="removeHandler($event)"
(add)="addHandler($event, myForm)"
..........
#grid
>
<ng-template kendoGridToolbarTemplate>
<button *ngIf="!isEdit && !isNew" kendoGridAddCommand type="button" look="bare" (click)="isNew = true">
<span class="fa fa-plus-circle"></span>{{ strings.add }}
</button>
....................................................
<button #btnSave class="btn-save" [disabled]="myForm.invalid || myForm.pristine" kendoGridSaveCommand [primary]="true" look="bare">
<span class="fa fa-check-circle"></span>{{ strings.save }}
</button>
....................................................
</ng-template>
But when I am adding new item in grid then Save-button isn't appearing (display: none property is set for that element).
I am trying to make Save-button visible/invisible inside my custom code. But in that case I am getting error inside save-command.directive.js (more precisely inside edit.service.js, string var formGroup = this.context(rowIndex).group; (this.context is undefined))
When I am trying to use custom button for saving created record I don't see the way how to get values of created record. May be you give me a piece of advice in what way in that case I can get created record ?
So, how can I solve that problem ?
Thanks a lot.
Hi,
I have seen some code in our project using formContol attribute. I couldn't find any documentation on it. For some reason this is causing the default value not set on the dropdown.
dropdownPlaceholder is something like this
this.dropdownPlaceholder = {
label : `Select ${label}` ,
value : null
};
Example:
<kendo-dropdownlist [data] = "list"
[textField] = "'label'"
[valueField] = "'value'"
[defaultItem] = "dropdownPlaceholder"
style="background-color: inherit"
[valuePrimitive] = "true"
(valueChange) = "onDropdownValueChange($event)"
[popupSettings] = "{popupClass: 'facets-input-dropdown-popup', width: 'auto'}"
[disabled] = "isDisabled"
[formControl]="control">
I expect the default value to be 'Select' in the dropdown, but not seeing that. Any documentation on formControl attribute for kendo-dropdownlist will be helpful.
Regards,
Jyothi
Is it possible to reuse an instance of kendo scheduler in an angularjs application? I have a scheduler with the following html.
<div kendo-scheduler="ctrl.scheduler" k-options="ctrl.schedulerOptions" k-rebind="ctrl.schedulerOptions"></div>
Now, a panel opens (for creating an event) with a button on the same screen, that displays the same scheduler with same events. I don't want to give it k-options again. I passed ctrl.scheduler to the panel and tried setting kendo-scheduler to an already created instance of scheduler, but it didn't work. Is there any other way? Thanks
<div kendo-scheduler="ctrl.scheduler"></div>
