I am seeing a different behavior between Blazor UI 8 and 9.
Since upgrading to version 9 the GridToolBarTemplate is getting a k-toolbar-scrollable and the toolbar is getting wrapped in a div with k-toolbar-items k-toolbar-items-scroll classes. This is preventing my toolbar from rendering the way it did in version 8.
I added <GridToolBarSettings OverflowMode="GridToolBarOverflowMode.None" /> as he first element of the template but that had no effect.
How can I prevent the toolbar from getting this new div and classes?
Thanks,
Dave Shine
dshine@caseglide.com
i using Telerik upload for uloading multiple file and max upload file is 5 but time of working uplaod works well but when i remove uplaoded item it just remove from frontend but in my controller it has diffrent id and client side has diffrent id i got it when i debug the code tried multiple times but i got not clue i am giving my full razor component and controller in below
below is my models
public class FileMetadata
{
public string FileId { get; set; }
public long Size { get; set; }
public string FileName { get; set; }
public byte[] FileContent { get; set; }
public Guid? ProcessId { get; set; }
public Guid? StructureId { get; set; }
public Guid? BillingSiteId { get; set; }
}
public partial class Document
{
public Guid DocumentId { get; set; }
public Guid InvoiceId { get; set; }
public Guid? JobId { get; set; }
public int JobStep { get; set; }
private string _fileName;
public string FileName
{
get { return _fileName; }
set
{
_fileName = value;
this.DocumentFormat = GetDocumentFormatByFileExtension(value);
}
}
// Field is ignored in regard to DbContext load/save
public string FileData { get; set; }
public DateTime CreatedOn { get; set; }
public DocumentType DocumentType { get; set; }
public DocumentFormat DocumentFormat { get; set; }
public DocumentSource DocumentSource { get; set; }
public bool CanBeArchived { get; set; }
public List<Variable> Variables { get; set; }
[JsonIgnore]
public virtual Invoice Invoice { get; set; }
[JsonIgnore]
public virtual Job Job { get; set; }
private static DocumentFormat GetDocumentFormatByFileExtension(string fileName)
{
if (string.IsNullOrEmpty(fileName))
return DocumentFormat.Undefined;
try
{
string fileExtension = Path.GetExtension(fileName)?.ToLower();
return fileExtension switch
{
".pdf" => DocumentFormat.PDF,
".txt" => DocumentFormat.TXT,
".json" => DocumentFormat.JSON,
".xml" => DocumentFormat.XML,
".vars" => DocumentFormat.VARS,
_ => DocumentFormat.Undefined,
};
}
catch
{
return DocumentFormat.Undefined;
}
}
}
below is my razor component code
<style>
/* to show custom message for Bug 51695: [Manual upload] Invalid success text */
.k-file-validation-message::before {
content: "@(isUploadedSuccess ? Resources.FileUploadMsg : "")";
visibility: @(isUploadedSuccess ? "visible" : "hidden");
}
/* to hide the predefined message when file is uploaded */
.k-file-validation-message {
visibility: @(isUploadedSuccess ? "hidden" : "visible");
}
/* display error message for invalid file in red */
.k-file-validation-message.k-text-error {
color: red;
}
</style>
<div style="width: 400px;">
<!-- Drop Zone Section -->
<div class="dropzone-section">
<TelerikDropZone Id="dropzone-id"
DragOverClass="dropzone-over"
NoteText="@DropZoneHintText">
</TelerikDropZone>
@if (UseDropZoneOverStyles)
{
<style>
.dropzone-over .k-dropzone-inner {
border: 2px dashed;
}
</style>
}
</div>
<!-- Upload Section -->
<div class="upload-section divstyling">
<TelerikUpload DropZoneId="dropzone-id" @ref="@UploadRef" Id="uploadFile"
SaveUrl="@UploadSaveUrl"
MaxFileSize="@(16 * 1024 * 1024)"
Class="@UploadClass"
OnSuccess="@OnUploadSuccess"
OnRemove="@OnUploadRemove"
OnError="@OnUploadError"
Multiple="true"
AllowedExtensions="@AllowedFileExtensions"
Accept=".pdf,.xml"
OnSelect="@OnSelectHandler" />
</div>
<!-- Notification Section OnSelect="@OnSelectHandler"-->
<div class="notification-section">
<TelerikNotification @ref="@NotificationRef" Class="MyTelerikNotification" HorizontalPosition="NotificationHorizontalPosition.Center" />
</div>
<!-- Upload Button -->
<div class="button-section d-md-flex justify-content-md-end">
<button id="btnUpload"
type="button"
class="btn btn-sm btnAction btn-action-filled-blue mr-1 mt10"
@onclick="@Upload"
disabled="@(isUploadInProgress || !selectedFiles.Any())">
@if (isUploadInProgress)
{
<span class="spinner-border spinner-border-sm mr-1"></span>
}
@(isUploadInProgress ? Resources.Uploading : Resources.AddAttachment)
</button>
</div>
</div>
<style>
/* Drop Zone */
.dropzone-section {
width: 100%;
max-width: 600px;
text-align: center;
margin-bottom: 20px;
}
/* Upload Section */
.upload-section {
width: 100%;
max-width: 600px;
margin-bottom: 20px;
}
/* Notification Section */
.notification-section {
width: 100%;
max-width: 600px;
margin-bottom: 20px;
}
/* Buttons */
#btnUpload {
border: 2px solid;
border-radius: 20px;
opacity: 1;
margin-right: 0px;
font-weight: bold;
/*font-size: 0.85rem !important;*/
padding-left: 20px !important;
padding-right: 20px !important;
max-width: fit-content;
}
#btnUpload:focus {
outline: none !important;
box-shadow: none !important;
}
/* Other Styles */
.dropzone-over .k-dropzone-inner {
border: 2px dashed;
}
.no-dropzone .k-dropzone-hint {
display: none;
}
.divstyling {
padding-bottom: 10px;
}
/* Error Notification caption */
/* .MyTelerikNotification .k-notification-container .k-notification {
width: 300px;
height: 50px;
font-size: 1.5em;
text-align: center;
align-items: center;
}
.divstyling > .k-upload .k-upload-files{
max-height : 250px;
}*/
</style>
and here is code behind code
using Blazored.Modal;
using Blazored.Modal.Services;
using CmpInvoicePlatform.Client.Services.Dialog;
using CmpInvoicePlatform.Client.Services.Request;
using CmpInvoicePlatform.Shared.Models;
using CmpInvoicePlatform.Shared.Resources;
using Microsoft.AspNetCore.Components;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Telerik.Blazor;
using Telerik.Blazor.Components;
using Telerik.Blazor.Components.Notification;
namespace CmpInvoicePlatform.Client.Pages.Invoices
{
public partial class MutlipleAttachmentAdd : ComponentBase
{
[CascadingParameter]
BlazoredModalInstance ModalInstance { get; set; }
[Inject]
private IRequestService RequestSvc { get; set; }
[Inject]
private IDialogService DialogSvc { get; set; }
[Inject]
private NavigationManager NavigationManager { get; set; }
[Parameter]
public InvoiceModelViewModel InvoiceMVM { get; set; }
private string DropZoneHintText => UploadVisible ? Resources.ManualUploadDrop : string.Empty;
private bool UseDropZoneOverStyles { get; set; } = true;
private bool UploadVisible { get; set; } = true;
private string UploadClass => $"no-dropzone {(!UploadVisible ? "k-hidden" : string.Empty)}";
private string UploadSaveUrl => ToAbsoluteUrl("api/MultipleFileUpload/save");
private HttpClient _httpClient;
public List<string> AllowedFileExtensions = new List<string> { ".pdf", ".xml" };
//mainly used to check the file uploaded is successful or not so according to it disabled the upload button
private bool isUploadedSuccess { get; set; }
private bool isUploadInProgress { get; set; }
private TelerikUpload UploadRef { get; set; }
private List<UploadFileInfo> selectedFiles = new();
private List<FileMetadata> fileMetadataList = new();
private static int MaxAttachmentFile = 5;
private static string MaxFileErrorMsg = string.Format(Resources.MaxUploadedFileErrorMsg, MaxAttachmentFile);
private string ToAbsoluteUrl(string url)
{
return $"{NavigationManager.BaseUri}{url}";
}
private TelerikNotification NotificationRef { get; set; }
private void OnUploadSuccess(UploadSuccessEventArgs args)
{
isUploadedSuccess = (args.Operation == UploadOperationType.Upload) ? true : false;
}
private void OnUploadError(UploadErrorEventArgs e) => isUploadedSuccess = false;
// Check if the extensions of all selected files are present in the allowed extensions list.
private async Task OnSelectHandler(UploadSelectEventArgs e)
{
var currentFileUploadedCount = selectedFiles.Count + e.Files.Count();
// Prevent selecting more than 5 files total
if (currentFileUploadedCount > MaxAttachmentFile)
{
e.IsCancelled = true;
await DialogSvc.AlertAsync(Resources.MaxFileUploadedTitle, MaxFileErrorMsg);
return;
}
selectedFiles.AddRange(e.Files);
isUploadedSuccess = e.Files.All(file =>
AllowedFileExtensions.Contains(file.Extension) &&
!(file.InvalidMinFileSize || file.InvalidMaxFileSize || file.InvalidExtension)
);
}
private async Task Upload()
{
try
{
isUploadInProgress = true;
var documentIds = new List<Guid>();
// Get all files by using UploadController
_httpClient = new HttpClient();
using var response = await _httpClient.GetAsync(new Uri($"{NavigationManager.BaseUri}api/MultipleFileUpload/GetAllFiles"));
if (response.IsSuccessStatusCode)
{
var uploadedFiles = await response.Content.ReadFromJsonAsync<List<Document>>();
// Process the files list as needed
foreach (var file in uploadedFiles)
{
var newDocument = new Document
{
DocumentId = Guid.NewGuid(),
InvoiceId = InvoiceMVM.InvoiceId,
DocumentSource = DocumentSource.External,
DocumentType = DocumentType.Support,
FileName = file.FileName,
FileData = file.FileData,
};
await RequestSvc.InvoiceAttachmentAddAsync(newDocument);
documentIds.Add(newDocument.DocumentId);
}
await DialogSvc.AlertAsync(Resources.AddAttachment, Resources.MultipleAttachmentUploadSuccessMsg);
UploadRef.ClearFiles();
selectedFiles.Clear();
isUploadedSuccess = false;
//Return the list of uploaded document IDs to the calling component
await ModalInstance.CloseAsync(ModalResult.Ok(documentIds));
}
await _httpClient.GetAsync(ToAbsoluteUrl("api/MultipleFileUpload/CleanFiles"));
}
catch (Exception ex)
{
await DialogSvc.AlertAsync(Resources.UploadInvoice, ex.Message);
}
finally
{
isUploadInProgress = false;
}
}
private async void OnUploadRemove(UploadEventArgs args)
{
_httpClient = new HttpClient();
foreach (var file in args.Files)
{
selectedFiles.RemoveAll(f => f.Id == file.Id);
await _httpClient.PostAsync(
ToAbsoluteUrl("api/MultipleFileUpload/remove"),
new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("fileId", file.Id)
}));
}
if (!selectedFiles.Any())
{
UploadRef.ClearFiles();
await _httpClient.GetAsync(ToAbsoluteUrl("api/MultipleFileUpload/CleanFiles"));
}
}
}
}
please look at the screenshots and provide appropriate solution as soon as possible[High Priority]
Thanks in Advance
I’m using the Telerik UI for Blazor <TelerikGrid> in a Razor Page. I’ve bound the grid to my view‑model like this:
<TelerikGrid @ref="SearchGrid"
TItem="ChargeUIResult"
Class="cgt-tables__table border-radius-top-zero cgt-charge-preview-grid"
Width="100%"
Pageable="true"
Sortable="false"
ConfirmDelete="true"
Resizable="true"
Groupable="false"
Navigable="false"
Reorderable="true"
EnableLoaderContainer="false"
FilterMode="GridFilterMode.None"
EditMode="GridEditMode.Popup"
SelectionMode="GridSelectionMode.Multiple"
ShowColumnMenu="true"
OnRead="@ReadItems"
SelectedItems="@SearchState.SelectedItems"
@bind-Page="@SearchState.CurrentPage"
@bind-PageSize="@SearchState.PageSize">
</TelerikGrid>
Problem:
User filters a grid but there is no "selected" row/item when filter returns results to the grid.
I'd like to set the selected item for a grid that supports:
SelectionMode="GridSelectionMode.Single" SelectedItems="@_selectedBookings"
I'm not sure what event I need to respond to, there doesn't appear to be a "Filter" button click event so I'm guessing I need to work with the Grid events like, OnUpdate or OnStateChanged?
Idea is to force first row to be selected from the Filter return set (which could be 0, 1, or many):
private void OnBookingGridUpdate(GridCommandEventArgs args)
{
if (_bookingList.Any())
{
var updatedItem = (BookingModel)args.Item;
_selectedBookings.Clear();
_selectedBookings.Add(updatedItem);
}
}
Thoughts?
I'm using the Blazor TelerikGrid component with SelectionMode="GridSelectionMode.Multiple".
I have an OnRowClick handler to manually toggle selection (see below), and I bind the selected items via SelectedItems="@SearchState.SelectedItems".
<TelerikGrid @ref="SearchGrid"
TItem="@ChargeUIResult"
SelectionMode="GridSelectionMode.Multiple"
SelectedItems="@SearchState.SelectedItems"
SelectedItemsChanged="@((IEnumerable<ChargeUIResult> args) => SetSelectedItem(args))"
OnRowClick="@OnRowClickHandler"
...>
</TelerikGrid>
void OnRowClickHandler(GridRowClickEventArgs args)
{
var currItem = args.Item as ChargeUIResult;
if (SearchState.SelectedItems.Any(x => x.Id == currItem?.Id))
{
SearchState.SelectedItems = SearchState.SelectedItems.Where(x => x.Id != currItem?.Id);
}
else
{
SearchState.SelectedItems = SearchState.SelectedItems.Concat(new[] { currItem });
}
SelectedItem = currItem;
ShouldRenderSelectedItem = true;
args.ShouldRender = false;
}
As of right now, the TelerikMenu generates a menu where each menu item is a span with an onclick handler that navigates to the page. It looks like this:
<li data-id="..." tabindex="0" class="k-item k-menu-item k-first" role="menuitem" aria-live="polite">
<span class="k-link k-menu-link ">
<span class="k-menu-link-text">
Page Title
</span>
</span>
</li>
However, because they are only spans, when right clicking on a menu item, there is no option to open the link in a new tab. In addition, middle clicking the menu item doesn't work either. Can these be changed to anchor tags so menu items can be opened in a new tab? I know there is an ItemContext that can be added to the TelerikMenu, but I would like to keep all the styling of the default TelerikMenu.
Can you tell me how to force the Grid Layout to allow space for my TelerikAnimationContainer? It gets chopped off when the 3rd row is "short". I don't want the scroll bar to accommodate the height. I want to see the entire filter.
Fully opened (When data extends the Grid):
Short Closed:
Short Open
<TelerikGridLayout Class="grid-layout">
<GridLayoutRows>
<GridLayoutRow Height="28px" />
<GridLayoutRow />
<GridLayoutRow />
</GridLayoutRows>
<GridLayoutItems>
<GridLayoutItem Row="1">
@if (Groups?.Count > 0)
{
<TelerikButton OnClick="@OnCreate"
Class="gsi-width-100pct gsi-padding-0">
Create New
</TelerikButton>
}
</GridLayoutItem>
<GridLayoutItem Row="2">
<div>
<div class="gsi-background-color-light" style="height: 41px; display:flex;justify-content:space-between;">
<div class="align-self-center gsi-font-kendo gsi-margin-0">
Patient Filters
</div>
<TelerikButton FillMode="Clear"
Class="gsi-border-width-0 gsi-border-color-white gsi-padding-8"
Icon="@(Telerik.SvgIcons.SvgIcon.Filter)"
OnClick="@GridFilterExpandCollapse" />
</div>
<TelerikAnimationContainer @ref="@FilterContainer"
Class="gsi-background-color-light gsi-margin-5 k-rounded-0"
Width="100%"
Height="100vm">
<TelerikStackLayout Spacing="1px" Class="gsi-margin-5">
<TelerikCard Width="33vh">
<CardBody>
@if (SessionOption1Items?.Count > 0)
{
<div class="form-group-short gsi-max-width-250">
<label class="col-form-label">@SessionOption1Template.Name</label><br />
<TelerikDropDownList Data="@SessionOption1Items"
@bind-Value="@SessionOptionIndex1"
TextField="Name" ValueField="Id" />
</div>
@if (SessionOption2Items?.Count > 0)
{
<div class="form-group-short gsi-max-width-250">
<label class="col-form-label">@SessionOption2Template.Name</label><br />
<TelerikDropDownList Data="@SessionOption2Items"
@bind-Value="@SessionOptionIndex2"
TextField="Name" ValueField="Id" />
</div>
}
}
else
{
<small>No Defined Filter</small>
}
</CardBody>
</TelerikCard>
<TelerikCard Width="33vh">
<CardBody>
<div class="form-group-short gsi-max-width-250">
<label class="col-form-label">Date Range</label><br />
<TelerikDropDownList Data="@DateRangeOptions"
@bind-Value="@DateRangeIndex"
TextField="Name" ValueField="Id" />
</div>
<div class="form-group-short gsi-max-width-250">
<label class="col-form-label">Group Behavior</label><br />
<TelerikDropDownList Data="@GroupFilterOptions"
@bind-Value="@GroupFilterIndex"
TextField="Name" ValueField="Id" />
</div>
</CardBody>
</TelerikCard>
<TelerikCard Width="34vh">
<CardBody>
<div class="form-group-short gsi-max-width-250">
<label class="col-form-label">Status</label><br />
<TelerikDropDownList Data="@IsActiveFilterOptions"
@bind-Value="@IsActiveIndex"
TextField="Name" ValueField="Id" />
</div>
<div class="form-group-short align-bottom">
<label class="col-form-label gsi-color-white">Apply Filter</label><br />
<TelerikButton OnClick="OnFilterChanged"
Class="gsi-background-color gsi-color-white gsi-width-100pct">
Apply Filter
</TelerikButton>
</div>
</CardBody>
</TelerikCard>
</TelerikStackLayout>
</TelerikAnimationContainer>
</div>
</GridLayoutItem>
<GridLayoutItem Row="3">
<TelerikGrid Data=@Sessions
...
I need to lock down the spreadsheet and prevent the user from adding or removing columns. I'd like to hide the highlighted items in the context menu below. How can I accomplish this?