Using Visual Studio 2019, I believe I have encountered a new bug. When I have an existing solution, full of various .NET projects of various types, adding a new Telerik Core Project does not actually create a Telerik project.
To be specific, using the menu Extensions/Telerik/Kendo UI for ASP.NET Core/Create menu item results in the "standard" visual studio template being used. Absolutely zero Kendo/Telerik logic gets added to the resulting project. If I use the new "magic search box", located in middle of top of VS 2019 window, and enter "add new telerik core mvc" the resulting listed items actually take you to the correct launch point. That is to say the resulting project does actually contain the needed references.
While both avenues result in a newly added project to your solution, the second option appears to be the only avenue to using the pre-defined Telerik Template.
In fairness to Telerik this might actually be a Visual Studio bug.
I have just started a new contract and althought I am used to using Kendo, this is my first experience using Kendo Core.
Typically I would have my controller, and my action and bind on this using
.DataSource(ds => ds.Read(r => r.Action("RefreshRecommendationGridData", "ReportLookup")))
However the firm that I am at heavily uses routing
[Authorize]
[Route("report-lookups")]
public class ReportLookupController : Controller
{
[AccessRights("Lists")]
[HttpPost]
[Route("report-lesson-recommendations/manage")]
public async Task<
IActionResult
> RefreshRecommendationGridData([DataSourceRequest] DataSourceRequest request)
{
var result = await _cacheService.SearchForReportLessonRecommendationsAsync(null);
return Json(result.ToDataSourceResult(request));
}
}
When attempting this and looking through developer tools and the network and when using
.DataSource(ds => ds.Read(r => r.Url("manage"))
I get a 400 Bad Reqest error.
I guess I am missing something, however what that is I am at a complete loss. I suspect its something quite simple, however, I cannot find anything on Telerik site that will help.
When inspecting the headers in Fiddler, I cant see anything wrong.
Hello,
I'm trying to get my chart to display correctly. However, it seems the categories are not correct. Here is my code:
@(Html.Kendo().Chart(Model.CDashBoardLineCounts)
.Name("applicationStepsByDay")
.Legend(legend => legend.Visible(true))
.SeriesDefaults(seriesDefaults =>
seriesDefaults.Line().Style(ChartLineStyle.Smooth)
)
.CategoryAxis(axis => axis
.Categories(Model.Categories)
.MajorGridLines(lines => lines.Visible(false))
)
.Series(series =>
{
foreach (var s in Model.CDashBoardLineCounts)
{
series.Line(model => model.countofitems)
.Name(s.dashcolor)
.CategoryField("dateofCItem");
}
})
.ValueAxis(axis => axis.Numeric()
.Labels(labels => labels.Format("{0}"))
.Line(lines => lines.Visible(false))
)
.Tooltip(tooltip => tooltip
.Visible(true)
.Shared(true)
.Format("{0}")
)
)
public IActionResult Index()
{
CombinedDashBoard x = new CombinedDashBoard();
x.CDashBoardLineCounts = GetAllLineChartDetails();
x.Categories = new string[] { "Green", "Red", "Yellow" };
return View(x);
}
public class CombinedDashBoard
{
public List<
CDashBoardModifiedPieCounts
> CDashBoardPieCounts { get; set; }
public List<
CDashBoardModifiedLineCounts
> CDashBoardLineCounts { get; set; }
public string[] Categories { get; set; }
}
public class CDashBoardModifiedLineCounts
{
public string dashcolor { get; set; }
public string CItemName { get; set; }
public DateTime dateofCItem { get; set; }
public int countofitems { get; set; }
}
I would like to get a line in the chart for Red (that shows count of items that have the color red mapped to the dates), another line that shows all green items mapped to date per count and one for yellow.
Instead I'm getting the chart image attached
Thank you for your time
Hi,
I have just started a new contract with a new company and my previous experience with Kendo MVC was with MVC 5 rather than Core. The other difference is that the company I am at is heavily using Routes, rather than the action and the controller in the URL to determine where the user goes \ what URL they see.
An issue that I have is that currently the action passes a model back to the view and the grid is databound with this a list that is returned from the mode. On click of a row a modal window is opened, with data that can be edited, and then on save \ formAction the posts the data, and then the method redirects to action and the page reloads in order ot refresh the grid.
What I want to acheive is to refresh the grid on modal \ window close so that we dont have to post back.
My View as it stands is
<
div
class
=
"container-fluid"
accessrights-modify>
<
div
class
=
"btn-toolbar mb-3"
role
=
"toolbar"
>
<
div
accessrights-create
class
=
"btn-group float-right mr-2"
role
=
"group"
>
<
button
class
=
"btn btn-primary"
id
=
"btnCreate"
>Create New</
button
>
</
div
>
</
div
>
@(Html.Kendo().Grid(Model.ReportLessonRecommendation)
.Name("listGrid")
.Columns(columns =>
{
columns.Bound(c => c.Description)
.ClientHeaderTemplate("Description");
columns.Bound(c => c.Active)
.ClientTemplate("#if(Active) {# <
i
class
=
'fas fa-check'
></
i
> # } else {# <
i
class
=
'fas fa-times'
></
i
> #} #")
.ClientHeaderTemplate("Active")
.HtmlAttributes(new { @class = "text-center" })
.Width(100);
})
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(true)
.ButtonCount(5))
.Sortable()
.Filterable()
//.Groupable()
.NoRecords(n => n.Template("<
p
>There are no records to display.</
p
>"))
.HtmlAttributes(new { style = "width:100%;" })
.Selectable(selectable => selectable
.Mode(GridSelectionMode.Single)
.Type(GridSelectionType.Row))
.Events(events => events
.Change("onChange")
)
.Pageable(p =>
{
p.PageSizes(new[] { 5, 10, 30, 50, 100 });
})
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(50)
.ServerOperation(false)
)
)
@(Html.Kendo().Window()
.Name("modalRecommendationsWindow")
.Modal(true)
.Visible(false)
.MinWidth(750)
.Events(evt => evt.Close("onClose"))
.Content(@<
text
><
div
id
=
"modalRecommendationsContent"
></
div
></
text
>)
)
</
div
>
typically I would do a Read Action in the DataSource and direct it to my controller and my action and return a DataSourceRequest and would be something like this
<
div
class
=
"container-fluid"
accessrights-modify>
<
div
class
=
"btn-toolbar mb-3"
role
=
"toolbar"
>
<
div
accessrights-create
class
=
"btn-group float-right mr-2"
role
=
"group"
>
<
button
class
=
"btn btn-primary"
id
=
"btnCreate"
>Create New</
button
>
</
div
>
</
div
>
@(Html.Kendo().Grid<
ReportLessonRecommendation
>()
.Name("listGrid")
.Columns(columns =>
{
columns.Bound(c => c.Description)
.ClientHeaderTemplate("Description");
columns.Bound(c => c.Active)
.ClientTemplate("#if(Active) {# <
i
class
=
'fas fa-check'
></
i
> # } else {# <
i
class
=
'fas fa-times'
></
i
> #} #")
.ClientHeaderTemplate("Active")
.HtmlAttributes(new { @class = "text-center" })
.Width(100);
})
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(true)
.ButtonCount(5))
.Sortable()
.Filterable()
//.Groupable()
.AutoBind(true)
.NoRecords(n => n.Template("<
p
>There are no records to display.</
p
>"))
.HtmlAttributes(new { style = "width:100%;" })
.Selectable(selectable => selectable
.Mode(GridSelectionMode.Single)
.Type(GridSelectionType.Row))
.Events(events => events
.Change("onChange")
)
.Pageable(p =>
{
p.PageSizes(new[] { 5, 10, 30, 50, 100 });
})
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(50)
.ServerOperation(false)
.Read(r => r.Action("actionName", "controller"))
)
)
@(Html.Kendo().Window()
.Name("modalRecommendationsWindow")
.Modal(true)
.Visible(false)
.MinWidth(750)
.Events(evt => evt.Close("onClose"))
.Content(@<
text
><
div
id
=
"modalRecommendationsContent"
></
div
></
text
>)
)
</
div
>
The controller is
[Route("report-lookups")]
public class ReportLookupController : Controller
{
...
}
and Method I want to his is
[AccessRights("Lists")]
[HttpGet]
[Route("report-lesson-recommendations/refresh")]
public async Task<
IActionResult
> RefreshRecommendations([DataSourceRequest]DataSourceRequest request)
{
var result = await _cacheService.SearchForReportLessonRecommendationsAsync(null);
return Json(result.ToDataSourceResult(request));
}
when trying to AutoBind, and refresh and dataSource.Read() this method isnt hit however I try and do it.
Any and all help will be very much appreicated.
Thanks
Simon
Can you tell me how to auto-size my first "icon-template" column's Width? I have it set to a hard 125 but if I have a deeper hierarchy I'd like it to accommodate. Also, I've found when I have no other columns that even the 125 width doesn't seem to stick.
I've posted my TreeList definition many times in this forum but here it is again:
@using GsiPortal.Configuration
@{ Layout = null; }
@*Syntax Help here: https://docs.telerik.com/kendo-ui/framework/templates/overview*@
<
script
id
=
"icon-template"
type
=
"text/x-kendo-template"
>
<
div
class
=
'group-icon'
style
=
'background-image: url(@Url.Content("#: ImageUrl #"));'
></
div
>
<
div
class
=
'group-name'
>#: Name #</
div
>
</
script
>
@(Html.Kendo().TreeList<
GsiPortal.Models.Group
>()
.Name("treelist")
.Columns(columns =>
{
columns.Add().Field(e => e.Name).TemplateId("icon-template").Width(125);
columns.Add().Field(e => e.Description).Hidden(Model.GetBoolValue(Glossary.Keys.Group.IsHideMeta));
columns.Add().Field(p => p.PersonCount).Hidden(Model.GetBoolValue(Glossary.Keys.Group.IsHideMeta));
if (!Model.GetBoolValue(Glossary.Keys.Group.IsHideDetails))
{
columns.Add().Command(c => { c.Custom().Text("Details").Name("detailButton").ClassName("detailButton").Click("toDetails"); }).Width(Glossary.ButtonWidth);
}
if (!Model.GetBoolValue(Glossary.Keys.Group.IsHideCreate))
{
columns.Add().Command(c => { c.Custom().Text("Create").Name("createButton").ClassName("createButton").Click("toCreate"); }).Width(Glossary.ButtonWidth);
}
if (!Model.GetBoolValue(Glossary.Keys.Group.IsHideFilter))
{
columns.Add().Command(c => { c.Custom().Text("Filter").Name("filterButton").ClassName("filterButton").Click("toFilter"); }).Width(Glossary.ButtonWidth);
}
})
.DataSource(dataSource => dataSource
.ServerOperation(false)
.Read(read => read.Action("IndexJson", "Groups").Data("getData"))
.Model(m =>
{
m.Id(f => f.Id);
m.ParentId(f => f.ParentId);
m.Expanded(true);
m.Field(f => f.Name);
})
.Events(events => events.Error("onError"))
).Events(evt => evt.DataBound("treeListBound"))
)
<
script
>
function treeListBound(e) {
var treeList = e.sender;
var items = treeList.items();
for (i = 0; i <
items.length
; i++) {
var
dataItem
=
treeList
.dataItem(items[i]);
if (dataItem.IsHideCreate) {
$(items[i]).find(".createButton").hide();
}
if (dataItem.IsHideDetails) {
$(items[i]).find(".detailButton").hide();
}
if (dataItem.IsHideFilter) {
$(items[i]).find(".filterButton").hide();
}
}
}
</script>
<
style
>
.group-icon {
display: inline-block;
width: 40px;
height: 40px;
border-radius: 50%;
background-size: 40px 44px;
background-position: center center;
vertical-align: middle;
line-height: 41px;
box-shadow: inset 0 0 1px #999, inset 0 0 10px rgba(0,0,0,.2);
}
.group-name {
display: inline-block;
vertical-align: middle;
line-height: 41px;
padding-left: 10px;
}
</
style
>
Is there a way to add a placeholder for the filter input box? I have Select Location as my main placeholder but when the user opens the tree I would like the placeholder in the search box to be "Search by city...".
Thanks,
Bill
I get the following error constantly when attempting to use the TreeLIst. I'm using the Google Chrome browser and hitting the F12 button to expose the errors. At the very least, please wrap the error so it doesn't go uncaught. Best case would be to throw a useful error message a developer could work around.
Logging.ts:203 AI: CannotSerializeObjectNonSerializable message:"Attempting to serialize an object which does not implement ISerializable" props:"{name:baseData}"
o.warnToConsole @ Logging.ts:203
kendo.all.js:120332 Uncaught TypeError: (e.name || e).toLowerCase is not a function
at init._button (kendo.all.js:120332)
at init._buildCommands (kendo.all.js:120327)
at init._td (kendo.all.js:120245)
at d (jquery.min.js:2)
at init._tds (kendo.all.js:120175)
at init._trs (kendo.all.js:120093)
at init._render (kendo.all.js:119638)
at init.refresh (kendo.all.js:118289)
at init.d (jquery.min.js:2)
at init.trigger (kendo.all.js:124)
dc.services.visualstudio.com/v2/track:1 Failed to load resource: the server responded with a status of 400 (Invalid instrumentation key)
My TreeList:
@using GsiPortal.Configuration
@{ Layout = null; }
@*Syntax Help here: https://docs.telerik.com/kendo-ui/framework/templates/overview*@
<
script
id
=
"icon-template"
type
=
"text/x-kendo-template"
>
<
div
class
=
'group-icon'
style
=
'background-image: url(@Url.Content("#: ImageUrl #"));'
></
div
>
<
div
class
=
'group-name'
>#: Name #</
div
>
</
script
>
@(Html.Kendo().TreeList<
GsiPortal.Models.Group
>()
.Name("treelist")
.Columns(columns =>
{
columns.Add().Field(e => e.Name).TemplateId("icon-template");
columns.Add().Field(e => e.Description);
columns.Add().Field(p => p.PersonCount);
columns.Add().Command(c => { c.Custom().Text("Details").Name("detailButton").ClassName("detailButton").Click("toDetails"); }).Width(Glossary.ButtonWidth);
columns.Add().Command(c => { c.Custom().Text("Create").Name("createButton").ClassName("createButton").Click("toCreate"); }).Width(Glossary.ButtonWidth);
if (!Model.GetBoolValue(Glossary.Keys.Group.IsHideFilter))
{
columns.Add().Command(c => { c.Custom().Text("Filter").ClassName("filterButton").Click("toFilter"); }).Width(Glossary.ButtonWidth);
}
})
.DataSource(dataSource => dataSource
.ServerOperation(false)
.Read(read => read.Action("IndexJson", "Groups").Data("getData"))
.Model(m =>
{
m.Id(f => f.Id);
m.ParentId(f => f.ParentId);
m.Expanded(true);
m.Field(f => f.Name);
})
.Events(events => events.Error("onError"))
).Events(evt => evt.DataBound("treeListBound"))
)
<
script
>
function treeListBound(e) {
var treeList = e.sender;
var items = treeList.items();
for (i = 0; i <
items.length
; i++) {
var
dataItem
=
treeList
.dataItem(items[i]);
if (dataItem.IsHideCreate) {
$(items[i]).find(".createButton").hide();
}
if (dataItem.IsHideDetails) {
$(items[i]).find(".detailButton").hide();
}
if (dataItem.IsHideFilter) {
$(items[i]).find(".filterButton").hide();
}
}
}
</script>
<
style
>
.group-icon {
display: inline-block;
width: 40px;
height: 40px;
border-radius: 50%;
background-size: 40px 44px;
background-position: center center;
vertical-align: middle;
line-height: 41px;
box-shadow: inset 0 0 1px #999, inset 0 0 10px rgba(0,0,0,.2);
}
.group-name {
display: inline-block;
vertical-align: middle;
line-height: 41px;
padding-left: 10px;
}
</
style
>