The set-up:
ASP MVC project
Kendo Grid in a view via Razor
Column custom command, calls...
JavaScript that opens Kendo window with refresh() URL to partial view as custom form
The form has an input type=button calling JavaScript
The barrier:
How to update the row (dataItem?) of Grid with new model (from window/form javascript). I am unable to get a handle to target dataItem. Select() is not applicable here because the row is not selected. Instead, a custom button event opens modal Grid Window having the fields and commands for update, close, etc..
I could use the native Edit of Grid, but what I am trying to accomplish is a way to have complete customization of a pop up window showing partial view that can be used to present CRUD actions.
BTW: Rationale for this is to optimize space in a grid row that would normally be consumed with unnecessary buttons for Editing, and Deleting, layed down by use of the Kendo native control properties. I feel this is better presented in a separate, details view, like a Model Grid Window, in my case.
Again, not using Select(), I am unable to understand how to get a handle, within the Window/form JavaScript, to the Grid row that it was called from, for purposes of updating the row with new model data.
Thanks for your time.
Using your method you are doing double request so my suggesting:
On edit open a window binded to row via MVVM :
function edit(e) {
//get the row which belongs to clicked edit button
var item = this.dataItem($(e.currentTarget).closest("tr"));
//bind the window to the item via mvvm http://docs.telerik.com/kendo-ui/framework/mvvm/overview
kendo.bind($("#window"), item);
}
The window contain an editor template (Shared/EditorTemplates/Client.cshtml) :
#(Html.Kendo().Window().Name("window")
.Title("Client Details")
.Visible(false)
.Modal(true)
.Draggable(true)
.Width(400)
.Content(#<text>
#Html.Partial("EditorTemplates/Client", new Product())
</text>))
//Put in every element in the window data-bind="value:INPUT NAME"
//<input name="price" /> become <input name="price" data-bind="value: price" />
$("#window [name]").each(function () {
var name = $(this).attr("name")
$(this).attr("data-bind", "value:" + name );
});
The editor template :
#model Product
#Html.TextBoxFor(m => m.Name)
This demo shows how to get reference of the dataItem bound to the column where the custom command key is pressed, and shows the respective info in a Window. You can use the dataItem to update the Grid as well:
http://demos.telerik.com/kendo-ui/grid/custom-command
Here is an example as well:
http://dojo.telerik.com/abUHI
Take a look at the showDetails function
My discoveries since posting this...
I'm new with web presentation development, therefore grasping the distinction of client vs. server side elements and scope of such was key point. As well, learning the various specifics of the Kendo Grid was also helpful.
Continuing on with my present solution...
Getting a handle on the row item selected from custom command event not done with Select() because row is not being selected. As previously stated in other posts, this was only a part of the needed work. In the custom command event handler JavaScript (seen again in full solution below):
var detailDataItem = this.dataItem($(e.target).closest("tr"));
MY SOLUTION:
In the parent window that hosts the Kendo Grid:
#* Declare modal Kendo Grid window control *#
#helper ClientGrid()
{
#(Html.Kendo().Grid<Purevision.Models.Person>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(c => c.FirstName).Width(100);
columns.Bound(c => c.LastName).Width(130);
columns.Bound(c => c.Email).Width(140);
columns.Bound(c => c.Phone).ClientTemplate("#= (data.Phone) ? formatPhoneNumber(data.Phone) : 'none' #").Width(130);
columns.Bound(c => c.Comments).Hidden().Width(140);
columns.Bound(c => c.UserId).Hidden();
columns.Bound(c => c.Id).Hidden();
columns.Command(command =>
{
command.Custom("Archive").Click("archiveCommand");
command.Custom("Detail").Click("detailCommand");
}).Width(90);
})
.ToolBar(toolbar => toolbar.Create())
.Selectable(s => s.Mode(GridSelectionMode.Single))
.Events(e => e.Change("onChange").DataBound("onDataBound").DataBinding("onDataBinding"))
.Scrollable()
.Sortable()
.Editable(editable => editable.Mode(GridEditMode.PopUp).TemplateName("Edit"))
.Pageable(pageable => pageable
.Refresh(true)
.PageSizes(true)
.ButtonCount(5))
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(20)
.Events(events => events.Error("error_handler"))
.Model(model => model.Id(c => c.Id))
.Create(create => create.Action("People_Create", "Clients"))
.Read(read => read.Action("People_Read", "Clients"))
.Update(update => update.Action("People_Update", "Clients"))
.Destroy(update => update.Action("People_Destroy", "Clients"))
)
)
}
#* Declare modal Kendo Grid window control; MUST be named 'detailWindow' as referenced by partial view script *#
#(Html.Kendo().Window().Name("detailWindow")
.Title("Client Details")
.Visible(false)
.Modal(true)
.Draggable(true)
.Width(400)
.Content(#<text>
#Html.Partial("_edit", new Person())
</text>
)
<script type="text/javascript">
function detailCommand(e) {
var window = $("#detailWindow");
var kWnd = window.data("kendoWindow");
var data = this.dataItem($(e.target).closest("tr"));
e.preventDefault();
kendo.bind(window, data);
kWnd.center().open();
}
</script>
In the partial view _edit.cshtml being presented in Kendo modal window:
<div class="form-group">
#Html.LabelFor(model => model.FirstName, htmlAttributes: new { #class = "control-label col-md-3" })
<div class="col-md-4">
#Html.EditorFor(model => model.FirstName)
#Html.ValidationMessageFor(model => model.FirstName)
</div>
</div>
<input type="button" id="updateButton" value="Update2" class="btn btn-default" />
Wire up button event during form ready, which gets a handle to the grid control still in scope on the client-side:
<script type="text/javascript">
// as mentioned by Tarek, bind each control's value attribute
$("#detailWindow [name]").each(function () {
var name = $(this).attr("name");
$(this).attr("data-bind", "value:" + name );
});
$(document).ready(function (e) {
var window = $("#detailWindow");
var grid = $("#grid").data("kendoGrid");
$("#updateButton").click(function (e) {
grid.saveChanges();
window.data("kendoWindow").close();
});
});
</script>
I'm open to refactoring suggestions here. It seems like lots of client-side coding in JavaScript to accomplish custom activity against the Kendo Grid. (sigh) I am happy to have the versatility though. (smile)
It took much re-editing to hopefully get this answer to something useful. Let me know. ;)
REFERENCES:
Telerik Forums / Kendo UI Forum / Grid / How does Grid update its dataSource?
Related
I'm working with a Kendo-UI grid for asp.net MVC (version 2022.2.621.545) and I added multi-checkbox filtering to the columns. The grid items are pulled from the server using a configured ajax call to a controller action, and clicking on a filter button triggers another call to retrieve the full set of items in order to build the checkbox list. In some cases there are too many items returned and the grid appears to hang trying to determine the unique items for the checkbox list.
I was wondering if lazy loading can be configured for multi-checkbox filtering such that paging info is sent to the data source controller action. Alternatively, I've read that there may be a way to hold off on retrieving items for the filter until a minimal search string has been entered, with the search string being sent to the data source controller action.
I've looked at Kendo-UI documentation for multi-checkbox filtering options, but nothing has been abundantly clear that what I need to do is possible, especially within the asp.net MVC directives. I'm hoping someone can provide some guidance as to how to modify my grid setup to configure additional control for retrieving filter options. This is my current working code:
<div style="height:690px" id="warehouseGrid">
#(Html.Kendo().Grid<WarehouseModel>()
.Name("inventoryGrid")
.HtmlAttributes(new { style = "height:100%; width: 100%;" })
.Columns(columns =>
{
columns.Bound("InventoryLineItemID").Title("").Width(35).Filterable(false).ClientTemplate(
"<img src='https://cdn.host/show_detail.png' class='k-icon k-delete' height='45' width='45' onclick='ShowInventoryItemDetails(\"#= InventoryLineItemID #\")' onmouseover='' style='cursor: pointer;' title='Show Inventory Item Details' alt='Show Inventory Item Details' />"
);
foreach (WarehouseField col in fields)
{
if (!string.IsNullOrEmpty(col.Template))
{
columns.Bound(col.PropertyName).Title(col.Title).Width(col.Width).Filterable(false).ClientTemplate(col.Template);
}
else
{
columns.Bound(col.PropertyName).Title(col.Title).Width(col.Width).Filterable(ftb => ftb.Multi(true).Search(true));
}
}
})
.Pageable(pager => pager.PageSizes(new[] { 10, 20, 50, 100 }))
.Excel(excel => excel
.AllPages(true)
)
.ToolBar(
toolbar =>
{
toolbar.Template(#<text>
#ToolbarTemplate()
</text>);
}
)
.Events(e => e.DataBinding(#<text>function(e) { onDataBinding(this) }</text>))
.Events(e => e.DataBound(#<text>function(e) { onDataBound(this) }</text>))
.Resizable(r => r.Columns(true))
.ColumnResizeHandleWidth(5)
.Scrollable()
.Sortable()
.Filterable()
.DataSource(dataSource => dataSource
.Ajax()
.PageSize(100)
.Read(read => read.Action("GetInventory", "Warehouse", new { area = "Rest" }).Data("additionalData"))
)
)
</div>
I have been using kendo grid for asp.net MVC.
Two problems I am facing
1 - While displaying create view for users, I have set an autofocus attribute to first text box. When using without kendo, autofocus works fine and gets injected in Dom. But when using kendo and editortemplate, I can't see autofocus attribute being inserted.
2 - Also in kendo grid Ajax editing, I am unable see bootstrap style to text box when clicking on Edit link button.
Following are the codes
KENDO GRID IN INDEX VIEW
#(Html.Kendo().Grid(Model)
.Name("Grid")
.Columns(columns =>
{
columns.Bound(u => u.USERNAME);
columns.Bound(u => u.PASSWORD);
columns.Bound(u => u.ROLE);
columns.Bound(u => u.STATUS);
columns.Command(command => { command.Edit(); command.Destroy(); }).Width(250);
}
)
.Pageable()
.DataSource(datasource => datasource
.Ajax()
.Model(model => model.Id(u => u.ID))
.Update(update => update.Action("Edit", "Users"))
.Destroy(destroy => destroy.Action("Delete", "Users"))
)
)
CREATE VIEW USERNAME SNIPPET FOR USER WHERE 1st PROBLEM I AM FACING
<div class="form-group">
#Html.LabelFor(model => model.USERNAME, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(model => model.USERNAME, new { #autofocus = "autofocus", #class = "form-control" } )
#Html.ValidationMessageFor(model => model.USERNAME, "", new { #class = "text-danger" })
</div>
</div>
You can see I have put autofocus in Create view but I am unable to see focus on page load when using Kendo. If I remove Kendo and EditorTemplate, autofocus works fine.
I have added code and some more details. Please have a look.Basically two problems I am facing, If I use kendo, I cant get autofocus for USERNAME textbox in Create.cshtml. Second in Kendo Grid Edit, I am unable to see bootstrap class applied to textboxes in edit mode unless I apply EditorTemplate in the folder. If I apply editortemplate, I cant get autofocus working on create.cshtml.
For your first problem, the autofocus attribute identifies the input that should have focus when the page loads. But the kendo grid editor popup is dynamically added to the page when the user clicks the edit button on a row. So you should manually set the focus using javascript code on grid edit event. So, in your grid settings:
.Events(events => events.Edit("gridEdit"))
And this is the code that I usually put in my gridEdit event handler:
function gridEdit(e) {
// get the handle of the edit window
var wnd = e.container.data("kendoWindow");
// set focus to the first input
wnd.bind('activate', function () {
e.container.find(':input:visible:enabled:first').focus();
});
}
We need to set the focus on edit-window activation, when the inner elements are ready. My code sets the focus to the first, enabled, visible input element, but your logic might be different.
Your second question is not clear to me, but maybe you should ask a new question for that, and please include more details, like a snapshot image of the problem.
My first problem is : I use kendo grid with Single Select mode and I need when view loaded for the first time, the first row is selected, in other words, i want to select the first kendo grid row programatically.
moreover other problem is i insert radiobutton column in that grid , and i want synchronize
radiobutton select with row select , in other words, i want that when user select row,it causes it's radiobutton Selected
Please help me
tnx
this is the code:
#(Html.Kendo().Grid<CommonData.Domain.LegalEntityPhone>()
.Name("SMSGrid")
.HtmlAttributes(new { style = "width:800px;" })
.Selectable(selectable =>
selectable.Mode(GridSelectionMode.Single).Type(GridSelectionType.Row))
.Columns(columns =>
{
columns.Bound(c => c.Id)
.Title(" ")
.ClientTemplate(" <input type='radio' id='Approve' name='chkApprove' />");
columns.Bound(c => c.Number)
.Title("Destination")
.HeaderHtmlAttributes(new { style = "text-align: center;" })
.HtmlAttributes(new { style = "text-align: center; });
columns.Bound(c => c.CityCode)
.Title("City Code")
.Width(30)
.HeaderHtmlAttributes(new { style = "text-align: center" })
.HtmlAttributes(new { style = "text-align:center;width:30px" });
columns.Command(command => { command.Edit(); }).Width(150);
})
.Editable(editable => editable.Mode(GridEditMode.InLine))
.Events(events => events.Change("OnChange"))
.DataSource(dataSource => dataSource
.Ajax()
.Model(model =>
{
model.Id(p => p.Id);
model.Field(p => p.Id).Editable(false);
})
.Read(read => read.Action("LegalEntityPhoneInfo_Read", "Message"))
.Update(update => update.Action("LegalEntityPhoneInfo_Update", "Message"))
)
)
There is no such thing as making the row selected in the controller because the Grid is all created on the client. You can use the dataBound event to make the first row selected.
e.g.
$(function(){
$('#GridName').data().kendoGrid.bind('dataBound',function(e){
this.select(this.tbody.find('>tr:first'));
})
})
Or use one instead of bind to make the row selected only when the page is loaded, not each time when the Grid is rebound - sort,filter, etc. Check documentation for more info.
If you are unfamiliar with jQuery, I highly recommend you take an online free tutorial from http://jqueryair.com/.
Assuming your project is referencing the jQuery script in your _Layout page, all you should have to do is add an Event handler for Databound to the grid:
.Events(events => events.DataBound("Grid_Databound"))
Then just paste this script onto the page:
<script>
function Grid_Databound() {
var grid = $("#MyGridName").data("kendoGrid");
row = grid.tbody.find(">tr:not(.k-grouping-row)").eq(0);
grid.select(row);
}
</script>
I'm sure the same script that zeinad added would work as well, always more than one way to skin a cat. As far as making the radio button show selected if the row is selected, I think if you watched the tutorial I mentioned, you should be able to figure it out. Post back if you need more help.
I have a view containing a Telerik grid:
Index.cshtml
#(Html.Telerik().Grid(Model)
.Name("Grid")
.DataKeys(keys => keys.Add(c => c.CustomerID))
.ToolBar(toolBar => toolBar.Template(
#<text>
<button id="feedback-open-button" title="Add Customer" class="t-button t-state-default">Add</button>
</text>))
.Columns(columns =>
{
columns.AutoGenerate(column =>
{
//customize autogenereted column's settings
column.Width = "150px";
if (column.Member == "CustomerID")
column.Visible = false;
});
columns.Command(commands => commands
.Custom("editCustomer")
.Text("Edit")
.DataRouteValues(route => route.Add(o => o.CustomerID).RouteKey("CustomerID"))
.Ajax(true)
.Action("EditCustomer", "Grid"))
.HtmlAttributes(new { style = "text-align: center" })
.Width(150);
})
)
I want to add/edit records to this grid using a popup. I have used a Telerik Window, in which I have opened another view as Partial View to add/edit records. This is the code for the window and how I am opening it as a popup for "ADD functionality".
Index.cshtml
#{ Html.Telerik().Window()
.Name("Window")
.Title("Add / Edit Customer")
.Content(#<text>
#Html.Partial("AddEditCustomer", new Customer());
</text>)
.Width(400)
.Draggable(true)
.Modal(true)
.Visible(false)
.Render();
}
#{ Html.Telerik().ScriptRegistrar()
.OnDocumentReady(#<text>
// open the initially hidden window when the button is clicked
$('#feedback-open-button')
.click(function(e) {
e.preventDefault();
$('#Window').data('tWindow').center().open();
});
</text>);
}
I have tried to use the same window for edit. But I am having problem in passing the customer object to the partial view within the window.
CustomerController.cs
public JsonResult EditCustomer(int CustomerID)
{
var model = CustomerModel._CustomerCollection.FirstOrDefault(o => o.CustomerID == CustomerID);
return Json(new { customer = model });
}
Index.cshtml
<script type="text/javascript">
function onComplete(e) {
if (e.name == "editCustomer") {
var detailWindow = $("#Window").data("tWindow");
var customer = e.response.customer;
detailWindow.center().open();
}
}
</script>
How can I pass this "customer" object to the partial view inside the popup window?
The way we deal with this where I work is by creating an empty div in the Telerik window. The "edit" link is an AJAX link which uses the window's div as its target. The link calls the controller method of your choice, and from there rather than returning Json, just return the PartialView you want displayed. The benefit of this approach is you use the customer object just like you would for any normal view/partial.
After the AJAX completes, open the Telerik window and the content should be there.
I have a Telerik Extensions for ASP .Net MVC grid on my web page and, even though I've added the "Selectable" method to it, the OnRowSelect event is not getting triggered. It seems that the grid is not even responding to the "Selectable" method since my mouse pointer does not change to the hand when I'm hovering over the grid.
Here is the grid declaration:
<% Html.Telerik().Grid(Model.Students)
.Name("Students")
.DataKeys(keys =>
keys.Add(s => s.Id)
)
.Columns(columns =>
{
columns.Bound(s => s.CourseScore).ReadOnly();
columns.Bound(s => s.StudentName).ReadOnly();
columns.Bound(s => s.Points).ReadOnly();
columns.Template(s =>
{%>
<input name="GradeReleaseStatus" type="checkbox" value="<%=s.GradeRelease%>"
<%if (s.GradeRelease)
{%>
checked="checked"
<%}%>
/>
<%
}).Title("Release Grade");
})
.Selectable()
.ClientEvents(events => events.OnRowSelect("Activities.DisplaySingleGrade"))
.Render(); %>
Can anyone tell me what I'm missing or doing wrong?
Thanks.
Do you see a hover effect when you move the mouse over a grid row? If yes - then selection is working. If not - probably there is a JavaScript error in your page. If you don't see a JavaScript error make sure the grid initialization JavaScript is output. This needs a ScriptRegistrar component to be present after the grid declaration. Lastly you can try with a simpler script to see if the JavaScript event is raised:
events.OnSelect("onSelect")
<script>
function onSelect() {
alert("OnSelect");
}
</script>