Kendo MVC Razor Grid Custom Command does not have Action Definition - razor

I am new to Kendo and are trying to add a custom command to a grid.
I have been going over example pages, StackOverflow, and Telerik's site and found multiple examples that has the following:
columns.Command(command =>
{
command.Custom("Details").Text("Show Details").Action("Details", "Billing");
});
When I try to use this, I get the following error:
'GridCustomActionCommandBuilder' does not contain a
definition for 'Action' and the best extension method overload
'UrlHelperExtensions.Action(IUrlHelper, string, object)' requires a
receiver of type 'IUrlHelper'
I then tried this example from telerik:
columns.Template(#<text>#Html.ActionLink("Edit", "Home", new { id = item.ProductID })</text>);
But get this error:
Cannot convert lambda expression to type 'string' because it is not a
delegate type
Just to confirm what is causing the error, then took out the ActionLink and used only this:
columns.Template(#<text>
<div>help me!!</div>
</text>);
and got the same error:
The total code snippet looks like this:
#(Html.Kendo().Grid<OrganisationEmployeesViewModel>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(p => p.EmployeeID).Visible(false);
columns.Template(#<text>
<div>help me!!</div>
</text>);
})
.Pageable()
.Sortable()
.Scrollable()
.Filterable()
.HtmlAttributes(new { style = "height:550px;" })
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Read(read => read.Action("Employees_Read", "Organisations"))
)
.Deferred()
)
I am using existing samples but don't know what is wrong.

I found a way for this to work:
columns.Template("<a href='" +
Url.Action("ControllerAction", "Controller") +
"?Parameter=#= RecID #'" +
">DisplayText</a>");
This can also be applied to a bound column like this:
columns.Bound(p => p.Name).ClientTemplate("<a href = '" +
Url.Action("Details", "Employees") +
"/#= EmployeeID #'" +
">#=Name#</a>");
And should you want to have a Custom Toolbar Action on the Kendo Grid:
I am using the standard bootstrap classes to apply defaults:
.ToolBar(t => t.ClientTemplate("<a class='k-button k-button-icontext k-grid-add' href='" +
Url.Action("OrganisationCreate", "Employees", new { OrganisationId = Model.OrganisationID }) +
"'><span class='k-icon k-add'></span>Add new Employee</a>") )

Related

Kendo MVC Grid Filtering - Filters that consider multiple fields

I have a MVC Kendo grid where one column is a client template that actually uses multiple fields. By default the built in filtering is only applied to the field the column is bound to. How do I override that so it considers both fields. Ie, when I search for "Contains" "De" a column that displays "Detroit, MI" should return.
Here's what I have so far:
MVC View
#(Html.Kendo().Grid<ViewModel>()
.DataSource(dataSource => dataSource
.Custom()
.Transport(t =>
{
t.Read(r => r.Action("StatusGridRead", "DeviceStatus"));
})
.Schema(schema => schema
.Data("Result.Data")
.Total("Result.Total")
.Errors("Result.Errors")
.Model(m =>
{
m.Id(f => f.Id);
m.Field(f => f.StateOrProvince);
m.Field(f => f.City);
...
})
)
)
.Columns(columns =>
{
columns.Bound(c => c.StateOrProvince).Title("City & State").ClientTemplate("#=City#, #=StateOrProvince#");
...
})
.Events(e=>
{
e.Filter("statusGridFilter");
})
.Sortable()
.Filterable(f =>
{
f.Extra(false);
f.Operators(o => o.ForString(s =>
{
s.Clear();
s.Contains("Contains");
s.IsEqualTo("Is Equal To");
s.StartsWith("Starts With");
s.EndsWith("Ends With");
s.DoesNotContain("Does Not Contain");
s.IsNotEqualTo("Is Not Equal To");
}));
})
)
Javascript
function statusGridFilter(e) {
if (e.field == "StateOrProvince") {
//What do I do here?
}
}
I understand if I made a column for city and one for state that would resolve this issue, however I actually have a similar scenario (client template with many string fields displayed) where that won't work and am just picking this as the easiest example. Other than making 1 column for 1 field, I'm open to any other ideas that may solve filtering for this scenario.

How to add SSN mask to a kendo grid filter?

I have a Kendo grid that displays many columns. I have a column for SSN. When user clicks on the filter and types in 123-45-6789 it filters the correct SSN, however, when user types in 123456789 nothing is filtered. Is there any way that it can filter only 9 numbers with or without dashes.
columns.Bound(p => p.SSN)
.Title("SSN")
.Width(100);
.HtmlAttributes(new {style = "height: 579px; width: 110%"})
.Scrollable()
.Sortable()
.Filterable(filterable => filterable
.Extra(false)
.Operators(operators => operators
.ForString(str => str.Clear()
.Contains("Contains")
.IsEqualTo("Is equal to")
.StartsWith("Starts with")
.IsNotEqualTo("Is not equal to")
)
)
)
You can set the filter to use a kendoMaskedTextBox like this:
<script>
function ssnFilter(element) {
element.kendoMaskedTextBox({
mask: "000-00-0000"
});
};
</script>
#(Html.Kendo().Grid<YourModel>()
.Name("YourGridName")
.Columns(columns =>
{
columns.Bound(p => p.SSN).Filterable(f => f.UI("ssnFilter"));
}
)
Kendo MaskedTextBox documentation
Kendo Grid Filter Customization documentation

How can I ensure Kendo Grid passes a numeric value with the correct separator to ASP.NET MVC?

I have a simple grid that uses a custom popup editor template. In the template, I'd like to use a Numeric Textbox.
Due to localization, the application keeps trying to use a comma to separate decimals in the numeric values. When these values are passed to the ASP.NET MVC back-end, the value is lost and null is passed. How can I ensure the posted value has a period separator?
I have tried setting the underlying field values to 2.5 instead of 2,5 in the grid's Save event, as well as tried to overwrite the e.model.WeightKg to 2.5. The value is still passed with a comma separator, as shown by inspecting the form data in the request.
My grid:
#(Html.Kendo().Grid<PackageViewModel>()
.Name("PackageGrid")
.Columns(columns => {
columns.Bound(o => o.PackageCode);
columns.Bound(o => o.WeightKg);
columns.Command(o => o.Edit());
})
.DataSource(d => d
.WebApi()
.Model(m => m.Id(o => o.PackageCode))
.Read(c => c.Url(Url.HttpRouteUrl("DefaultApi", new { controller = "Packages" })))
.Create(c => c.Url(Url.HttpRouteUrl("DefaultApi", new { controller = "Packages" })))
.Destroy(c => c.Url(Url.HttpRouteUrl("DefaultApi", new { controller = "Packages" id = "{0}" })))
.Update(c => c.Url(Url.HttpRouteUrl("DefaultApi", new { controller = "Packages" id = "{0}" })))
.PageSize(20)
)
.Editable(e => e.Mode(GridEditMode.PopUp).TemplateName("Package"))
.Selectable()
.Deferred()
)
The numeric textbox in the template:
#Html.Kendo().NumericTextBoxFor(m => m.WeightKg).Decimals(8)
And finally, the unparsed form data, followed by the parsed form data:
sort=&group=&filter=&PackageCode=DOOS-B&WeightKg=2%2C5
sort:
group:
filter:
PackageCode:DOOS-B
WeightKg:2,5

Kendo templates and reserved words

From the GridInForm C# project available from Telerik the file Index.cshtml contains this grid (among other things):
#(Html.Kendo().Grid(Model.Products)
.Name("Products")
.ToolBar(tools => tools.Create().Text("Add new product"))
.Editable(editable => editable.Mode(GridEditMode.InCell).CreateAt(GridInsertRowPosition.Bottom))
.Columns(columns =>
{
columns.Bound(p => p.Name).ClientTemplate("#= Name #" +
"<input type='hidden' name='Products[#= index(data)#].Name' value='#= Name #' />");
columns.Bound(p => p.ProductID).Hidden().ClientTemplate("#= ProductID #" +
"<input type='hidden' name='Products[#= index(data)#].ProductID' value='#= ProductID #' />");
columns.Command(command => command.Destroy()).Width(100);
})
.DataSource(dataSource => dataSource
.Ajax()
.Model(model =>
{
model.Id(p => p.ProductID);
model.Field(p => p.ProductID).Editable(false);
})
.ServerOperation(false)
)
)
And this javascript function:
function index(dataItem) {
var data = $("#Products").data("kendoGrid").dataSource.data();
return data.indexOf(dataItem);
}
My question is about finding more information about the data parameter being passed in the template to the index function (in the call to ClientTemplate). What is it and where does it come from?
This line shows the use of the index() function:
"<input type='hidden' name='Products[#= index(data)#].ProductID' value='#= ProductID #' />"
data in this line is a built in object that the Kendo framework creates when it parses the client template. It represents the data object for that particular row.
You can read a bit about the data object here: http://docs.telerik.com/kendo-ui/getting-started/using-kendo-with/aspnet-mvc/helpers/grid/faq#how-do-i-use-a-javascript-function-in-a-column-client-template? under the question titled "How do I use a JavaScript function in a column client template?"
If you want to know specifically what it looks like, you can add a console.wirte(JSON.stringify(dataItem)) to the index() function to see it's exact structure.
edit
Additionally, the client template is just a text string that the Kendo Javascript parses as each column in each row is being created. At that time, it has the data object for that row which it uses to insert the values into the grid. The MVC is just a wrapper for the Javascript libraries that actually generate the HTML in the document.

MVCContrib Grid Razor problem, Column.Action do not render

Code below works great with aspx view engine, i am trying to convert it to razor as below. Problem is first column do not show up.
I convert first column into link using action method. With razor it(first column) is not getting rendered in page at all. Rest of grid is fine.
What could be the problem?
#{Html.Grid(Model.Orders).Attributes(style => "width: 100%;").Columns(
column => {
column.For(x => x.OrderNumber).Action(p => {
#:<td>
Html.ActionLink(
p.OrderNumber.ToString(),
"orderdetail",
"OrderUpdate",
new { id = p.OrderNumber, backUrl = Url.Action("OrderHistory", new { controller = "DataController", id = ViewData["id"] }) },
new { });
#:</td>
}).HeaderAttributes(style => "text-align:left");
column.For(x => x.OrderTimeV2).HeaderAttributes(style => "text-align:left");
column.For(x => x.Status).HeaderAttributes(style => "text-align:left");
column.For(x => x.Type).HeaderAttributes(style => "text-align:left");
}).RowStart((p, row) => { }).Render();}
I have moved away from using mvccontrib grid as it doesn't make much sense in grid we have.
Anyway problem was code in the question does not return html but puts code directly into response stream. And code for columns rendered using razor which put's code into stream whenever called. so it ends up putting columns into stream before grid is rendered.
It was resolved by not using razor code in action called by grid.
Ok I got it working for me with the following
#Html.Grid(Model.Result).Columns(column => {
column.For(u => u.Name).Named("Name");
column.For(u => u.Code).Named("Code");
column.For(u => Html.ActionLink("Edit", "Edit", new { id = u.Id })).Named("Edit");
You can do a custom column to get what you want:
#Html.Grid(Model).Columns(column => {
column.Custom(
#<div>
<em>Hello there</em>
<strong>#item.Name</strong>
</div>
).Named("Custom Column");
})
From: MvcContrib Grid Custom Columns (Razor)
I did this when porting some .aspx pages to Razor.