I'm trying to use the Kendo Mvc Grid as a Mvc EditorTemplate like so.
ViewModel.cs
public class ViewModel{
...
public List<EditorViewModel> Lines{get;set;}
...
}
EditorViewModel.cs
public class EditorViewModel{
...
public string Text{get;set;}
...
}
View.cshtml
#model ViewModel
<form>
...
#Html.EditorFor(m => m.Lines, "Grid")
...
</form>
EditorTemplates/Grid.cshtml
#Model IEnumerable<EditorViewModel>
#Html.Kendo().Grid<EditorViewModel>().BindTo(Model)
...
.Columns(col => {
col.Bound(m => m.Text)**.EditorTemplate("Text.Grid");**
})
.Editable(g => g.Enabled(true).Mode(GridEditMode.InCell))
...
)
The Grid is displayed correctly and is editable as excepted, but when I'm leaving the edit mode a javascript error is thrown.
Uncaught TypeError: Cannot read property 'Text' of undefined
at eval (eval at getter (kendo.all.js:2041), <anonymous>:3:21)
at init.set (kendo.all.js:8149)
at init.change (kendo.all.js:8930)
at init.f (jquery-2.2.4.min.js:2)
at init.trigger (kendo.all.js:124)
at init.window.kendo.window.kendo.devtools.kendo.ui.Widget.trigger (<anonymous>:587:33)
at init._change (kendo.all.js:35754)
at init._blur (kendo.all.js:35719)
at init._focusout (kendo.all.js:35770)
at HTMLInputElement.f (jquery-2.2.4.min.js:2)
Is it possible to use a KendoGrid as Mvc EditorTemplate?
And if it is possible what am I doing wrong?
UPDATE:
If found a solution for this problem.
Changes made is with bold text.
In the Text.Grid.cshtml you add this line
#{
ViewData.TemplateInfo.HtmlPrefix = string.Empty;
}
this way the property prefix is removed
Related
I am using ASP.Net Mvc 4 with Kendo UI grid.
I would like to perform more advanced features on the kendo UI grid (like exporting the sorted data from the grid to excel, adding filters, etc.). I need to configure the DataSource in my View and the "Read" method in the Controller. The grid is populated from a LINQ query and stored in the ViewBag.
Here is the razor code in my view Index.cshtml
#(Html.Kendo().Grid((IEnumerable<Reports.Models.Company>)ViewBag.ActComp)
.Name("grid")
.Columns(columns =>
{
columns.Bound(comp => comp.Name);
columns.Bound(comp => comp.DateCreated);
columns.Bound(comp => comp.Quarter).Sortable(false);
columns.Bound(comp => comp.Code);
columns.Bound(comp => comp.Enabled).Column.Title = "Active";
})
.Sortable()
.Groupable()
.Scrollable(src => src.Height(500))
)
Here is the Controller ActiveCompController.cs
namespace Reports.Controllers
{
public class ActiveCompController : Controller
{
private FSLContext fslData = new FSLContext();
public ActionResult Index()
{
ViewBag.ActComp = from b in fslData.Companies
where b.Enabled == true
orderby b.Name
select b;
return View();
}
I have seen a couple of different examples with .Ajax() like:
.DataSource(dataSource => dataSource // Configure the grid data source
.Ajax() // Specify that ajax binding is used
.Read(read => read.Action("Products_Read", "Home")) // Set the action method which will return the data in JSON format
However, it didn't work as my data is from a LINQ query not formatted in JSON. Also, I don't know what to write in the "Read" method.
Any thoughts on how to configure the Datasource and the controller with my configuration ?
It looks like your code is similar to the example for the Kendo Grid at
http://demos.kendoui.com/web/grid/index.html
I would start by setting up a ViewModel class for Company that would hold all of your columns for the grid similar to how they have a ProductViewModel in their example. For instance, you would have the following in your ViewModel:
Name, DateCreated, Quarter, Code, Enabled
If you navigate to ASP.NET MVC > IndexController.cs you'll see where they've defined their method:
public ActionResult Products_Read([DataSourceRequest] DataSourceRequest request)
From there you'll see that they wrapped their LINQ results into their ViewModels and returned them in JSON format. You're on the right track for setting up the DataSource for your grid. As far as the Controller goes, you would change
.Read(read => read.Action("Products_Read", "Home"))
to
.Read(read => read.Action("<YourMethodHere>", "Home"))
Which will allow you to modify the logic for the read. However, note the Read operation is simply used for populating the table, any other functionality (such as sorting) would be handled differently. For more information on sorting take a look here
http://demos.kendoui.com/web/grid/sorting.html
I'm using editor from Kendo UI, so I have big problem.
I don't know how display items which are returned by editor.
Editor convert something like:
<img src="someurl" />
to:
lt;p><img src="someurl"/></p>
and I keep converted string in database, and try display it with:
#Html.Raw(item.description)
where description is string returned by kendo.
So I have no idea how display it correctly in my View
Any help would be appreciated.
There is an option of the KendeUI editor called encoded which configures whether the Editor should submit encoded HTML tags or not.
The default value for encoded is true
If you wan't to store the unencoded text use this sniplet when creating your editor:
$("#Editor").kendoEditor({
encoded: false
});
But because you are not sending encoded text to the server the Asp.net request validator kicks in and it will abort your request.
If you are using strongly typed views what you can do is to use the AllowHtmlAttribute on your model property:
View:
#model MyModel
#using(Html.BeginForm("SomeAction", "SomeController"))
{
#Html.TextAreaFor(m => m.Editor)
<input type="submit" value="Save" />
}
<script type="text/javascript">
$(function(){
$("#Editor").kendoEditor({
encoded: false
});
});
</script>
Model:
public class MyModel
{
[AllowHtml]
public string Editor { get; set; }
}
Controller action
public ActionResult SomeAction(MyModel myModel)
{
//Save to db, etc.
}
You also need to set the following in your web.config or this attribute won't have effect in .NET 4.0:
<httpRuntime requestValidationMode="2.0"/>
I found this solution for MVC:
in View
<div class="editor-field">
#(Html.Kendo().EditorFor(model => model.HtmlField).Encode(false))
#Html.ValidationMessageFor(model => model.HtmlField)
</div>
in model:
[DataType(DataType.Html)]
[AllowHtml]
public string HtmlField{ get; set; }
That was enough
Simplier way to do it is make changes in controller, no in view and model. So:
View
$("#Editor").kendoEditor();
Model
public class MyModel
{
public string Editor { get; set; }
}
Controller
Editor = Server.HtmlDecode(Editor);
HtmlDecode
The editor templates generated from the .NET Wrappers aren't working any more. Here is a fix.
http://pknopf.com/blog/kendo-ui-editor-templates-for-asp-net
I have a view with several controls that are used for searching. When a user searches (Ajax.BeginForm) off of these I return the data into a PartialView (Telerik MVC3 Grid) that was generated dynamically.
This all works fine. In the grid are buttons for selecting a row. When I select a row, it posts to my controller, I do some "stuff" etc. When I try to get back to the view all I get is my grid data on a page by itself, it displays like a table with no borders, no other controls etc. My code is below.
My partial grid:
#model Highlander.Areas.Highlander.Models.ViewModels.DeliveriesGridViewModel
#using System.Data;
#(Html.Telerik().Grid<System.Data.DataRow>(Model.Data.Rows.Cast<System.Data.DataRow>())
.Name("Grid")
.DataKeys(dataKeys => dataKeys.Add("DeliveryID"))
.Columns(columns =>
{
columns.Command(commandbutton =>
{
commandbutton.Select().ButtonType(GridButtonType.ImageAndText);
}).Width(80).Title(ViewBag.Title);
columns.LoadSettings(Model.Columns as IEnumerable<GridColumnSettings>);
})
.DataBinding(dataBinding => dataBinding.Server().Select("_MarkSystem", "Deliveries"))
.EnableCustomBinding(true)
.Resizable(resize => resize.Columns(true))
)
My Controller:
[GridAction]
public ActionResult _MarkSystem(GridCommand command, int id)
{
string shipDeliver = DataCache.ShipDeliver;
DataTable fullTable = DataCache.FullTable;
// call to function to get the datatable data based on the id
rHelpers.GetDataTableRow(id, fullTable, shipDeliver);
// get the data for the grid into the model
fullTable = DataCache.FullTable;
model = new DeliveriesGridViewModel();
model.Data = fullTable;
model.Columns = rHelpers.NewColumns(DataCache.FullTable);
return PartialView("_DeliveryGrid", model);
//if (Request.IsAjaxRequest())
//{
// return PartialView("_DeliveryGrid", model);
//}
//return PartialView("_DeliveryGrid", model);
//return PartialView("DeliveryManager", model);
}
As you can see I have tried various things with no success.
Can anyone give me some direction on this.
Thanks for your time.
As far i understand you are using dataBinding.Server() that call a server side binding. Use .Editable(editing => editing.Mode(GridEditMode.InLine) it will work.
Both kind of bindings (Server and Ajax) needs a editing mode. Put an editing mode and try again.Kindly Response if it does not work for you. Here full code of data binding:
**.DataBinding(dataBinding => dataBinding.Ajax()
.Select("myAction", "myController")
.Update("myAction",myController")).
Editable(editing => editing.Mode(GridEditMode.InLine))**
I have a view model that looks like this:
public class VenueIndexViewModel : BaseViewModel
{
public VenueAddViewModel Venue;
...
}
public class VenueAddViewModel
{
...
[Required(ErrorMessage = "This field is required")]
public string State { get; set; }
...
}
In my view, I'm rendering a form with with a drop down list for this property like so:
using (var form = Html.BeginForm())
{
...
#Html.DropDownListFor(x => x.Venue.State, Model.GetStates())
#Html.ValidationMessageFor(x => x.Venue.State)
...
}
This works, but the problem is that the the Required attribute on the view model appears to be ignored. If I look at the HTML, the data-val-* attributes are missing as well.
<select id="Venue_State" name="Venue.State">...</select>
However, if I change the rendering to a textbox...
using (var form = Html.BeginForm())
{
...
#Html.TextBoxFor(x => x.Venue.State)
#Html.ValidationMessageFor(x => x.Venue.State)
...
}
I see the expected data-val-* attributes and the validation works:
<input data-val="true"
data-val-required="This field is required"
id="Venue_State" name="Venue.State" type="text" value="">
I should note that I have other view models elsewhere that use DropDownListFor with a flat view model (no nested objects) and the validation works fine there, so I'm thinking I've hit a bug in the MVC validation handling for drop down lists when using a nested view model. Can anyone confirm / advise?
As far as I know you can't have client side validation on nested objects. And a quick google search seems to confirm that.
http://forums.asp.net/t/1737269.aspx/1
I have a situation where I want to use a custom EditorTemplate with a ViewModel. So I have my ViewModel...
class Aspect {
}
class AspectViewModel {
}
then my EditorTemplate
Views
Shared
EditorTemplates
Aspect.cshtml
Aspect.cshtml
#model AspectViewModel
// other html
Then in another view that takes AspectViewModel, I call #Html.EditorFor(model => model), but it does not work. It only works if I use a hard-coded string #Html.EditorForModel("Aspect").
Any idea why it isn't being called?
You should name the editor template AspectViewModel.cshtml if it is strongly typed to AspectViewModel. Then all you have to do is:
#model AspectViewModel
#Html.EditorForModel()
or
#model SomeViewModel
#Html.EditorFor(x => x.Aspect)
where the Aspect property of SomeViewModel is of type AspectViewModel.
The convention is that the editor/display should be named as the type of the property you are calling it on and not the name of this property.
They also work greatly with collections. For example if you have the following property:
public class SomeViewModel
{
public IEnumerable<AspectViewModel> Aspects { get; set; }
}
and you use:
#model SomeViewModel
#Html.EditorFor(x => x.Aspects)
then the ~/Views/Shared/EditorTemplates/AspectViewModel.cshtml editor template wil be rendered for each element of this collection. Thanks to this you really no longer need to ever write for/foreach loops in your views.
This is because your model is AspectViewModel, but your view name is Aspect. They must match exactly.