ForeignKey column does not select value in Kendo-Grid - grid

I have a grid with some columns where one of these columns is a foreignKey column.
I want to show all possible values for that column in a combobox. ViewData["States"] is an IList<State> where State has an Id field and a Name field.
To achieve that, I modified the template "GridForeignKey.cshtml" like the following:
#model object
#(
Html.Kendo().ComboBoxFor(m => m)
.BindTo((SelectList)ViewData[ViewData.TemplateInfo.GetFullHtmlFieldName("") +
"_Data"]).Filter(FilterType.Contains).Placeholder("Select...")
)
My View looks like this:
<div class="contentwrapper">
#{
ViewBag.Title = "Home Page";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#(
Html.Kendo().Grid<CustomerModel>()
.Name("Grid")
.Columns(columns => {
columns.Bound(p => p.Name);
columns.ForeignKey(p => p.StateId, (IEnumerable)ViewData["States"], "Id", "Name");
columns.Bound(p => p.StreetAddress).Width(140);
columns.Bound(p => p.Zip).EditorTemplateName("Integer");
columns.Command(command => { command.Edit(); command.Destroy(); });//edit and delete buttons
})
.ToolBar(toolbar => toolbar.Create())//add button
.Editable(editable => editable.Mode(GridEditMode.InLine))//inline edit
.Pageable()
.Sortable()
.Scrollable()
.Filterable()
.DataSource(dataSource => dataSource
.Ajax()
.Events(events => events.Error("error_handler"))
.Model(model => {
model.Id(c => c.CustomerId);
model.Field(c => c.CustomerId).Editable(false);
model.Field(c => c.Zip).DefaultValue(4444);
}
)//id of customer
.Create(update => update.Action("EditingInline_Create", "Customer"))
.Read(read => read.Action("EditingInline_Read", "Customer"))
.Update(update => update.Action("EditingInline_Update", "Customer"))
.Destroy(update => update.Action("EditingInline_Destroy", "Customer"))
)
)
</div>
<script type="text/javascript">
function error_handler(e) {
if (e.errors) {
var message = "Errors:\n";
$.e`enter code here`ach(e.errors, function (key, value) {
if ('errors' in value) {
$.each(value.errors, function () {
message += this + "\n";
});
}
});
alert(message);//show error
}
}
</script>
Now my problems:
My Table does not show the selected value for "State".
When I edit a row, the combobox shows up and has all the desired values in it, but the value is not chosen. Instead it always shows the placeholder-text.
Before I had a complex object bound to my grid which had a field which was a complex type itself (State which contained the Id and Name attributes) but somehow kendo wouldnt let me bind it like p => p.State.Id. That's why I have flattened my model, and I now use the field StateId instead. Is it even possible to use a cascaded complex type like this?

What you have will not work. You need to pass the EditorTemplate the list in the EditorViewData and tell it which EditorTemplateName to use.
columns.ForeignKey(p => p.StateId, (IEnumerable)ViewData["States"], "Id", "Name")
.EditorViewData(new { statesList = ViewData["States"] })
.EditorTemplateName("GridForeignKey");
And GridForeignKey.cshtml like
#model int // Assuming Id is an int
#(Html.Kendo().ComboBoxFor(m => m)
.Placeholder("Select...")
.DataValueField("Id")
.DataTextField("Name")
.BindTo(ViewData["statesList"])
)
This might not be exactly right since I just did it off the top of my head. But it should get you in the right direction at least.

to achieve what you want you need to implement some client side scripts after you define the edit event in the Grid
.Events(events => events.Edit("onEdit"))
if your grid called **myGrid** then your script will be in this way
<script>
$(document).ready(function (e) {
var innerContent = $(".k-grid-delete").html().replace("Delete", "");
$(".k-grid-delete").html(innerContent);
});
function onEdit(e) {
$("#**myGrid** tbody [data-role=dropdownlist]").each(function () {
var ddl = $(this).data("kendoDropDownList");
if (ddl) {
ddl.options.optionLabel = "Select";
ddl.refresh();
ddl.value("");
}
})
}

Related

Kendo Grid datetime filtering

I am using Kendo Grid. The problem I am facing is that I am not able to filter the datetime by selecting any option from filter.
Here is my code:
#(Html.Kendo()
.Grid<IssueViewModel>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(c => c.IssuePostedAt).Format("{0:dd.MM.yyyy hh:mm:ss}").Filterable(filterable => filterable.UI("orderDateFilter")).Title("Posted")
.ClientTemplate("#:kendo.toString(data.IssuePostedAt, \"dd.MM.yyyy hh:mm:ss\")#");
})
.Sortable()
.Pageable(pageable => pageable
.Refresh(true)
.ButtonCount(5))
.Events(events => events.DataBound("onGridDataBound"))
.Filterable(filterable => filterable
.Enabled(true)
.Extra(false)
.Operators(operators => operators.ForString(str => str.Clear().Contains("Содержит")))
)
.DataSource(dataSource => dataSource
.WebApi()
.Model(model => model.Id(i => i.Issue.Id))
.Sort(sort => sort.Add(i => i.IssuePostedAt).Descending())
.Read(read => read.Url("/issue/gridData"))
.PageSize(20)
)
JavaScript:
function orderDateFilter(element) {
element.kendoDateTimePicker({
format: "dd.MM.yyyy hh:mm:ss",
timeFormat: "hh:mm:ss"
});
}
This is code in the controller:
[HttpGet]
[Route("gridData")]
public async Task<ActionResult> GridData([ModelBinder(typeof(DataSourceRequestModelBinder))] DataSourceRequest request)
{
var filterByUser = HttpContext.GetReferrerParam("name");
var gridData = await IssuesRepository.Instance.Get(filterByUser); // get all data from DB
var results = gridData.ToDataSourceResult(request);
return Json(results);
}
DateTime filtering doesn't work at all. gridData.ToDataSourceResult(request); always return empty result.
I will be thankful if anybody could help me out in solving my issue. Thanks in advance.

how to add anchor link column in Kendu UI Grid in the asp.net mvc

I am new in ASP.NET MVC Kendo UI. I am using ASP.NET MVC 5. I wanted to make the Name column as HTML link in the Kendo UI grid. But I am getting an error like "The best overloaded method match for 'Kendo.Mvc.UI.Fluent.GridBoundColumnBuilder.ClientTemplate(string)' has some invalid arguments".
Following is my code.
#(Html.Kendo().Grid<Music.DataAccess.Models.Genre>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(c => c.Name).ClientTemplate(Html.ActionLink(c => c.Name, "Browse", new { genre = c.Name }));
columns.Bound(c => c.Description).Width(190);
})
.HtmlAttributes(new { style = "height: 380px;" })
.Scrollable()
.Groupable()
.Sortable()
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(true)
.ButtonCount(5))
.Filterable()
.DataSource(dataSource => dataSource
.Ajax()
.Read(read => read.Action("Genres_Read", "Store"))
)
)
And here is my Genre Model
public class Genre
{
public int GenreId { get; set; }
[DisplayName("Genre Name")]
public string Name { get; set; }
public string Description { get; set; }
public List<Album> Albums { get; set; }
}
Can anyone help me?
It would be something like this:
#(Html.Kendo().Grid<Music.DataAccess.Models.Genre>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(c => c.Name).ClientTemplate("<a href='" + Url.Action("Browse") + "/?#= Name #'>Edit</a>");
columns.Bound(c => c.Description).Width(190);
})
.HtmlAttributes(new { style = "height: 380px;" })
.Scrollable()
.Groupable()
.Sortable()
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(true)
.ButtonCount(5))
.Filterable()
.DataSource(dataSource => dataSource
.Ajax()
.Read(read => read.Action("Genres_Read", "Store"))
)
)
The client template for the columns either accepts a bunch of javascript as a string or a function.
Personally I prefer to pull out the formatting side of things into a javascript function as it is easier to work with.
So for your example something like this should work:
Grid Column
columns.Bound(c => c.Name).ClientTemplate("#=getActionLink(data.Name)#")
Javascript Function
function getActionLink(data)
{
var link = "#Url.Action("YourActionHere","YourControllerHere")" + "/" + data;
var returntext = "<a href='" + link + "'>" + data + "</a>";
return returntext;
}
Obviously customise on how you need it but this should work for you.

Kendo grid auto-edit, auto-save works but field value reverts in UI

In a Kendo grid (v2013.3) I want to auto-save a row when the user moves to a different row. So I code the change event, which fires when the row selection is changed, to call grid.saveChanges(). Then I re-select the row that we changed to (because the saveChanges seems to have canceled the row selection.) Finally, I call grid.editRow(row) so that the new row will be in edit mode.
This almost works fine. When the user changes a value in a row A, then clicks away to row B, the save action properly occurs and the web app sees the changed value. However, the UI itself reverts to the old value. This occurs because of the call to grid.editRow().
I suspect that Kendo is doing a cancel behind the scenes, even though the changed data is already saved.
Suggestions on how to address this problem? Here's the change handler:
ViLinking.gridItemSelected = function (e) {
var row = ViLinking.getSingleSelectedRow(this);
if (row == null) {
return;
}
var dataItem = this.dataItem(row);
if (dataItem == ViLinking.currentDataItem) {
return;
}
// apparently the row reference does not survive saveChanges() so prepare to re-get it.
ViLinking.currentDataItem = dataItem;
var dataUid = row.attributes["data-uid"];
var table = $(row).closest("table");
ViLinking.setKendoUpdateContentType(this);
this.saveChanges();
row = table.find('tr[data-uid="' + dataUid.value + '"]');
this.select(row);
this.editRow(row);
};
Here's the part of the view that generates the table (it's a child table)
<script id="ViDetailsTemplate" type="text/kendo-tmpl">
#(Html.Kendo().Grid<VendItemProxyForUi>()
.Name("details_#=ItemOid#")
.Columns(cs =>
{
cs.Bound(c => c.ItemOid).Hidden();
cs.Bound(c => c.VendorItemID);
cs.Bound(c => c.IsSplit);
cs.Bound(c => c.VendorItemName);
cs.Bound(c => c.VendorItemPackSize);
cs.Bound(c => c.IsCatchweight);
cs.Bound(c => c.IsApproved);
cs.Bound(c => c.UofMOidForUi).EditorTemplateName("UofmDdTemplate");//.ClientTemplate("#=UofMName#");
cs.Bound(c => c.UofMName);
cs.Command(command =>
{
command.Edit();
command.Destroy();
}).Width(200);
}
)
.Selectable()
.Editable(edit => edit.Mode(GridEditMode.InLine))
.DataSource(ds => ds
.Ajax()
.Model(mdl =>
{
mdl.Id(vi => vi.VendorItemID);
mdl.Field(f => f.VendorItemID).Editable(false);
mdl.Field(f => f.VendorItemName).Editable(false);
mdl.Field(f => f.IsSplit).Editable(false);
mdl.Field(f => f.IsCatchweight).Editable(false);
mdl.Field(f => f.DiscontinueDate).Editable(false);
mdl.Field(f => f.IsRestricted).Editable(false);
mdl.Field(f => f.VendorItemPackSize).Editable(false);
mdl.Field(f => f.IsApproved).Editable(true);
mdl.Field(f => f.UofMName).Editable(true);
}
)
.Read(read => read.Action("GetVisForGi", "ViLinkingWorksheet", new { _msk = Model.MultiSessionKey, itemOid="#=ItemOid#"}))
.Update(update => update.Action("SyncModelFromUi", "ViLinkingWorksheet", new { _msk = Model.MultiSessionKey, itemOid="#=ItemOid#", delete=false}))
.Destroy(update => update.Action("SyncModelFromUi", "ViLinkingWorksheet", new { _msk = Model.MultiSessionKey, itemOid="#=ItemOid#",delete=true}))
)
//.HtmlAttributes(new { style = "height:100px;" })
.Events(ev =>
{
ev.Change("ViLinking.gridItemSelected");
ev.Cancel("ViLinking.saveOnCancel");
})
//.Navigatable()
.ToClientTemplate())
</script>
1- View
#(Html.Kendo().Grid<User>()
.Name("GridName")
.Columns(columns =>
{
...
})
.Editable(editable => editable.Mode(GridEditMode.InCell))
.Pageable(p => p.PageSizes(new[] { 5, 10, 20, 50, 100 }))
.Groupable()
.Sortable()
.Selectable()
.Scrollable(s => s.Height("auto"))
.DataSource(ds => ds
.Ajax()
.Batch(true)
.ServerOperation(false)
.Events(events => events.Error("error_handler"))
.PageSize(20)
.Model(model =>
{
model.Id(a => a.Id);
})
.Read(read => read.Action("Read", "Users"))
.Update(update => update.Action("Update", "Users"))
)
.Events(events => events.Save("SaveChanges"))
)
<script>
function SaveChanges() {
setTimeout(function() {
$("#GridName").data("kendoGrid").dataSource.sync();
});
</script>
2- Controller
public ActionResult Update([DataSourceRequest] DataSourceRequest request, IEnumerable<User> models)
{
if (models != null && ModelState.IsValid)
{
if (models.Any())
{
foreach (var item in models)
{
Update(item); // Find item in database, modify the properties of the object & save change in database
}
}
}
return Json(models.ToDataSourceResult(request, ModelState));
}

Kendo UI grid Create action passes null reference from WCF service

I am struggling calling a create action through a WCF service from a kendo ui grid.When the odataservice calls the business logic controller to write the record it passes a null reference....the customer object is populated up until the call to the business logic CreateEntity method. I originally thought this was because of the content type but I am having my doubts now. Accessing the WCF service directly with fiddler successfully creates the record...
Kendo Grid:
Here is the application level Customer_Create action being called by the kendo grid
#(Html.Kendo().Grid<Application.ServiceProxy.CustomerDTO>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(c => c.salesOrganizationID).Width(15).Title("sales org");
columns.Bound(c => c.customerID).Width(20).Groupable(false);
columns.Bound(c => c.name1).Width(25).Title("name");
columns.Bound(c => c.city).Width(15).Title("city");
columns.Bound(c => c.stateCode).Width(10).Title("state");
columns.Bound(c => c.countryCode).Width(15).Title("country");
columns.Bound(c => c.matchcode).Width(25).Title("matchcode");
columns.Command(command => { command.Edit(); command.Destroy(); }).Width(35);
//Add program type here CMI, VMI etc..
//columns.Width(25).Title("program");
})
.ToolBar(toolbar => toolbar.Create())
.Editable(ed => ed.Mode(GridEditMode.PopUp).Window(w => w.Title("Edit Customer Details").Name("editWindow").HtmlAttributes(new { #style = "width:700px;" })))
.Pageable()
.Sortable()
.Groupable()
.Scrollable()
.Filterable()
.HtmlAttributes(new { style = "height:420px;" })
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.ServerOperation(true)
.Events(events => events.Error("error_handler"))
.Model(model => model.Id(c => c.customerID))
.Create(update => update.Action("Customer_Create", "Customer"))
.Read(read => read.Action("Customer_Read", "Customer"))
.Update(update => update.Action("Customer_Update", "Customer"))
.Destroy(update => update.Action("Customer_Delete", "Customer"))
)
)
Here is the application level Customer_Create action being called by the kendo grid
[System.Web.Http.HttpPost]
public ActionResult Customer_Create([DataSourceRequest] DataSourceRequest request, Application.ServiceProxy.CustomerDTO customer)
{
if (customer != null && ModelState.IsValid)
{
var odataService = new Container(new Uri("http://localhost:8089/odata/"));
//odataService.r
odataService.AddToCustomer(customer);
odataService.SaveChanges();
return Json(ModelState.ToDataSourceResult());
}
return View("Index");
}
Here is the CreateEntity method being called through the generated WCF data service.
protected override CustomerDTO CreateEntity(CustomerDTO customerDTO)
{
var customer = new customer()
{
matchcode = customerDTO.matchcode,
salesOrganizationID = customerDTO.salesOrganizationID,
statusID = customerDTO.statusID,
serviceLevelStatusID = customerDTO.serviceLevelStatusID,
mediaIDLogo = customerDTO.mediaIDLogo,
systemID = customerDTO.systemID,
customerExternalSystemID = customerDTO.customerExternalSystemID,
internationalGroup = customerDTO.internationalGroup,
division = customerDTO.division,
corporateID = customerDTO.corporateID,
inventoryManagerID = customerDTO.inventoryManagerID,
dunsNumber = customerDTO.dunsNumber
};
entity.customer.Add(customer);
entity.SaveChanges();
return GetEntityByKey(customer.customerID);
}

KendoGrid - MVC - Entity - Identity column

I am building an MVC, Entities application with KendoGrids.
I have build this kendoGrid
#(Html.Kendo().Grid<ModelApp.Models.Tickets>()
.Name("ticketgrid")
.Columns(columns =>
{
columns.Bound(p => p.TicketID).Title("ID");
columns.ForeignKey(p => p.CustomerID, (System.Collections.IEnumerable)ViewData["customers"], "CustomerID", "CustomerName").Title("Customer");
columns.ForeignKey(p => p.AreaOfBusinessID, (System.Collections.IEnumerable)ViewData["areaofbusinesses"], "AreaOfBusinessID", "AreaOfBusiness1").Title("AreaOfBusiness");
columns.Bound(p => p.OccurredOn).Title("Occured").Format("{0:yyyy-MM-dd}");
columns.ForeignKey(p => p.SeverityID, (System.Collections.IEnumerable)ViewData["severities"], "SeverityID", "Severity1").Title("Severity");
columns.ForeignKey(p => p.AssigneeID, (System.Collections.IEnumerable)ViewData["assignees"], "AssigneeID", "AssigneeName").Title("Assignee");
columns.ForeignKey(p => p.TicketStatusID, (System.Collections.IEnumerable)ViewData["ticketstatuses"], "TicketStatusID", "TicketStatus1").Title("Status");
columns.Bound(p => p.UserID).Title("User");
columns.Bound(p => p.DateRegistered).Title("Registered").Format("{0:yyyy-MM-dd}");
})
.DataSource(dataSource =>
dataSource
.Ajax()
.Model(model => model.Id(p => p.TicketID))
.Read(read => read.Action("Index","Ticket"))
.Create(create => create.Action("Create", "Ticket"))
.Update(update => update.Action("Edit", "Ticket"))
//.Destroy(destroy => destroy.Action("Delete", "Ticket"))
)
.Pageable()
.Editable(editing => editing.Mode(GridEditMode.InCell))
.ToolBar(toolbar =>
{
toolbar.Create();
toolbar.Save();
})
.Navigatable()
.Selectable()
)
and I am facing 2 problems
1)The TicketID column is an identity column. When I select the Create button it fetches a zero. How can I make the Gid understand that it should not mess with this column and that the database will handle it?
Of course, no insert is being made anyway which takes me to the second question
2)The Edit does not post to database
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit([DataSourceRequest] DataSourceRequest request, IEnumerable<ModelApp.Models.Tickets> models)
{
if (models != null)
{
try
{
foreach (var updatedEntity in models)
{
var itemToUpdate = db.Tickets.Where(p => p.TicketID == updatedEntity.TicketID).FirstOrDefault();
if (itemToUpdate != null)
{
itemToUpdate.CustomerID = updatedEntity.CustomerID;
itemToUpdate.AreaOfBusinessID = updatedEntity.AreaOfBusinessID;
itemToUpdate.AssigneeID = updatedEntity.AssigneeID;
itemToUpdate.OccurredOn = updatedEntity.OccurredOn;
itemToUpdate.SeverityID = updatedEntity.SeverityID;
itemToUpdate.DateRegistered = updatedEntity.DateRegistered;
itemToUpdate.UserID = updatedEntity.UserID;
db.SaveChanges();
ModelState.Clear();
}
}
}
catch (Exception e)
{
db.add_exception_log(e.Message, "UPDATE RATES");
}
}
return Json(ModelState.ToDataSourceResult());
}
because models is null. Any clues why?
Thanx in advance
1) You should make the field non-editable inside of the Model configurator of the dataSource
model=>{
model.Fiedl(p=>p.TicketID).Editable(false);
}
2) You are not using batch editing to expect collection - change the signate to expect single record
public ActionResult Edit([DataSourceRequest] DataSourceRequest request, ModelApp.Models.Tickets model)

Resources