Kendo Read Action - getting the control Id - asp.net-mvc

I have a partial view using a Kendo DropDownListFor and within the Datasource Read action I am passing a function name to get additional parameters eg.
#(Html.Kendo().DropDownListFor(m => m.AssignedUserId)
.OptionLabel("Assign to ...")
.DataTextField("FullName")
.DataValueField("UserId")
.Filter(FilterType.StartsWith)
.AutoBind(true)
.DataSource(source => {
source.Read(read => { **read.Action("GetStaffList", "ManageUser").Data("filterAssigned");** })
.ServerFiltering(true);
})
)
function filterAssigned(e) {
// Selector needs to be prefixed "Create_" or "Update_" depending on view/HtmlFieldPrefix.
var ctl = $("#AssignedUserId").data("kendoDropDownList");
return {
staffFilter: (ctl.filterInput.val() || 'empty'),
selectedId: (ctl.value() || 0)
};
}
Within the "FilterAssigned" function I want to get the Id of the control rather than hardcoding $("#AssignedUserId").data("kendoDropDownList"). This is because when creating the View, I am setting the ViewData.TemplateInfo.HtmlFieldPrefix = "Create" so the actual control id is rendered as "Create_AssignedUserId" and I want to use the same function for Create, Update etc.
I have tried the usual options:
this.id
this.attr('id')
this.element.attr('id')
e.sender
Telerik state that the 'this' attribute is not obtainable during a read but I have seen no other solution other than the selector method. Basically I am trying to do this:
function filterAssigned() {
var ctl = **this.id**;
return {
staffFilter: (ctl.filterInput.val() || 'empty'),
selectedId: (ctl.value() || 0)
};
}

I found the best way to solve this was to use the razor helper #Html.IdFor. The control id this returns includes the HtmlFieldPrefix. The function will now look like ...
function filterAssigned() {
var ctl = $("##Html.IdFor(m => m.AssignedUserId)").data("kendoDropDownList");
return {
staffFilter: (ctl.filterInput.val() || 'empty'),
selectedId: (ctl.value() || 0)
};
}

Related

Kendo DropDownList FilterText always null

I have a Kendo DropdownList that I can't get to filter - on looking at the data received in the controller to the following function I notice that the "string text" is always null:
[OutputCache(NoStore = true, Duration = 0)]
public JsonResult GetAssemblys(string text, long site)
{
return Json(CreateFilteredList(text, site, (long)AssetTypeEnum.Assembly), JsonRequestBehavior.AllowGet);
}
This is the code for the DropDownList:
<div>#(Html.Kendo().DropDownList()
.Name("AssemblySelector")
.DataTextField("AssetName")
.DataValueField("AssetId")
.HtmlAttributes(new { style = "width: 570px;" })
.OptionLabel("Select assembly...")
.DataSource(s =>
{
s.Read(r => r.Action("GetAssemblys", "Form707B").Data("getsite"));
s.ServerFiltering(true);
})
.Filter(FilterType.Contains)
.Height(300)
.SelectedIndex(0))
This worked before I added the .Data("getsite")) part to to the read method. getsite() returns a long called site (this is successfully received in the controller).
What is often not known by people using the MVC Builder is that fluent builder puts a default read data handler to send the filter text to their controller.
if you override the data handler you need to send the text filter yourself or call the method it usually calls which is the following
if (DataSource.ServerFiltering && !DataSource.Transport.Read.Data.HasValue() && DataSource.Type != DataSourceType.Custom) {
DataSource.Transport.Read.Data = new ClientHandlerDescriptor {
HandlerName = "function() { return kendo.ui.DropDownList.requestData(jQuery(\"" + EscapeRegex.Replace(Selector, #"\\$1") + "\")); }"
};
}
to do so your getsite function should look like this.
function getsite() {
// drop down element
var $dd = $('#AssemblySelector');
// widget
var dd = dd.data('kendoDropDownList');
var filterText = dd.input.text();
var site = null; // do your logic for this.
return {
site: site,
text: filterText
};
}
or
function getsite() {
// drop down element
var $dd = $('#AssemblySelector');
// widget
var dd = dd.data('kendoDropDownList');
var ret = kendo.ui.DropDownList.requestData($dd);
ret['site'] = site;
return ret;
}

Retrieve all drop-down values from database and show the saved value as selected one in drop down

I am using a kendo grid with pop up editing mode and editor template in mvc4. The template consists of a drop down list which is bound through database. The problem comes when in Edit operation all other data is retrieved along with all elements of drop down list and displayed in respective html attributes such a textbox ,checkbox etc but the value which i have saved from drop down list is not shown auto selected there.
Example
During add operation i have selected "Work" from the drop down list and saved it in database. At the time of Edit i want "Work" to be shown auto selected in drop down list.
[AcceptVerbs(HttpVerbs.Post)]
public JsonResult Update([DataSourceRequest] DataSourceRequest request,Model object)
{
if (obj == null || !ModelState.IsValid) return null;
var obj = _Repo.FindBy(t => t.ID == object.ID);
obj.Text = object.Text;
obj.Type = object.Type;
obj.MasterTypeID_Fk = new Guid(object.Type);
obj.Notes = object.Notes;
obj.Primary = object.Primary;
obj.LastVerified = DateTime.Now.ToUniversalTime();
obj.LastUpdated = DateTime.Now.ToUniversalTime();
_Repo.Update(obj);
var result = new[] { object }.ToDataSourceResult(request, ModelState);
return Json(result);
}
//this is my code for ddl in editor template
#(Html.Kendo().DropDownList()
.Name("Type")
.DataTextField("Value")
.DataValueField("TypeID")
.DataSource(source =>
{
source.Read(read => { read.Action("GetTypes", "Dashboard"); });
})
)
// this is code in controller to bind ddl
public ActionResult GetTypes()
{
List<TypeModel> Type = _Repo.GetTypes().ToList().ToMap<TypeBO, TypeModel>();
Type.Insert(0, new TypeModel() { Value = "--Select--", TypeID = Guid.Empty });
return Json(Type, JsonRequestBehavior.AllowGet);
}
You can set your value in Html helper using Value("ValueData"):
#(Html.Kendo().DropDownList()
.Name("Type")
.DataTextField("Value")
.DataValueField("TypeID")
.DataSource(source =>
{
source.Read(read => { read.Action("GetTypes", "Dashboard"); });
})
.Value("ValueData")
)
Like in this example: http://demos.telerik.com/aspnet-mvc/dropdownlist/index

Kendo UI treeview binding

I want to make a Kendo TreeView that shows all nodes on first load. I'm using the Kendo 'Binding to remote data' sample but it doesn't work correctly. It shows just the first level and the id passed to the controller action is always null.
Please help me.
View code :
#(Html.Kendo().TreeView()
.Name("treeview")
.DataTextField("Title")
.ExpandAll(true)
.LoadOnDemand(false)
.DataSource(dataSource => dataSource
.Read(read => read.Action("Employees", "Follow").Data("addData"))))
function addData(data) {
return { id: data.id };
}
Controller code : (controller Follow)
public System.Web.Mvc.JsonResult Employees(int? id)
{
System.Collections.Generic.List<FollowType> List =
new System.Collections.Generic.List<FollowType>();
if (id.HasValue == true) {
List = FollowTypeList.FindAll(current => current.ParentId == id);
} else {
List = FollowTypeList.FindAll(current => current.ParentId == null);
}
System.Collections.Generic.List<Kendo.Mvc.UI.TreeViewItemModel> NodeList =
new System.Collections.Generic.List<Kendo.Mvc.UI.TreeViewItemModel>();
foreach (CommonData.Domain.FollowType item in List)
{
NodeList.Add(new Kendo.Mvc.UI.TreeViewItemModel() {
Id = item.Id.ToString(),
Text = item.Title,
HasChildren = FollowTypeList.Exists(c => c.Id == item.ParentId)
});
}
return Json(NodeList, System.Web.Mvc.JsonRequestBehavior.AllowGet);
}
I guess that in your javascript code, the id field of data should be Id (be careful to the capitalization) :
return { id : data.Id };

How to sync Kendo UI mvc Grid with Kendo Mvc Autocomplete

I am working asp.net mvc witk Kendo UI MVC Tools. I am trying to display list of records in a Kendo UI Mvc Grid. and i have one kendo ui autoComplete Textbox when i type a letter it shows corresponding field record that matches the criteria will be showed like a dropdown. Now i want to sync the autocomplete textbox with kendo ui mvc grid. that means when i type a letter records that matches criteria should display in the grid. I have tried with change event but it doesnt seems work for me.
#(Html.Kendo().AutoComplete().Events(c=>c.Change("GridChange"))
.Name("txtSearchItem")
.Filter("startswith")
.DataTextField("xxx")
.Value(ViewBag.SearchValue)
.BindTo((List<MyRecords>)Model).HtmlAttributes(new { #class = "required", style = "font-size:19px;width:150px;", onkeypress = "return isNumericKey(event);" })
)
please guide me.
First, create a grid with a HeaderTemplate to make a combobox that behaves as an autocomplete as well.
#( Html.Kendo().Grid(Model)
.Name("Grid")
.ClientDetailTemplateId("inventoryTemplate")
.DataSource(ds => ds.Ajax()
.Read(r => r.Action("Read", "Home"))
)
.Columns(columns =>
{
columns.Bound(p => p.Item).Width(10)
.Filterable(false).Sortable(false).HeaderTemplate(#<text>
#(Html.Kendo().ComboBox()
.DataValueField("Items")
.Placeholder("Items")
.DataTextField("Items")
.Name("Items")
.DataSource(ds => ds.Read(rea => rea.Action("ListOfItems", "Home")))
.Events(ev => ev.Change("onComboListCodeChange"))
)
</text>);
})
)
Now create this method will get an array from Dictionary of filters, you will need it later.
function getArrayFromDic(dic) {
var arr = new Array();
arr = $.map(dic, function (n, i) {
return { field: n.field, operator: n.operator, value: n.value };
});
return arr;
}
This function will get a dictionary that represents the filters available on the grid. If there is more than one filter.
function getFilterDic() {
var grid = $('#Grid').data('kendoGrid');
var filtersDicTemp = {
};
if (grid.dataSource._filter) {
$.each(grid.dataSource._filter.filters, function (index, value) {
filtersDicTemp[value.field] =
{
field: value.field, operator: value.operator, value: value.value
}
});
}
return filtersDicTemp;
}
This will be called each time you change the value of the filter Autocomplete combobox in this case.
There is a method on the kendo.data.DataSource called filter, where you can pass an array of filters.
function onComboListCodeChange(e) {
var grid = $('#Grid').data('kendoGrid');
var filtersDic = getFilterDic();
if (this.value() && this.value() != 'All') {
if (this.value() != 'Items' && this.value() != '') {
filtersDic["Items"] =
{
field: "Items", operator: "startswith", value: this.value()
}
}
}
else {
if (filtersDic["Items"]) {
delete filtersDic["Items"];
}
}
var filters = getArrayFromDic(filtersDic);
grid.dataSource.filter(
filters
);
}
Hope it helped!
Use the approach from here http://demos.kendoui.com/web/grid/toolbar-template.html
The difference would be that you will use AutoComplete (which is almost the same) and you do not need to put it inside the Toolbar via the Toolbar template.

Persist CheckBox State in Telerik MVC Grid While Paging in ASP.NET MVC Application

I am using Telerik MVC Grid where one of the columns is checkboxes. If I select checkboxes and then go to page 2 and then come back to page 1 all the checkboxes are gone. Which is of course the way HTTP works. Now, I put all the selected checkboxes inside the hidden field but since the grid does some sort of postback my hidden field is cleared next time.
If you're using Client Side data binding you can use the javascript/jquery below to maintain checkbox state.
Maintain checkbox state:
var selectedIds = [];
$(document).ready(function () {
//wire up checkboxes.
$('#YOUR_GRID_ID :checkbox').live('change', function (e) {
var $check = $(this);
console.log($check);
if ($check.is(':checked')) {
//add id to selectedIds.
selectedIds.push($check.val());
}
else {
//remove id from selectedIds.
selectedIds = $.grep(selectedIds, function (item, index) {
return item != $check.val();
});
}
});
});
Restore checkbox state after data binding:
function onDataBound(e) {
//restore selected checkboxes.
$('#YOUR_GRID_ID :checkbox').each(function () {
//set checked based on if current checkbox's value is in selectedIds.
$(this).attr('checked', jQuery.inArray($(this).val(), selectedIds) > -1);
});
}
A more verbose explanation available on my blog:
http://blog.cdeutsch.com/2011/02/preserve-telerik-mvc-grid-checkboxes.html
You need to save the state of the checkboxes to your database, and then retrieve them again from the database when you reload the page.
During paging, you need to reload only those records that pertain to a particular page. You can do that using the Skip() and Take() methods from Linq.
to preserve checked /unchecked checkbox state using telerik grid clientemplate across postbacks and async postbacks and in refreshing grid and (auto)paging, I tried the solution above with no avail and so went up with a bit harder solution; as I could not save the state in db, I used a session variable and an hiddenfield:
first, a way to do ajax postback (see function DoAjaxPostAndMore , courtesy of somebody herearound), where in success we take care of client values of selections, adding and removing as checked /unchecked
I also had to manually check / uncheck the checkboxes inside the manual ajax post
second, an hidden field (see 'hidSelectedRefs') to preserve clientactions, as the Session variable I am using will not be seen clientside in partial rendering
#model IEnumerable<yourInterfaceOrClass>
#{
ViewBag.Title = "Select Something via checkboxes";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Select Something via checkboxes</h2>
<!-- we need a form with an id, action must be there but can be an empty string -->
<form id="frm" name ="frm" action="">
<p>
<!--we need this as Session new values will not be takein in aajax requests clientisde, so it is easier to mange this field, which, in first and subsequent complete postbacks can have the value of the Session variable -->
<input type="hidden" name="hidSelectedRefs" id="hidSelectedRefs" value= '#Session["SelectedReferencesToPrint"]' />
</p>
<br />
<script type="text/javascript">
//ajax manual post to a custom action of controller, passing the id of record and the state of the checkbox
//to adjust the Session value
//data: $form.serialize() will have the single checbox value
//but only if checked. To make my life eaasier, I added the value (is id ) and the checked/unchecked
//state of checkbox (is the $(chkClicked).attr('checked'))
function DoAjaxPostAndMore(chkClicked) {
var $form = $("#frm");
$.ajax({
type: "POST",
url: 'SelectReferences',
data: $form.serialize() + '&id=' + $(chkClicked).val() + '&checked=' + $(chkClicked).attr('checked'),
error: function (xhr, status, error) {
//do something about the error
alert("Sorry, we were not able to get your selection...");
},
success: function (response) {
//I also needed to check / uncheck manually the checkboxes:
$(chkClicked).attr('checked', !$(chkClicked).attr('checked'));
//and now put correct values in hidSelectedRefs hidden field:
if ($(chkClicked).attr('checked')) {
$('input[name=hidSelectedRefs]').val($('input[name=hidSelectedRefs]').val() + '|' + $(chkClicked).val() + '|');
} else {
var tmp = $('input[name=hidSelectedRefs]').val();
$('input[name=hidSelectedRefs]').val(tmp.toString().replace('|' + $(chkClicked).val() + '|', ''));
}
}
});
return false; // if it's a link to prevent post
}
Then I handled the OnRowDataBound, to ensure the checboxes would be correctly checked on postbacks,
function onRowDataBound(e) {
var itemsChecked = $('input[name=hidSelectedRefs]').val();
if (itemsChecked)
{
if (itemsChecked.indexOf('|' + $(e.row).find('input[name=checkedRecords]').val() + '|') >= 0)
{
$(e.row).find('input[name=checkedRecords]').attr('checked', true);
}
}
}
</script>
The telerik mvc Grid is as follows:
(you can see I also handled OnDataBinding and OnDataBound, but thats's only to show a
"Loading" gif. The controller is named "Output" and the action that normally would be called "Index" here is callled "PrintReferences". The correspondenting Ajax action is called "_PrintReferences")
Of interest here is the ClientTemplate for checkbox (cortuesy of someone else herearound, where onclick
we call our custom ajax action (named "SelectReferences") on our Output controller via a call to the
DoAjaxPostAndMore() javascript/jquery function
#(Html.Telerik().Grid<yourInterfaceOrClass>()
.Name("Grid")
.ClientEvents(e => e.OnDataBinding("showProgress").OnDataBound("hideProgress").OnRowDataBound("onRowDataBound"))
.DataBinding(dataBinding =>
{
dataBinding.Server().Select("PrintReferences", "Output", new { ajax = ViewData["ajax"]});
dataBinding.Ajax().Select("_PrintReferences", "Output").Enabled((bool)ViewData["ajax"]);
})
.Columns( columns =>
{
columns.Bound(o => o.ID);
columns.Bound(o => o.ID)
.ClientTemplate(
"<input type='checkbox' name='checkedRecords' value='<#= ID #>' onclick='return DoAjaxPostAndMore(this)' />"
)
.Width(30)
.Title("")
.HtmlAttributes(new { style = "text-align:center; padding: 0px; margin: 0px;" });
columns.Bound(o => o.TITLE);
columns.Bound(o => o.JOBCODE);
columns.Bound(o => o.ORDERCODE );
//columns.Bound(o => o.AUTHOR);
columns.Bound(o => o.STATE);
columns.Command(commands =>
commands
.Custom("Details")
.ButtonType(GridButtonType.Image)
.HtmlAttributes(new { #class = "t-icon-details" })
.DataRouteValues(route => route.Add(o => o.ID)
.RouteKey("ID"))
.Ajax(false)
.Action("Details", "Referenza")
);
})
.Pageable(paging =>
paging.PageSize(10)
.Style(GridPagerStyles.NextPreviousAndNumeric)
.Position(GridPagerPosition.Bottom))
.Sortable()
.Filterable()
.Resizable(resizing => resizing.Columns(true))
.Reorderable(reorder => reorder.Columns(true))
.NoRecordsTemplate("No Reference found. Please review your filters...")
.ColumnContextMenu()
)
</form>
that's all for the View. Now, to the controller:
//Get : this is the usally called "Index" action
//here we can load data, but we also must ensure the Session variable is fine
public ActionResult PrintReferences(bool? ajax, string msgInfo, string selectedRef)
{
if (Session["SelectedReferencesToPrint"] == null)
{
Session["SelectedReferencesToPrint"] = string.Empty;
}
if (string.IsNullOrEmpty(selectedRef))
{
selectedRef = "|0|";
}
string msgOut = string.Empty;
//this is where I get data to show
List<yourInterfaceOrClass> ret = LoadData(out msgOut);
if (!string.IsNullOrEmpty(msgInfo) && !string.IsNullOrEmpty(msgInfo.Trim()))
{
msgOut = msgInfo + ' ' + msgOut;
}
ViewBag.msgOut = msgOut;
ViewData["ajax"] = ajax ?? true;
return View(ret);
}
//GridAction: here is telerik grid Ajax get request for your "_Index"
[GridAction]
public ActionResult _PrintReferences(string msgInfo)
{
//again, we must take care of Session variable
if (Session["SelectedReferencesToPrint"] == null)
{
Session["SelectedReferencesToPrint"] = string.Empty;
}
string msgOut = string.Empty;
List<yourInterfaceOrClass> ret = LoadData(out msgOut);
return View(new GridModel(ret));
}
//Post: this is where our custom ajax post goes
//we are here if a checkbox is cheched or unchecked
//in the FormCollection parameter we get the checkbox value only if checked, and also
//(and always) the parms we passed (id of record and state of checkbox: we cannot simply add,
//we must also subtract unchecked)
[HttpPost]
public ActionResult SelectReferences(FormCollection collection)
{
//we need a session variable
if (Session["SelectedReferencesToPrint"] == null)
{
Session["SelectedReferencesToPrint"] = string.Empty;
}
//use a local variable for calculations
string wholeSelectionToPrint = Session["SelectedReferencesToPrint"].ToString();
//get value passed: id
string selectedRefId = collection["id"];
if (!string.IsNullOrEmpty(selectedRefId))
{
selectedRefId = "|" + selectedRefId + "|";
}
bool cheked = (collection["checked"].ToString()=="checked");
//get vcalue passed :checked or unchecked
if (cheked)
{
//the element is to add
wholeSelectionToPrint += selectedRefId;
}
else
{
//the element is to remove
wholeSelectionToPrint = wholeSelectionToPrint.Replace(selectedRefId, "");
}
//set session variable final value
Session["SelectedReferencesToPrint"] = wholeSelectionToPrint;
return null;
}
//normal postback:
//we will be here if we add a button type submit in our page,
//here we can collect all data from session variable to do
//something with selection
[HttpPost]
public ActionResult PrintReferences(FormCollection collection)
{
//get selected references id
if (Session["SelectedReferencesToPrint"] == null)
{
Session["SelectedReferencesToPrint"] = string.Empty;
}
//use a local variable for calculations
string wholeSelectionToPrint = Session["SelectedReferencesToPrint"].ToString();
wholeSelectionToPrint = wholeSelectionToPrint.Replace("||", "|");
string[] selectdIDs = wholeSelectionToPrint.Split(new char[] { '|' });
foreach (string id in selectdIDs)
{
if (!string.IsNullOrEmpty(id))
{
//do something with single selected record ID
System.Diagnostics.Debug.WriteLine(id);
}
}
//omitted [....]
ViewData["ajax"] = true;
return View(ret);
}

Resources