Kendo grid and mvc editor templates - kendo-ui

I have an mvc editor template (named ExpenseTypeEdit) defined like this:
#model ExpenseType
#(Html.Kendo().DropDownListFor(et => et.ExpenseTypeId)
.OptionLabel("--Please Select--")
.DataTextField("Description")
.DataValueField("ExpenseTypeId")
.DataSource(datasource => datasource
.Read("GetExpenseTypeList", "Lookup", new { area = "" })
)
.HtmlAttributes(new { width = "98%" })
)
I have a kendo grid that looks something like this:
#(Html.Kendo().Grid<ExpenseViewModel>()
.Name("ExpenseGrid")
.Editable(editable => editable.Mode(GridEditMode.InLine))
.Columns(columns =>
{
columns.Bound(e => e.ExpenseType)
.EditorTemplateName("ExpenseTypeEdit");
columns.Command(command =>
{
command.Custom("SaveExpense").Click("SaveExpense_click").Text("Save");
}
);
})
.DataSource(datasource => datasource.Ajax()
.ServerOperation(false)
.Model(model =>
{
model.Id(i => i.ExpenseId);
model.Field(f => f.ExpenseType)
.DefaultValue(new Solutions.Business.Entities.PrimitiveObjects.ExpenseType { ExpenseTypeId = 0, Description = "" });
})
)
)
The function SaveExpense_click looks like this:
function SaveExpense_click(e) {
var item = this.dataItem($(e.currentTarget).closest("tr"));
/*
Variable 'item' looks like like:
{
ExpenseType: {
ExpenseTypeId: 4,
Description: ""
}
}
*/
//debugger;
};
The ExpenseTypeId is present but not the description. Why is item not picking up the Description from the drop down and what do I need to do to get it passed in?

You can't get the Description of a DDL server side, you can only get the value. You can either get the value then retrieve the text from the DB or you can use the combo box control and then you will be able to get both value and text.
Just noticed your tryign to get it client side, if thats the case.
$("#ExpenseTypeId").text() should work, as per your example item.text() might work

Related

Need to pass model value on Read action on DropDownFor in a popup editor template

I have a Telerik grid (MVC) configured with a popup editor on the grid rows. In the editor template, I have a DropDownFor list in addition to textboxes displaying the grid row values. This all works.
The DropDownFor has a Read action and I need to pass the model value to the controller to set the selected value. The model value is not recognized.
Here is the DropDownFor:
#(Html.Kendo().DropDownListFor(m => m.OuterDiameter)
.Name("OuterDiameter")
.DataValueField("Text")
.DataTextField("Value")
.DataSource(ds =>
{
ds.Read(read =>
{
read.Action("GetPipeOD", "Materials", new { od = m.OuterDiameter });
});
})
.HtmlAttributes(new { style="width:100px"})
)
You can pass adicional parameter using a JavaScript funcion.
#(Html.Kendo().DropDownListFor(m => m.OuterDiameter)
.Name("OuterDiameter")
.DataValueField("Text")
.DataTextField("Value")
.DataSource(ds =>
{
ds.Read(read =>
{
read.Action("GetPipeOD", "Materials").Data("getParameter");
});
})
.HtmlAttributes(new { style="width:100px"})
)
<script>
function getParameter() {
return od: '#Model.Parameter'
//Or what do you need...
}
</script>

binding a collection/list to a kendo mvc grid column

I am trying to bind a list of comments to a column, but it doesn't display anything. I am using an inline Client Template to quickly test it, but no luck. I know for sure there are Comments in the model, but it seems to think that the Comments is undefined or null. Below is my code:
#{
var grid = Html.Kendo().Grid(Model)
.Name("grid")
.Columns(columns =>
{
columns.Bound(l => l.Name);
columns.Bound(l => l.Description);
columns.Bound(l => l.Comments).ClientTemplate("# if(Comments) { for(var i=0; i<Comments.length; i++) {# #=Comments[i].Comment# #}}# ").Title("Comments");
})
.HtmlAttributes(new { style = "height: 850px;" })
.Sortable()
.Scrollable(scr => scr.Height(430))
.Filterable()
.DataSource(dataSource => dataSource
.Ajax()
.ServerOperation(false)
);
grid.Render();
}
I suggest creating a JavaScript function and calling it in your client template. Also, it will be easier to debug.
function displayComments(data) {
return $.map(data.Comments, function (e) { return e.Comment; }).join(", ");
}
In your Grid:
columns.Bound(l => l.Comments).ClientTemplate("#= displayComments(data) #").Title("Comments");

Setting options of a Kendo Grid that is inside an Editor Template

Inside the editor template of one of my Grids, A, I have another grid, B. I want to set read and update actions of this Grid based on the current Id in the A.
I've tried using Razor code inside the editor template like this:
// details grid: B
.Read("action", "controller", new { #Model.Id })
But Id was always null, probably because Razor is server-side.
So I've tried to set the Grid inside the main page, in the Edit event of the main Grid.
function EditHandler(e) {
if (e.model.isNew())
return;
var detailGrid = e.container.find("#details").data('kendoGrid');
detailGrid.dataSource.options.transport.read.url = "#Url.Action("", "")".concat('/', e.model.Id);
detailGrid.dataSource.options.transport.update.url = "#Url.Action("", "")".concat("/", e.model.Name);
}
This doesn't work neither. The definition of the Grid in the editor template will overwrite these properties.
This is the main Grid:
#(Html.Kendo().Grid<A>()
.Name("A")
.Columns(columns =>
{
columns.Bound(x => x.Id).Hidden();
columns.Bound(x => x.Name).HtmlAttributes(new { #style = "text-align: left" });
....
columns.Command(command =>
{
command.Edit(); command.Destroy();
});
})
.....
.Selectable()
.Navigatable()
.DataSource(ds => ds
.Ajax()
.Model(model =>
{
model.Id(x => x.Name);
})
.Read("", "")
.Update("", "")
.Destroy("", "")
.Create("", "")
)
.Events(e => e.Edit("EditHandler").Save("SaveHandler"))
)
Inside the editor template of this class, a.cshtml, I have another Grid that I want its Edit and Read Actions include the Id of the Grid A.
#(Html.Kendo().Grid<B>()
.Name("B")
.Columns(columns =>
{
columns.Bound(.....
})
.....
.Editable(edit => edit.Mode(GridEditMode.InCell))
.Selectable()
.Navigatable()
.DataSource(ds => ds
.Ajax()
.PageSize(5)
.Model(model =>
{
model.Id(x => x.Id);
})
.Read("", "")
.Update("", "")
).ToClientTemplate()
)
UPDATE
function EditHandler(e) {
if (e.model.isNew())
return;
var detailGrid = e.container.find("#details").data('kendoGrid');
detailGrid.dataSource.read({ Id: e.model.Id });
detailGrid.dataSource.update({ Name: e.model.Name });
}
As Dion noted, it needs 2 changes:
In the child Grid, B, set the auto bind to false: .AutoBind(false)
Set the ID with read method, not manually as I've been trying.
To overcome this case, I will trigger Grid-B's read manually inside Grid-A's edit event. Follow this setup:
Grid-B Config:
.AutoBind(false)
.DataSource(ds => ds.Ajax()
.Read("action", "controller")
.Update(url => url.Action("update", "controller").Data(paramData)))
Modify Grid-A edit function:
function EditHandler(e) {
var gridB = $("#gridB").getKendoGrid(),
model = e.model;
gridB.dataSource.read({Id: model.Id});
}
// get Id for update
function paramData() {
return { Id : $("#Id").val(); };
}
Hope this help.
Note: Unlike read, update will be triggered after popup shown then Id field will be already have its value. Therefor you can use Url.Action(...).Data() for this case.

How can I set default value for a foreign key colum in Kendo Grid?

In the Kendo Grid there is a foreign key column, and I retrieve the select list from ViewData. Grid's edit mode is InLine.
When I want to add a new record, the first item is selected. If I don't change it and don't select anything else, column's value will be null on the server side.
How can I specify a default value for this column? Please note that ID's are user-generated and I'm not able to guess which Id will the first Item.
This is the Grid:
#(Html.Kendo().Grid<InvtMat>()
.Name("BOM")
.Columns(columns =>
{
columns.ForeignKey(x => x.CGoodCode, (IEnumerable)ViewData["Goods"], "Id", "Text");
// removed for brevity
columns.Command(command => { command.Edit(); command.Destroy(); });
})
.ToolBar(toolbar =>
{
toolbar.Create();
})
.Editable(edit => edit.Mode(GridEditMode.InLine))
.DataSource(ds =>
ds.Ajax()
.Model(model =>
{
model.Id(x => x.CGoodCode);
model.Id(x => x.CGoodCode1);
})
)
)
You can set default value for Grid's model inside DataSource.Model section.
Here is an example:
.DataSource(ds =>
ds.Ajax()
.Model(model =>
{
model.Id(x => x.CGoodCode);
model.Field(x => x.CGoodCode).DefaultValue(0);
})
)
Because you don't know what default value you must write there, then you should find it first before you define the Grid. I suppose you have something like this in your controller:
var goods = // get goods from DB.
var goodsDV= goods.First().Id;
ViewData["Goods"] = goods;
ViewData["GoodsDefaultValue"] = goodsDV;
Or you could also perform this in razor view
#{
var firstGood = ((IEnumerable<Good>)ViewData["Goods"]).First();
ViewData["GoodsDefaultValue"] = firstGood.Id;
}
Then use it like this
model.Field(x => x.CGoodCode).DefaultValue(ViewData["GoodsDefaultValue"]);
Easy right?!

MVC3 Telerik Grid - How to submit all rows to controller?

By default it looks like Telerik Grid for MVC3 submits only the rows marked as "dirty" to my controller. I need to be able to submit all rows on a Telerik Grid to my controller. In other words I think I need to mark all rows as changed so the grid will send all rows to my controller.
I am using Ajax data binding as in:
.DataBinding(dataBinding => dataBinding
.Ajax()
.Select("GetData", "ModuleAccess", new { roleId = #ViewBag.RoleId, appId = #ViewBag.AppId })
.Update("SaveBatchEditing", "ModuleAccess")
#(Html.Telerik().Grid<BarcodeListModel>()
.Name("orders-grid")
.ClientEvents(events => events.OnDataBinding("onDataBinding"))
.DataKeys(keys =>
{
keys.Add(x => x.Id);
})
.ToolBar(commands =>
{
commands.SubmitChanges();
})
.DataBinding(dataBinding =>
dataBinding.Ajax()
.Select("BulkEditSelect", "ProductVariant")
.Update("BulkEditSaveBarcode", "ProductVariant")
.Delete("DeleteBarcode", "ProductVariant")
)
.Columns(columns =>
{
columns.Bound(x => x.Id).ReadOnly();
columns.Bound(x => x.SKU);
columns.Bound(x => x.barcode);
//columns.Bound(x => x.Id)
// .Template(x => Html.ActionLink(T("Admin.Common.View").Text, "DeleteBarcode", new { id = x.Id }))
// .ClientTemplate("" + "Delete" + "")
// .Width(50)
// .Centered()
// .HeaderTemplate("DeleteBarcode")
// .Filterable(false)
// .Title("Delete");
columns.Command(commands => commands.Delete()).Width(180);
})
.Pageable(settings => settings.PageSize(gridPageSize).Position(GridPagerPosition.Both))
.DataBinding(dataBinding => dataBinding.Ajax().Select("BarcodeList", "ProductVariant", Model))
.Editable(editing => editing.Mode(GridEditMode.InCell))
.EnableCustomBinding(true)
)
use like this code
I found the answer:
function ModuleAccessGridHasChanges() {
var grid = $("#ModuleAccessGrid").data("tGrid");
if (grid != null) {
var additionalValues = grid.data;
if (!$.telerik.trigger(grid.element, 'submitChanges', { values: additionalValues })) {
grid.sendValues($.extend({}, additionalValues), 'updateUrl', 'submitChanges');
}
}
}
Fiddler shows all the data for the grid coming accross:

Resources