I'm trying to bind Telerik Chart to IEnumerablge<MyModel> Inside Partial View
My Model
public class MyModel
{
private string identifier;
private DateTime date;
private int visits;
}
Partial View
#model IEnumerable<MyModel>
#{
Html.Telerik().Chart(Model)
.Name("Visits")
.Legend(legend => legend.Visible(true).Position(ChartLegendPosition.Bottom))
.Series(series => {
series.Line("CurrentMonth").Name("Current Month")
.Markers(markers => markers.Type(ChartMarkerShape.Triangle));
series.Line("PrevMonth").Name("Previous Month")
.Markers(markers => markers.Type(ChartMarkerShape.Square));
})
.CategoryAxis(axis => axis.Categories(s => s.date))
.ValueAxis(axis=>axis.Numeric().Labels(labels=> labels.Format("{0:#,##0}")))
.Tooltip(tooltip => tooltip.Visible(true).Format("${0:#,##0}"))
.HtmlAttributes(new { style = "width: 600px; height: 400px;" });
}
Getting Following error:
CS1660: Cannot convert lambda expression to type 'System.Collections.IEnumerable' because it is not a delegate type
On Following line of code:
.CategoryAxis(axis => axis.Categories(s => s.date))
Thank you!
There were multiple issues with the code. after changing bits in pieces in code I finally figured out following works fine:
#{
Html.Telerik().Chart(Model)
.Name("SampleChart")
.Tooltip(tooltip => tooltip.Visible(true).Format("${0:#,##0}"))
.Legend(legend => legend.Position(ChartLegendPosition.Bottom))
.Series(series =>
{
series.Line(s => s.visits).Name("Visits");
series.Line(s => s.hits).Name("Hits");
})
.CategoryAxis(axis => axis
.Categories(s => s.date)
)
.Render();
}
So there was Render() missing in the end.
Also paramter in series.Line("CurrentMonth") must match the field name in the myObject, Or field selected through lambda expression.
Related
I have a Kendo MVC Grid which is becoming really big and complex. I'd like to know how I can move some of the column definitions inside an helper method within the view. I can't figure out the right syntax for my helper method below.
#(Html.Kendo()
.Grid<MyModel>()
.Name("documents")
.Editable(e => e.Mode(GridEditMode.InLine))
.AutoBind(false)
.DataSource(b => b.Ajax()
.Model(m =>
{
m.Id(o => o.Id);
})
.Read(a => a.Action("documents", "document")
)
.Columns(c =>
{
c.Bound(m => m.Name)
.Title(Resources.Document.Name);
c.Bound(m => m.Description)
.Title(Resources.Document.Description);
...
if(ViewBag.CanViewEquipmentColumns) {
CreateEquipmentColumns(c); // The helper method
}
...
c.Bound(m => m.Size)
.Title(Resources.Document.Size);
})
)
// Here is the code that I can't get to work. How can I define this custom helper method here using the Razor view engine and Kendo Grid fluent API?
#{
Kendo.Mvc.UI.Fluent.GridBoundColumnBuilder<MyModel> CreateEquipmentColumns(Kendo.Mvc.UI.Fluent.GridColumnFactory<MyModel> c)
{
c.Bound(m => m.Equipment)
.Title(Resources.MaintenanceBooklet.Equipment);
c.Bound(m => m.StartDate)
.Title(Resources.MaintenanceBooklet.StartDate);
c.Bound(m => m.EndDate)
.Title(Resources.MaintenanceBooklet.EndDate);
}
}
I'm not sure about method within the view. You should make extension method, something like that:
public static void CreateEquipmentColumns<MyModel>(this GridColumnFactory<MyModel> factory, WebViewPage<YourViewModel> webViewPage)
{
factory.Bound(m => m.Equipment)
.Title(Resources.MaintenanceBooklet.Equipment);
}
And u can use it within the view:
Columns(c =>
{
c.Bound(m => m.Name)
.Title(Resources.Document.Name);
c.Bound(m => m.Description)
.Title(Resources.Document.Description);
...
if(ViewBag.CanViewEquipmentColumns) {
c.CreateEquipmentColumns(this); // The helper method
}
...
c.Bound(m => m.Size)
.Title(Resources.Document.Size);
})
You can add extension method like this and you can avoid repeating code across solution.
public static class KendoExtensions
{
public static GridBuilder<T> AddDefaultOptions<T>(this GridBuilder<T> builder) where T : mymodelClass // Your class here
{
return builder
.Columns(c =>
{
c.Bound(m => m.Equipment).Title(Resources.MaintenanceBooklet.Equipment);
c.Bound(m => m.StartDate).Title(Resources.MaintenanceBooklet.StartDate);
c.Bound(m => m.EndDate).Title(Resources.MaintenanceBooklet.EndDate);
});
}
}
View
#(Html.Kendo().Grid(Model.Mydata)
.Name("mygrid")
.AddDefaultOptions()
)
App type: ASP.NET MVC with Kendo framework
Problem Encountered: The detail template is not firing the controller action method. Please find the attached screenshot also. I checked it under the firebug window also, there is no ajax call to the controller action method "PublishedImportFiles_Read". This is making me crazy and annoying. No error is thrown or shown for this anomaly. I guess i am missing something very small.
Please help.
MVC - View Code
<div class="gapLeft gapBelow20" style="width:70%;">
#(Html.Kendo().Grid<ViewModels.PublishedImportViewModel>()
.Name("GridImport")
.Columns(columns =>
{
columns.Bound(p => p.TemplateGroup).Title("Template Group").Width("120px");
columns.Bound(p => p.TaxYear).Title("Tax Year").Width("70px");
columns.Bound(p => p.FileDescription).Title("Description").Width("200px");
columns.Bound(p => p.DatePublished).Title("Published Date").Format("{0:MM/dd/yyyy}").Width("100px");
columns.Bound(p => p.PublishedBy).Title("Published By").Width("100px");
})
.Scrollable()
.ClientDetailTemplateId("tplGridImport")
.Events(et => et.DataBound(fnCall.Replace("functionName", "gridImpDataBound")))
.Events(et => et.DetailInit(fnCall.Replace("functionName", "gridImpChildInit")))
.HtmlAttributes(new { style = "height:300px;" })
.DataSource(ds => ds.Ajax().ServerOperation(false)
.Read(read => { read.Action("PublishedImport_Read", "Import"); })
.Model(m => { m.Id(p => p.TemplateGroupID); })
)
)
</div>
<script id="tplGridImport" type="text/kendo-tmpl">
#(Html.Kendo().Grid<ViewModels.PublishedImportViewModel>()
.Name("GridImport_#=TemplateGroupID#")
.Columns(columns =>
{
columns.Bound(c => c.TemplateGroup).Title("Template Group").Width("120px");
columns.Bound(c => c.TaxYear).Title("Tax Year").Width("70px");
})
.DataSource(dsx => dsx.Ajax()
.Read(rd => { rd.Action("PublishedImportFiles_Read", "Import"); })
)
.ToClientTemplate()
)
</script>
Import Controller ActionResult Method:
[OutputCache(Duration = 0)]
public ActionResult PublishedImportFiles_Read([DataSourceRequest] DataSourceRequest request)
{
int groupID = 5;
IEnumerable<PublishedImportViewModel> pubVM = Enumerable.Empty<PublishedImportViewModel>();
var pubRecords = base.ScenarioMangtService.GetPublishedImportFilesByTemplateGroup(ClientID, SelectedYear, groupID);
pubVM = pubRecords.Select(s => new PublishedImportViewModel
{
ImportFileJobID = s.ImportFileJobID,
TemplateGroupID = s.TemplateGroupID,
TemplateGroup = s.TemplateGroup,
FileName = s.FileName,
FileDescription = s.FileDescription,
TaxYear = SelectedYear,
DatePublished = s.DatePublished,
PublishedBy = s.PublishedBy
});
return Json(pubVM.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
}
There was nothing wrong with the KendoGrid code. Strangely, there was a javascript error in another js file. And for some weird reason, it was breaking the binding of the detail template grid.
So when i commented the other broken code in another file, this grid starts working automatically.
I have a grid with a client detail template. This detail template is rendered in a separate partial view. Within this grid I need to use client templates to format some of the columns. Unfortunately I run into an invalid template error.
This is my detail template:
<script id="operationDetailTemplate" type="text/kendo-template">
#(Html.Kendo().TabStrip()
.Name(componentName: "tabStrip_#=Id#")
.SelectedIndex(index: 0)
.Animation(animation => animation.Open(open => open.Fade(FadeDirection.In)))
.Items(items => {
items.Add().Text(this.LocalResources(key: "Messages")).Content(#<text>
#(Html.Kendo().Grid<NotificationViewModel>()
.Name(componentName: "notificationGrid_#=Id#")
.Pageable()
.Scrollable()
.Filterable()
.Sortable()
.Columns(col => {
col.Bound(c => c.DateCreated).Format(value: "{0:yyyy/MM/dd HH:mm}");
col.Bound(c => c.Severity);
col.Bound(c => c.Title);
col.Bound(c => c.Text).ClientTemplate(string.Format("{0}...", "#= formatter(Text, 20) #"));
})
.DataSource(ds => ds.Ajax().Sort(sort => sort.Add(memberName: "DateCreated").Descending())
.Read(read => read.Route(MessageEventControllerRoute.PostReadForOperation, new RouteValueDictionary { { "operationId", "#=Id#" }, { "culture", UICulture.ToLower() } })))
.ToClientTemplate())
</text>
);
items.Add().Content(#<text>
#(Html.Kendo().Grid<OperationViewModel>().Name(componentName:"alternativesGrid")
.Columns(col => {
col.Bound(op => op.OperationIdFormatted);
col.Bound(op => op.EfficiencyRank);
col.Bound(op => op.WorkOrder.WorkOrderIdFormatted);
col.Bound(op => op.Length)
.ClientTemplate(value: "#if (data.Length) {# #:kendo.toString(Length.Hours, '00')#:#:kendo.toString(Length.Minutes, '00')#:#:kendo.toString(Length.Seconds, '00')# #}#")
.EditorTemplateName(templateName: "TimeSpan");
})
.DataSource(ds => ds.Ajax()
.Read(read => read.Route(OperationControllerRoute.PostOperationAlternatives, new RouteValueDictionary { { "workOrderId", "#=Operation.WorkOrderId#" }, { "seqNo", "#=Operation.SequenceNumber#" }, { "culture", UICulture.ToLower() } })).Model(m => m.Id(op => op.Id)))
.ToClientTemplate()
)</text>);
})
.ToClientTemplate())
</script>
As I am not able to pass an template id to the column template, I have no idea how to avoid the invalid template error.
Any ideas how to use client templates in this scenario?
Regards
Bernd
After some more experimenting I found two solutions.
Escape the client template in the low level grid.
Using
.ClientTemplate(value: "\\#if (data.Length) {\\# \\#:kendo.toString(Length.Hours, '00')\\#:\\#:kendo.toString(Length.Minutes, '00')\\#:\\#:kendo.toString(Length.Seconds, '00')\\# \\#}\\#")
instead of
.ClientTemplate(value: "#if (data.Length) {# #:kendo.toString(Length.Hours, '00')#:#:kendo.toString(Length.Minutes, '00')#:#:kendo.toString(Length.Seconds, '00')# #}#")
Change the tab content to load on demand.
Only problem here is that the ajax data source isn't called. So pass a model to the partial view and remove the
.ToClientTemplate()
instruction.
I'm using Kendo UI MVC and I have a view that contains details about an object. On that page I have a Kendo UI Grid that shows a list of notes about the object. I allow the user to create or edit the notes from the grid.
The problem I have is when the user clicks the add button I need to pass the id of the page's object. I'm using GridEditMode.PopUp.
Basically, this is what I have:
public class Item {
public int Id { get;set; }
...
}
public class Note {
public int ItemId {get;set;}
...
}
Here is the grid code:
#(Html.Kendo()
.Grid<NoteViewModel>()
.Name("kendo-grid")
.Columns(columns =>
{
columns.Bound(n => n.NoteDateTime).Title("Date").Format("{0:MM/dd/yyyy}");
columns.Bound(n => n.NoteDateTime).Title("Time").Format("{0:h:mm tt}").Sortable(false);
columns.Bound(n => n.NoteActivityType).Title("Activity Type");
columns.Bound(n => n.NoteDescription).Title("Description");
columns.Bound(n => n.NoteDetail).Title("Notes");
columns.Command(command => { command.Edit(); command.Destroy(); }).Width(200);
})
.ToolBar(toolbar => toolbar.Create())
.Editable(editable => editable.Mode(GridEditMode.PopUp).TemplateName("Note"))
.Mobile()
.Pageable()
.Sortable()
.Filterable()
.Reorderable(r => r.Columns(true))
.Resizable(r => r.Columns(true))
.DataSource(dataSource => dataSource.Ajax()
.Model(model => model.Id(note => note.Id))
.PageSize(25)
.Sort(sort =>
{
sort.Add(note => note.NoteDateTime);
})
.Read(read => read.Action("ReadNotes", "Case").Data("getCaseId"))
.Create(a => a.Action("CreateNote", "Case"))
.Update(u => u.Action("UpdateNote", "Case"))
.Destroy(d => d.Action("DeleteNote", "Case"))
)
)
I need to set Note.ItemId when the user clicks the add button on the grid. Or, is there a better way to do this, as in send the ItemId value on the post?
I ended up getting this to work by hooking into the edit event of the popup. I wasn't able to figure out how to do it on the initial setup, so I added this to doc ready handler to the edit popup. This kind of feels like a hack, so if someone has a better way I'd love to hear about it. The #ItemId input is already on the details page, so I figured I may as well use it.
$(function () {
function setItemId(event) {
var uid = $('.k-edit-form-container').closest('[data-role=window]').data('uid');
var model = $('#kendo-grid').data('kendoGrid').dataSource.getByUid(uid);
if (model.get('ItemId') === 0) {
model.set('ItemId', Number($('#ItemId').val()));
}
}
var grid = $('#kendo-grid').data('kendoGrid');
grid.bind('edit', setItemId);
});
I'm not sure if it's possible what you want, but to get you on the way this is how you'd start doing it.
You generally want a flat viewmodel, containing everything you want to use.
public class NoteViewModel {
public int ItemId { get;set; }
}
Then properly setup the use of your editor template. Since your ItemId is now part of the grid's model it'll be send to the controller on edit/create.
#(Html.Kendo()
.Grid<NoteViewModel>()
.Name("kendo-grid")
.Columns(columns =>
{
columns.Bound(n => n.ItemId).Hidden();
columns.Bound(n => n.NoteDateTime).Title("Date").Format("{0:MM/dd/yyyy}");
columns.Bound(n => n.NoteDateTime).Title("Time").Format("{0:h:mm tt}").Sortable(false);
columns.Bound(n => n.NoteActivityType).Title("Activity Type");
columns.Bound(n => n.NoteDescription).Title("Description");
columns.Bound(n => n.NoteDetail).Title("Notes");
columns.Command(command => { command.Edit(); command.Destroy(); }).Width(200);
})
.ToolBar(toolbar => toolbar.Create())
.Editable(editable => editable.Mode(GridEditMode.PopUp).TemplateName("NoteTemplate"))
Etc...
)
Finally create your template (called NoteTemplate.cshtml) and place it in Views/Shared/EditorTemplates so Kendo can find it.
#model NoteViewModel
Date: #Html.EditorFor(l => l.NoteDateTime)
Note Description: #Html.EditorFor(l => l.NoteDescription)
(Add all fields you need to edit here)
I had same problem
Problem is that some of fields of the model(viewmodel) is nullable
Model nullable field is not fully supported in Kendo UI
In my view, the drop down list is displayed properly when I do this -
#Html.DropDownListFor(m => m.SelectedEstimateState, Model.EstimateStateList.ToSelectList(c => c.Value, c => c.Text), new { });
But not when I do this -
#{
Html.DropDownListFor(m => m.SelectedEstimateState, Model.EstimateStateList.ToSelectList(c => c.Value, c => c.Text), new { });
}
What is the difference between the two?
this is the code block expression , which is used to evaluate the expression. but it does not write out. for more info check the razor syntax Razor syntax and web-programming-using-the-razor-syntax
#{
Html.DropDownListFor(m => m.SelectedEstimateState, Model.EstimateStateList.ToSelectList(c => c.Value, c => c.Text), new { });
}
Where below will write out the content (basically it's same as the response.write() with encoded )
#Html.DropDownListFor(m => m.SelectedEstimateState, Model.EstimateStateList.ToSelectList(c => c.Value, c => c.Text), new { });