How to Apply Class to GridMVC - asp.net-mvc

I need to apply some masking class to some columns.
Razor
#Html.Grid(Model).Columns(columns =>
{
columns.Add(c => c.BrokerID).Titled("FEN Account ID").SetWidth(220);
}

Exm :
Html.Grid(x).Columns(col => {}).Attributes(#class => "usertable");

You can just use the Css method to add a class to a column:
Columns.Add(x => x.Number).Css("hidden-xs")

Related

How can I move some of the Kendo MVC grid column definitions inside an helper method

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()
)

Kendo UI Grid pass value to edit popup

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

KendoUI Edit Issue

Kendo UI edit option showing some unexpected behaviour, as you can see in the image there is a text box below Server column and 2 below ServerIP column all containing the id of server "SQL" i selected. Problem is when ever i want to show Server IP column this behaviour occurs, both server and server IP are from the same table.
#(Html.Kendo().Grid<EnvironmentPOCO>()
.Name("Grid")
.Columns(columns =>
{
columns.Bound(d => d.EnvironmentName).Width(200).Title("EnvirontmentName");
columns.ForeignKey(d => d.EnvironmentTypeID, (List<EnvironmentTypePOCO>)ViewData["EnvironmentType"], "EnvironmentTypeID", "EnvironmentTypeCode").Width(150).Title("EnvironmentCode").EditorTemplateName("_EnvironmentCodeDropDown");
columns.ForeignKey(d => d.ServerID, (List<ServerPOCO>)ViewData["ServerDetails"], "ServerID", "ServerName").Width(200).Title("Server").EditorTemplateName("_ServerDropDown");
columns.ForeignKey(d => d.ServerID, (List<ServerPOCO>)ViewData["ServerDetails"], "ServerID", "ServerIP").Width(200).Title("ServerIP");
columns.ForeignKey(d => d.ProjectID, (List<ProjectPOCO>)ViewData["Projects"], "ProjectID", "ProjectName").Width(200).Title("ProjectName").EditorTemplateName("_ProjectNameDropDown");
// columns.ForeignKey(d => d.ProjectID, (List<ProjectPOCO>)ViewData["Projects"], "ProjectID", "ProjectDescription").Width(200).Title("ProjectDescription")/*.EditorTemplateName("_ProjectDescription")*/;
columns.Command(d =>
{
d.Edit();
d.Destroy();
}).Width(200).Title("Action");
})
.ToolBar(tools => tools.Create())
.Sortable()
.Pageable()
.Filterable()
.DataSource(dataSource => dataSource
.Ajax()
.Model(model =>
{
model.Id(m => m.EnvironmentID);
model.Field(m => m.EnvironmentName);
model.Field(m => m.EnvironmentTypeID);
model.Field(m => m.ProjectID);
model.Field(m => m.ServerID);
})
.Read(read => read.Url(ViewBag.ApiBaseUrl).Type(HttpVerbs.Get))
.Create(create => create.Url(ViewBag.ApiBaseUrl).Type(HttpVerbs.Post))
.Update(update => update.Url(ViewBag.ApiBaseUrl).Type(HttpVerbs.Put))
.Destroy(destroy => destroy.Url(ViewBag.ApiBaseUrl).Type(HttpVerbs.Delete))
)
)
I found a solution to this, actually if you want to show 2 fields of the foriegn key, You can make a property in your class.
public string ServerDetailsProperty
{
get
{
return string.Format(" Name: {0} || IP: {1}", ServerName, ServerIP);
}
}
then call it in your csHTML file like this.
columns.ForeignKey(d => d.ServerID, (List<ServerPOCO>)ViewData["ServerDetails"], "ServerID", "**ServerDetailsProperty**").Width(200).Title("ServerIP");
Now if you press Edit you want see the unexpected behiour as in the diagram.
Try Changing the id and name attribute of the Server IP columns as the Grid is not able to differentiate between the Server Column and Server IP column on Edit.
For your reference I have tried below:
columns.ForeignKey(d => d.ServerID, (List<ServerPOCO>)ViewData["ServerDetails"], "ServerID", "ServerIP").Width(200).Title("ServerIP").HtmlAttributes(new { #id="ServerIP_#=ServerIP#", #name="ServerIP_#=ServerIP#" })
Let me know if this doesn't solve your issue.
EDIT:
You can add the dropdown in client template as below:
columns.Bound(s => s.ServerID).ClientTemplate((#Html.Kendo().DropDownList()
.BindTo((List<ServerPOCO>)ViewData["ServerDetails"])
.Name("ServerIP#=ServerIP#")
.DataTextField("ServerIP")
.DataValueField("ServerID")
.ToClientTemplate()).ToHtmlString());
On Grid DataBound event set the grid scripts to load with document as below:
function onGridDataBound(e) {
$('#GridName script').appendTo(document.body);
}
Finally set the field to readonly in model meta:
model.Field(s => s.SensorID).Editable(false);
For further information have a look at the explaination: Dropdown in Column Client Template

Binding Telerik chart in MVC cs1660 error

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.

Sorting with MVCContrib

Does anyone know how to sort the MVCContrib grid when using a complex object.
My grid is displaying a list of Person and I'm trying to sort on the Country property. The problem is that Country is a property an Address class which is a property of Person.
Person.Address.Country
<%Html.Grid(Model).Columns(column =>
{
column.For(x => x.Id);
column.For(x => x.FirstName);
column.For(x => x.LastName).Sortable(false);
column.For(x => x.Address.Country).Sortable(false);
column.For(x => x.Age).Sortable(true);
}).Render(); %>
Exception:
Property 'Country' is not defined for type '{Namespace}.Person'
var sourceProp = Expression.Property(sourceParam, this.SortBy);
\MVCContrib\UI\Grid\Sortable\ComparableSortList.cs Line: 41
Any suggestions would be helpful.
Thank you,
MG1
A workaround would be to expose Country as a property on Person and use that:
public string Country { get { return Address.Country; } }
#orip gave you an answer.
But if you want to use the sorting feature you need to use:
<%Html.Grid(Model).Columns(column =>
{
column.For(x => x.Id);
column.For(x => x.FirstName);
column.For(x => x.LastName).Sortable(false);
column.For(x => x.Address.Country).Sortable(false);
column.For(x => x.Age).Sortable(true);
}).RenderUsing(new SortableHtmlTableGridRenderer<Person>())
.Render(); %>
Source: http://www.jeremyskinner.co.uk/2009/02/23/rewriting-the-mvccontrib-grid-part-3-gridmodels-and-gridrenderers/
You need to use SortColumnName for this.
column.For(x => x.Address.Country).SortColumnName("Address.Country");
I have tested this and it works like a charm :)
If you are not able to access SortColumnName(), you can get the latest version of MVC contrib from
http://mvccontrib.codeplex.com/SourceControl/changeset/changes/7db1cecc938f

Resources