i'm new to kendo UI and currently learning about custom editor.
My Problem is i managed to get my editor template working in edit mode and populate the data just fine, but somehow it won't save the value to the display grid
I Retreive all my data from API.
UPDATE:
i've managed to properly save the value from the custom editor template to the controller and it works just fine, but using clientTemplate won't display the correct value from what i select in the dropdown, and only show a string
DropDown Only Display A String
my setup code is like this
#( Html.Kendo().Grid<SalesOrderDetailVM>()
.Name("list-detail")
.Columns(columns =>
{
columns.Bound(c => c.Product).ClientTemplate("\\#=Product.ProductId\\#").Title("Products");
columns.Bound(c => c.Quantity);
columns.Bound(c => c.UnitPrice);
})
.Editable(GridEditMode.InCell)
.ToolBar(tool =>
{
tool.Create();
tool.Save();
}
)
.DataSource(dataSource => dataSource
.Ajax()
.ServerOperation(false)
.Batch(true)
.Model(model =>
{
model.Id(p => p.ProductId);
model.Field(p => p.Product);
})
.Create(act => act.Action("DetailCell_Create","SalesOrder"))
)
)
DDLProduct.cshtml:
#model AAF.WEB.MVC.ViewModels.ProductVM
#(
Html.Kendo().DropDownListFor(m => m)
.DataValueField("ProductId")
.DataTextField("ProductName")
.OptionLabel("Select Product")
.BindTo((System.Collections.IEnumerable)ViewData["products"])
)
Edit Mode
DisplayMode / Out of Product Edit Mode
Use template method to acheive dropdown with kendo grid.
GridForeignKey.cshtml - it should placed in shared folder or EditorTemplates
#model object
#(
Html.Kendo().DropDownListFor(m => m)
.BindTo((SelectList)ViewData[ViewData.TemplateInfo.GetFullHtmlFieldName("") + "_Data"])
)
In your kendo grid please change like below
#( Html.Kendo().Grid<AAF.WEB.MVC.ViewModels.SalesOrderDetailVM>()
.Name("list-detail")
.Columns(columns =>
{
columns.Bound(c => c.Id)
columns.ForeignKey(c => c.ProductId, (System.Collections.IEnumerable)ViewData["Products"], "ProductId", "ProductName").Title("Products");
columns.Bound(c => c.Quantity);
columns.Bound(c => c.UnitPrice);
})
.Editable(GridEditMode.InCell)
.ToolBar(tool =>
{
tool.Create();
tool.Save();
}
)
.DataSource(dataSource => dataSource
.Ajax()
.ServerOperation(false)
)
)
You can set the products data to view data. using this method you can save the product id.
Thanks
Okay after i frustrated for many hours, finally found the solution
the solution is to add a defaultvalue to the passed model in the grid
.Model(model =>
{
model.Id(p => p.ProductId);
model.Field(p => p.Product).DefaultValue(
ViewData["defaultProduct"] as ProductVM
);
})
and pass the data from the controller
// Function that get data from API
ViewData["products"] = products;
ViewData["defaultProduct"] = products.First();
Related
I have kendo grid and I need to have in inline editing two dropDownLists in two cells. The second list is depended on first one. The second can have 0 or X items. When is 0 in second, how Can I send null value to server when save item ?
Grid look like this:
columns.Bound(work => work.Project).ClientTemplate("#=Project.Name#").Width(350); // 1 DropDownList
columns.Bound(work => work.Spp).ClientTemplate("#=Spp.Code#").Width(100);
columns.Bound(work => work.Operation).ClientTemplate("#=Operation.Code#").Width(100);// 2 DropDownList
.DataSource(dataSource => dataSource
.Ajax()
.Batch(false)
.Events(events => events.RequestEnd("OnRequestEnd_TopLinePriceGrid"))
.PageSize(20)
//.Events(events => events.Error("error_handler"))
.Model(model =>
{
model.Id(p => p.Id);
model.Field(p => p.Operation).DefaultValue(ViewData["defaultOperation"] as TT.ViewModel.OperationViewModel);
model.Field(p => p.Spp).DefaultValue(ViewData["defaultSpp"] as TT.ViewModel.SppViewModel);
model.Field(p => p.Project).DefaultValue(ViewData["defaultProject"] as TT.ViewModel.ProjectViewModel);
})
.Read(read => read.Action("WorkRead", "Home").Data("currentWeekInfo")) // Přidádo HTTP parametr s vybranným týdnem
.Create(update => update.Action("EditingInline_Create", "Home").Data("currentWeekInfo"))
.Update(update => update.Action("EditingInline_Update", "Home").Data("currentWeekInfo"))
.Destroy(update => update.Action("EditingInline_Destroy", "Home").Data("currentWeekInfo"))
)
Editor template for Operation:
#(Html.Kendo().DropDownList()
.Name("Operation")
.OptionLabel("Choose operation...")
.CascadeFrom("Project")
.DataValueField("Id")
.DataTextField("Code")
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetCascadeOperations", "Home")
.Data("filterOperations");
}).ServerFiltering(true); ;
})
.Enable(false)
.AutoBind(false)
)
When I click save I have always default value fot operation in request.
Thnaks for any help!
To send null value to the server the corresponding field (Operation) in the model should be of nullable type. Also the DropDownList should have OptionLabel defined and ( in case it's primitive type) ValuePrimitive option set to true.
I have a kendo grid with datasource. Each time it is refreshing the old data with new data. But my requirement is quite different I also want display old data as well.
Another data source is in anotherKENDO GRID.
My Kendo Grid as below:
#(Html.Kendo().Grid<ABC>()
.Name("grdABC")
.HtmlAttributes(new { style = "height:450px" })
.Columns(columns =>
{
columns.Bound(d => d.ID).Hidden(true);
columns.Bound(d => d.Group).Hidden(true);
columns.Bound(d => d.Name).Title("Name").Width(350);
})
.Selectable(selectable => selectable
.Mode(GridSelectionMode.Multiple))
.Scrollable()
.Filterable()
.DataSource(dataSource => dataSource
.Ajax()
.Sort(sort => sort.Add("Name").Ascending())
.Model(model => model.Id(p => p.ID))
.Read(read => read.Action("GetSelectedNames", "EligCriteria", new { Id = Model.ID != null ? Model.ID : (decimal?)null }).Data("getSelectedEligibilityNames"))
)
.AutoBind(false)
)
We can maintain using below code:
var grid = $("#GridID").data("kendoGrid");
grid.one("dataBinding", function(e){
e.preventDefault()
});
I have a Kendo Grid which has a popup editable template,
If possible i would like to pass the model (the model of the row, or at least its Id) to the editable template
Grid
#(Html.Kendo().Grid<Client>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(c => c.Name).Width(140);
columns.Bound(c => c.Status);
columns.Bound(c => c.ProcesingStyle);
columns.Bound(c => c.ArchiveDays);
columns.Command(command =>
{
command.Edit().Text(" ");
command.Destroy().Text(" "); ;
}).Width(90);
})
.ToolBar(toolbar => toolbar.Create().Text("New"))
.Editable(editable => editable
.Mode(GridEditMode.PopUp)
.TemplateName("Client").AdditionalViewData(new { Client = Model })
.Window(w => w.Title("Site")))
.HtmlAttributes(new { style = "height: 380px;" })
.Scrollable()
.Sortable()
.Selectable()
.Resizable(resize => resize.Columns(true))
.Reorderable(reorder => reorder.Columns(true))
.Events(events => events.Change("onChange"))
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(true)
.ButtonCount(5))
.DataSource(dataSource => dataSource
.Ajax()
.Read(read => read.Action("Get", "Clients"))
.Model(model => model.Id(p => p.Id))
.Create(update => update.Action("Create", "Clients"))
.Update(update => update.Action("Update", "Clients"))
.Destroy(update => update.Action("Destroy", "Clients"))
)
)
Template
#model Client
#(Html.Kendo().ComboBoxFor(m => m.Plan)
.DataTextField("Name")
.DataValueField("Id")
.Placeholder("Select Plan...")
.HtmlAttributes(new { style = "width:300px" })
.Filter(FilterType.Contains)
.MinLength(3)
.DataSource(source =>
source.Read(read =>
read.Action("GetPlans", "Plans",new {ClientId = Model.Id}))))
Everything works fine except i need to use the Id of the row/model inside the template, in particular , i need the to pass the model.Id (which is the id of the model of the row), to the action on the Combobox in the template, so i can filter the data correctly
This is the offending line in the grid,
.TemplateName("Client").AdditionalViewData(new { Client = Model })
The result is the Model inside the template is always null, im not sure how to pass the data i need to the template
Is there anyway i can do this, or should i be looking at a different approach?
The way I got around this was to put a JavaScript function in the original view as seen below:
function getClientId() {
var row = $(event.srcElement).closest("tr");
var grid = $(event.srcElement).closest("[data-role=grid]").data("kendoGrid");
var dataItem = grid.dataItem(row);
if (dataItem)
return { clientId: dataItem.Id }
else
return { clientId: null }
}
And reference it from my editor template:
.DataSource(source => source.Read(read => read.Action("GetPlans", "Plans").Data("getClientId"))))
Note : I'm pretty sure you cant run JavaScript from a EditorTemplate so it needed to be housed in the original view.
I know this is a really old question, but for those who are wondering why this doesn't work:
.TemplateName("Client").AdditionalViewData(new { Client = Model })
This code doesn't work because the only data you can pass through this method is static data. You can pass specific strings or numbers, like "Hello World", and that would work fine. For dynamic data with kendo, I've learned that it really depends on the situation, and your solution here works well.
I'm trying to populate a kendo grid within a kendo window in MVC and am unable to find what is wrong. The window is created, and the grid is created within the window... however the DataSource's Read method is never called.
Window:
#{
Html.Kendo().Window()
.Name("DListing")
.Title("Listing")
.Draggable()
.Resizable()
.Width(1000)
.Height(500)
.Visible(true)
.Modal(true)
.Actions(actions => actions
.Maximize()
.Close())
.LoadContentFrom("Dispatch", "Listing", new { Number = #ViewBag.Number })
.Render();}
The Dispatch method in the Listing controller returns back a partial view that contains the grid.
Grid:
#(Html.Kendo().Grid(Model)
.Name("Grid")
.Events(events => events.Change("onChange"))
.HtmlAttributes(new { style = "height:400px;" })
.Columns(columns =>
{
columns.Bound(p => p.Number);
columns.Bound(p => p.DateTime).Format("{0:MM/dd/yyyy hh:mm tt}");
columns.Bound(p => p.Location);
columns.Bound(p => p.Name);
columns.Bound(p => p.Elapsed_Hours);
})
.Groupable()
.Pageable(pageable => pageable
.Numeric(false)
.Input(true)
.PageSizes(new[] { 5, 10, 25 }))
.Sortable()
.Scrollable(scrollable => scrollable
.Virtual(true))
.Filterable()
.Selectable(selectable => selectable
.Mode(GridSelectionMode.Multiple))
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(13)
.Sort(sort => { sort.Add(p => p.DateTime).Descending(); })
.Model(model => { model.Id(p => p.Number); })
.Read(read => read.Action("Listing_Read", "Listing", new { Number = #ViewBag.Number })))
)
Listing_Read Method:
public ActionResult Listing_Read([DataSourceRequest] DataSourceRequest request, int Number)
{
return Json(GetListing(branchNumber).ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
}
Also, it should be noted that I went through and verified that the viewbag data is available for both the window and later on in the grid.
For a little more back info, I initially had the grid on it's own page and it was able to call the read method and populated with the data with no issues. After moving it to populate in the window is when this became a problem.
Monitoring the http requests, the grid never attempts to call the read method (so the request isn't failing). I tried manually refreshing the datasource after the window has loaded thinking that might force the call, but that doesn't call the read method either.
I've been scratching my head on this one for a few hours now trying different things, hoping someone can spot what the problem is :)
Here's what worked for me:
1) View (~/Views/Home/Index.cshtml)
#(Html.Kendo().Window()
.Name("myWindow")
.Title("Title")
.Actions(actions => actions.Pin().Minimize().Maximize().Close())
//.Content(Html.Partial("gridCat").ToHtmlString())
.LoadContentFrom("Load_gridCat", "Home")
)
2) Partial View (~/Views/Shared/gridCat.cshtml)
#(Html.Kendo().Grid<TelerikMvcApp1.Models.Category>()
.Name("CategoriesGrid")
.Columns(columns =>
{
columns.Bound(c => c.CategoryID).Title("Category").Width("10%");
columns.Bound(c => c.CategoryName);
columns.Bound(c => c.Description);
})
.Filterable()
.Pageable()
.Sortable()
.Scrollable()
.DataSource(dataSource => dataSource
.Ajax()
.Model(model => model.Id(p => p.CategoryID))
.Read(r => r.Action("Categories_Read", "Home"))
)
.HtmlAttributes(new { style = "height:250px" })
)
3) Controller (~/Controllers/HomeController.cs)
public ActionResult Load_gridCat()
{
return PartialView("gridCat");
}
public ActionResult Categories_Read([DataSourceRequest]DataSourceRequest request)
{
using (var ctx = new NWindContext())
{
IQueryable<Category> categories = ctx.Categories;
DataSourceResult result = categories.ToDataSourceResult(request);
return Json(result, JsonRequestBehavior.AllowGet);
}
}
I have a Grid with Employes. There is a Edit button and the edit mode is set to Popup. In the EditorTemplate of the entity I want to edit, there is another grid that has a history of Salary with a incell or inline edit mode.
Both grids uses Ajax datasources. The problem is with the inner grid binding. The controller action feeding a Json result to the ajax call requires the ID of the employe we are editing to return the appropriate Salary history. However, Kendo UI ASP.NET MVC wrapper will render some sort of template of the editor before knowing which employee we want to edit, then it will edit it when we are requesting the popup.
How can I feed the Employe ID in the Read Ajax call?
Main Grid
#(Html.Kendo().Grid<MyProject.Business.Models.EmployeDTO>().Name("EmployeGrid")
.ToolBar(toolbar => toolbar.Create())
.Columns(cols =>
{
cols.Bound(o => o.someData).Title("Some Data");
cols.Bound(o => o.moreData).Title("More Data");
cols.Command(o =>
{
o.Edit();
o.Destroy();
}).Title(" ");
})
.Editable(editor => editor
.Mode(GridEditMode.PopUp)
.Window(window => window.Draggable().Resizable().HtmlAttributes(new { #style = "width:700px;" })))
.Sortable()
.Filterable()
.Groupable()
.DataSource(datasource => datasource
.Ajax()
.Model(model => model.Id(o => o.id))
.Read(read => read.Action("GetAll", "EmployesAjax"))
.Update(update => update.Action("Update", "EmployesAjax"))
.Create(create => create.Action("Create", "EmployesAjax"))
.Destroy(destroy => destroy.Action("Destroy", "EmployesAjax"))
)
)
Inner Grid (In Views/Shared/EditorTemplates/EmployeDTO.cshtml)
#Html.Kendo().Grid<MyProject.Business.Models.SalairyDTO>().Name("SalaryGrid")
.Columns(cols =>
{
cols.Bound(o => o.someInfo).Title("Some Info");
})
.DataSource(datasource => datasource
.Ajax()
.Model(model =>
{
model.Id(o => o.id);
model.Field(o => o.employe_id).DefaultValue(Model.id);
})
// NEED THE ID HERE
.Read(read => read.Action("GetByEmployeId", "SalairyAjax", new { id = "" }))
.Update(update => update.Action("Update", "SalairyAjax"))
.Create(create => create.Action("Create", "SalairyAjax"))
.Destroy(destroy => destroy.Action("Destroy", "SalairyAjax"))));
Basically I would suggest you to Set the AutoBind option to false of the inner Grid and use the edit event of the outer Grid to perform a read request and pass the value as additional parameter.
Here is an example:
function onEditOfEmployeGrid(e){
$('#SalaryGrid').data().kendoGrid.dataSource.read({id:e.model.EmployeeID})
}
You could simply pass the value from the grid using addtionaldata parameter within the grid. the RouteID on the (left side) can then be referenced within the Grid Popup Editor using ViewData["RouteID"]. I hope that helps
.Editable(editable => editable.Mode(GridEditMode.PopUp)
.TemplateName("busStop")
.DisplayDeleteConfirmation(true)
.Window(window => window.Modal(true).Resizable().Draggable())
.AdditionalViewData(new { RouteID = Model.RouteID }))