Telerik Forums
UI for ASP.NET Core Forum
5 answers
1.1K+ views

I just finished a rather painful journey into putting together a demo to be able to use the Telerik Grid on a Razor page at all and then how to add checkboxes to it. Sounds easy, but it was not. Just try to find useful (or in some cases any) documentation on this stuff. 

Start with the https://github.com/telerik/ui-for-aspnet-core-examples solution and use the Kendo.Examples.RazorPages project. I added a Mange folder under pages and a "Lab" page under that (Lab.cshtml / Lab.cshtml.cs) - here is the code and my discussion follows:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Kendo.Mvc.Extensions;
using Kendo.Mvc.UI;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
 
namespace Kendo.Examples.RazorPages.Pages.Manage
{
    public class LabModel : PageModel
    {
        public static IList<ClientDto2> ClientsDtos;
 
        [TempData]
        public string TempMessage { get; set; }
        public bool ShowTempMessage => !string.IsNullOrWhiteSpace(TempMessage);
 
        public void OnGet()
        {
            Console.WriteLine("Manage OnGet");
            try
            {
                if (ClientsDtos != null) return;
 
                ClientsDtos = new List<ClientDto2>();
                //var json = await GetClientJson().ConfigureAwait(false);
                // substitute test data
                var json = "[{\"id\": 1,\"clientId\": \"client1\",\"clientName\": \"Client Credentials 1\",\"description\": \"Credentials 1\",\"userCodeType\": \"1\"}," +
                           "{\"id\": 2,\"clientId\": \"client2\",\"clientName\": \"Client Credentials 2\",\"description\": \"Credentials 2\",\"userCodeType\": \"2\"}]";
                var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
                var clientList = JsonSerializer.Deserialize<List<ClientDto2>>(json, options);
 
                foreach (var client in clientList)
                {
                    ClientsDtos.Add(new ClientDto2()
                    {
                        Id = client.Id,
                        ClientId = client.ClientId ?? "0",
                        ClientName = client.ClientName ?? "None",
                        Description = client.Description ?? "None",
                        UserCodeType = client.UserCodeType ?? "None",
                        Admin = client.Id % 2 == 1
                    });
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                TempMessage = ex.Message;
                if (ex.InnerException != null)
                    TempMessage += " : " + ex.InnerException.Message;
            }
        }
 
        public JsonResult OnPostRead([DataSourceRequest] DataSourceRequest request)
        {
            var res = new JsonResult(ClientsDtos.ToDataSourceResult(request));
            return res;
        }
 
        public JsonResult OnPostUpdate([DataSourceRequest] DataSourceRequest request, ClientDto2 client)
        {
            // the updatedClientData contains the updated data (only one record at a time in this example)
            var updatedClientData = ClientsDtos.Where(x => x.Id == client.Id).Select(x => client);
            // test changing data here
            client.UserCodeType = "99";
            TempMessage =
                $"Admin = {client.Admin}, Management = {client.Management}, Office = {client.Office} ";
            // use this data to update DB here and return the updated data
            return new JsonResult(new[] { client }.ToDataSourceResult(request, ModelState));
        }
    }
 
    public class ClientDto2
    {
        public int Id { get; set; }
        public string ClientId { get; set; }
        public string ClientName { get; set; }
        public string Description { get; set; }
        public string UserCodeType { get; set; }
        public bool Admin { get; set; }
        public bool Management { get; set; }
        public bool Office { get; set; }
    }
}

 

@page
@model Kendo.Examples.RazorPages.Pages.Manage.LabModel
@using Kendo.Mvc.UI
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
@Html.AntiForgeryToken()
 
@{
    ViewData["Title"] = "Lab";
}
 
<h1>Lab</h1>
<form method="post">
    @*FYI the following does not fire unless the page is reloaded
    it does not fire for a data update*@
    @if (!string.IsNullOrEmpty(Model.TempMessage))
    {
        var statusMessageClass = Model.TempMessage.StartsWith("Error") ? "danger" : "success";
        @if (Model.TempMessage != "")
        {
            <div class="alert alert-@statusMessageClass alert-dismissible" role="alert">
                <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
                @Model.TempMessage
            </div>
        }
    }
 
    @(Html.Kendo().Grid<ClientDto2>().Name("grid")
        .Columns(columns =>
        {
            columns.Bound(column => column.ClientId).Width(100).Title("Client");
            columns.Bound(column => column.ClientName);
            columns.Bound(column => column.Description);
            columns.Bound(column => column.UserCodeType);
            columns.Bound(column => column.Admin)
                .ClientTemplate(
                    "<input class='k-checkbox' data-val=#: Admin# id='Admin#: id#' name='Admin' " +
                    "type='checkbox' #= Admin ? checked='checked' : '' # onclick='return false;' value=#: Admin# >" +
                    "<label for='Admin#: id#' class='k-checkbox-label'></label>");
            columns.Bound(column => column.Management)
                .ClientTemplate(
                    "<input class='k-checkbox' data-val=#: Management# id='Management#: id#' name='Management' " +
                    "type='checkbox' #= Management ? checked='checked' : '' # onclick='return false;' value=#: Management# >" +
                    "<label for='Management#: id#' class='k-checkbox-label'></label>");
            columns.Bound(column => column.Office)
                .ClientTemplate(
                    "<input class='k-checkbox' data-val=#: Office# id='Office#: id#' name='Office' " +
                    "type='checkbox' #= Office ? checked='checked' : '' # onclick='return false;' value=#: Office# >" +
                    "<label for='Office#: id#' class='k-checkbox-label'></label>");
            columns.Command(column => { column.Edit(); });
        })
        .DataSource(ds => ds.Ajax()
            .Read(r => r.Url("/Manage/Lab?handler=Read").Data("forgeryToken"))
            .Update(u => u.Url("/Manage/Lab?handler=Update").Data("forgeryToken"))
            .Create(c => c.Url("/Manage/Lab?handler=Create").Data("forgeryToken"))
            .Destroy(d => d.Url("/Manage/Lab?handler=Destroy").Data("forgeryToken"))
            .Model(m => m.Id(id => id.Id))
            .PageSize(20)
        )
        .Scrollable()
        )
</form>
 
<script type="text/javascript">
    function forgeryToken() {
        return kendo.antiForgeryTokens();
    }
</script>

 

By far the biggest hurdle here was adding in the checkboxes. The default grid shows "true" and "false" until you go onto edit mode and then it shows an actual checkbox (BTW that comes from Shared/EditorTemplates/Boolean.cshtml). It sure would be nice if the grid default would be to show the checkboxes but since that is not the case I went in search of how to show them. At first I went down the rabbit hole at the https://demos.telerik.com/aspnet-core/grid/rowtemplate page - I could not get this to work. In my case it seems if you add ClientRowTemplate that wipes out any other column data and I could not get it to work like the display shows after many tries. Then I stumbled on the ClientTemplate (good luck finding any documentation on this one!) and after much trial and error I got a checkbox on the grid, but without a class and it was ugly and out of place so added the "k-checkbox" class and the checkbox disappeared. It turns out you need to add the label next to it or it disappears - WTF! Lastly I needed to make the checkbox read only since clicking it in browse mode would change it but that would not change the underlying data and so I found an HTML hack to add the onclick return false function which essentially makes it read only. - So holy crap this was a painful journey but I hope this post helps others. 

Tsvetomir
Telerik team
 answered on 13 Jan 2020
1 answer
189 views

I’ve a Razor Page project with Telerik ASP.NET Core Calender and a database in the back-end. In the Calender I can create new schedules that saves to the database and also read them to populate. For every schedule I would like to add what shift I should be related to so I’ve added a resource and if I create it as a new list it works fine but I can’t figure out how to populate from a table in the database. It feels that I’ve tried million ways now without success.
In this way it works:
                     .Resources(resource =>
                        {
                            resource.Add(m => m.ShiftID)
                            .Name("ShiftList")
                            .Title("Skift") 
                            .DataTextField("Text")
                            .DataValueField("Value")
                            .DataColorField("Color")

                            .BindTo(new[] {
                                new { Text = "fm-skift", Value = 1, Color = "#f8a398" } ,
                                new { Text = "em-skift", Value = 2, Color = "#51a0ed" } ,
                                new { Text = "Natt-skift", Value = 3, Color = "#56ca85" },
                                new { Text = "FM-skift", Value = 4, Color = "#c39bd3" },
                                new { Text = "EN-skift", Value = 5, Color = "#f1c40f" }
                            })
                            ;
                        })

But how can I populate from the database? All the Examples I can find are using MVC and not “true” Razor Pages.

on the model page I've created a list from the database that contains, Value, Textand Color, but I can't use it with Telerik Resources.

Veselin Tsvetanov
Telerik team
 answered on 13 Jan 2020
1 answer
418 views

While putting together my first app, I am loading a grid via javascript, populating the grid with Json data only after a number of other inputs are gathered from the user. While doing this, I omitted the .Read method on the datasource.  I was noticing http 400 errors everytime this page loaded.  Initially thought I was having issues with the Forgerytoken, but after trial-and-error, comparing to another sample page, I decided to stub in a .Read method and handler in the controller, and the http 400 errors stopped.  So I suppose my question is this - is a .Read method required, even if it will never be used?

 

See attached files, that show both screenshots of network traffic from the chrome debugger console.  Notice the last request in the stack in each case.

 

Tsvetomir
Telerik team
 answered on 13 Jan 2020
4 answers
507 views
Does Telerik have plans for custom filtering in the Telerik ASP.NET Core UI Grid?

When I ask, "Custom" I mean truly custom. 

Our need is to have a listbox (or similar) with multiple check boxes (scrolling) in it for each column of each grid.
This is for allowing the user to select one or more values.  These are parameter values.

So if we could inject a Razor partial or draw it in a hooked event into the row[0] of the grid we could gather these values when the search button is clicked.

Right now we draw the filtering partial view above the grid and play hell trying to align column widths in general, but our designer cannot make it work with mobile resolutions, etc.  So we need to draw the filter in the grid to make it work.

If Telerik has no plans to accommodate this scenario we need to know.  And if necessary we have to find a component suite that does.
Reid
Top achievements
Rank 2
 answered on 12 Jan 2020
3 answers
114 views

In this dojo I want to have a button to select the next and previous tabs(wizard navigation). The buttons work if the user clicks them slowly.

If the next button is clicked say 5 times rapidly, the tabstrip will only select up until the 2nd or 3rd tab instead of going all the way to the end.

I am using the asp.net core version of kendo but the jquery version is easier to show in the dojo and represents my problem.

https://dojo.telerik.com/EWALijil

 

Is there a way outside of disabling the button/debouncing/ or timeouts to get the tabstrip to queue any selects and use the final?

 

 

Martin
Telerik team
 answered on 10 Jan 2020
1 answer
128 views

I insert a image to the sheet, and transform sheet to datauri format. I get a error message.

function SaveElnFile(e) {
        var spreadSheet = GetSpreadsheet("ElnMain");
        var sheet = spreadSheet.activeSheet();
        spreadSheet.bind("excelExport", function (e) {
            var fileName = "ElnTemplate/" + GetDateTimeString() + ".xlsx";
            e.workbook.fileName = fileName;
            var workbook = new kendo.ooxml.Workbook({
                sheets: e.workbook.sheets
            });

            workbook.toDataURLAsync().then(function (dataURL) {
                xxxxxx....
            });
                e.preventDefault();
        });
        spreadSheet.saveAsExcel();
    }

 

 

Veselin Tsvetanov
Telerik team
 answered on 09 Jan 2020
1 answer
59 views

I don't think I'm alone in saying that it would be nice to see better docs, maybe even an entire separate section for this library that was Raorpages-specific.  

Would be nice to see such things as:
- Client template examples
- Different ways of loading & customizing the grid
- Common problems and their solutions


Petar
Telerik team
 answered on 09 Jan 2020
1 answer
275 views

I recently upgraded my project to ASP NET Core 3.2 and now my grids are returning undefined.  I've found a couple threads about this, but nothing that has worked for me so far.  I have an enumerable defined object that I'm creating in my AJAX LoadData method to load my data and returning.  What am I doing wrong?

 

index.cshtml

<ejs-grid id="Grid" allowPaging="true" allowSorting="true" allowFiltering="true">
    <e-data-manager url="/Routes/LoadData" updateUrl="/Routes/UpdateData" adaptor="UrlAdaptor"></e-data-manager>
    <e-grid-columns>
        <e-grid-column field="Name" headerText="Name" allowSorting="true"></e-grid-column>
        <e-grid-column field="Frequency.Name" headerText="Frequency" type="string"></e-grid-column>
        <e-grid-column field="DayOfWeek.Name" headerText="Day" type="string"></e-grid-column>
        <e-grid-column field="TimeOfDay.TimeString" headerText="Time"></e-grid-column>
        <e-grid-column field="RouteId" headerText="" template="#edittemplate"></e-grid-column>
    </e-grid-columns>
</ejs-grid>

<script id="edittemplate" type="text/x-template">
    <div>
        <a rel='nofollow' href="/Routes/Edit/${RouteId}">Edit</a>&nbsp;|&nbsp;
        <a rel='nofollow' href="/Routes/Details/${RouteId}">Details</a>&nbsp;|&nbsp;
        <a rel='nofollow' href="/Routes/Delete/${RouteId}">Delete</a>&nbsp;
    </div>
</script>

 

 

Controller

        public IActionResult LoadData([FromBody]DataManagerRequest dm)
        {
            var sa = new JsonSerializerSettings();
            IEnumerable<Route> DataSource = _context.Route
                .Include(r => r.DayOfWeek)
                .Include(r => r.Frequency)
                .Include(r => r.TimeOfDay)
                .ToList();
            DataOperations operation = new DataOperations();
            if (dm.Search != null && dm.Search.Count > 0)
            {
                DataSource = operation.PerformSearching(DataSource, dm.Search);  //Search
            }
            if (dm.Sorted != null && dm.Sorted.Count > 0) //Sorting
            {
                DataSource = operation.PerformSorting(DataSource, dm.Sorted);
            }
            if (dm.Where != null && dm.Where.Count > 0) //Filtering
            {
                DataSource = operation.PerformFiltering(DataSource, dm.Where, dm.Where[0].Operator);
            }
            int count = DataSource.Cast<Route>().Count();
            if (dm.Skip != 0)
            {
                DataSource = operation.PerformSkip(DataSource, dm.Skip);         //Paging
            }
            if (dm.Take != 0)
            {
                DataSource = operation.PerformTake(DataSource, dm.Take);
            }

            return Json(new { result = DataSource, count = _context.Route.Count() });
        }

Alex Hajigeorgieva
Telerik team
 answered on 09 Jan 2020
18 answers
641 views
I have looked all over the forums and I haven't been able to find a solution. I have attached some screenshot of the issues I keep encountering. This happens on only 3 of my charts which have long category names on the axis. I have tried some function and templates but have not been able to correct this. The issue only appears when exporting to pdf.
DC
Top achievements
Rank 1
 answered on 08 Jan 2020
2 answers
571 views

Have a razorpages app started and several areas of a view have various dropdowns etc that gather a users selections.  These selections are then used as inputs to grab data for a grid.  Ok, easy enough, my example is working so far.  However, so far I have only got to the point of LOADING my grid, now I need to handle updates/deletes etc.

Im looking over the examples, both frm the kendo project template and from this github project
https://github.com/telerik/ui-for-aspnet-core-examples/blob/master/Kendo.Examples.RazorPages/Kendo.Examples.RazorPages/Pages/Grid/GridCrudOperations.cshtml

Ok, some general questions and observations:

(1) These examples assume that criteria for getting the grid data is known at execution time.  In my case I need to gather several inputs before fetching the data for the grid.  Im doing this now, then loading the grid with json and javascript and it works.  However, now I need to handle updating/deleting etc
(2) What is the purpose of the .Data methods on the Datasource crud methods eg. and where is this Data method in the docs as used here?

.DataSource(ds => ds.Ajax()
        .Read(r => r.Url("/Index?handler=Read").Data("forgeryToken"))
        .Update(u => u.Url("/Index?handler=Update").Data("forgeryToken"))
        .Create(c => c.Url("/Index?handler=Create").Data("forgeryToken"))
        .Destroy(d => d.Url("/Index?handler=Destroy").Data("forgeryToken"))
        .Model(m => m.Id(id => id.OrderID))
    .PageSize(10)

(3) If I want to handle "batch" editing, AND I load the Dataset via JSON with javascript, how then does the .Read and other datasource method(s) need to change?
eg.  this example ,
https://demos.telerik.com/aspnet-core/grid/editing

so to load the product grid then

function testLoadDS() {
    var testObj = [{ "OrderID": "1", "Freight": "10.1", "OrderDate": "10/19/2019", "ShipCity": "Austin", "ShipName": "Test123" }];
    let productDS = $("#grid").data("kendoGrid").dataSource;
    productDS.data(testObj);
}

 

So then, this example, what things need to change from in-line to batch editing?
https://github.com/telerik/ui-for-aspnet-core-examples/tree/master/Kendo.Examples.RazorPages/Kendo.Examples.RazorPages/Pages/Grid

 


Tsvetomir
Telerik team
 answered on 08 Jan 2020
Narrow your results
Selected tags
Tags
+? more
Top users last month
Rob
Top achievements
Rank 3
Iron
Iron
Iron
Atul
Top achievements
Rank 1
Iron
Iron
Alexander
Top achievements
Rank 1
Veteran
Iron
Serkan
Top achievements
Rank 1
Iron
Shawn
Top achievements
Rank 1
Iron
Iron
Want to show your ninja superpower to fellow developers?
Top users last month
Rob
Top achievements
Rank 3
Iron
Iron
Iron
Atul
Top achievements
Rank 1
Iron
Iron
Alexander
Top achievements
Rank 1
Veteran
Iron
Serkan
Top achievements
Rank 1
Iron
Shawn
Top achievements
Rank 1
Iron
Iron
Want to show your ninja superpower to fellow developers?
Want to show your ninja superpower to fellow developers?