I have a kendo grid on MVC proeject with a foreignKey column with a client template on the same column to send the data to the controller (hidden) as I have a header information just above the kendo grid that i want to send to the controller. Everything works fine. But when I select the dropdown in the grid it displays the value rather than the text.
columns.ForeignKey(c => c.studentId, (System.Collections.IEnumerable)ViewData["Students"], "Id", "name")
.Title("id - name")
.Width(70)
.ClientTemplate("#= studentId #" + "<'input type='hidden' name='MyModel[#= index(data)#].StudentId' value='#= StudentId #' />");
The above is the exact code I currently have.
How can I show the user the selected text (name in this case) rather than the value(Id in this case) on the kendo grid.
Thanks
just had the same problem and found this on the telerik site:
Basically create a function that looks up the text from Foreign Key Drop Down in the grid.
columns.ForeignKey(c => c.G_ID, plus, "Value", "Text").Title("Plu").Lockable(true).ClientFooterTemplate("Total").ClientTemplate("#= getTextByValue(data)#" +
"<input type='hidden' name='Schedules[#= index(data)#].G_ID' value='#= G_ID #' />"); //.Hidden();
and the javascript:
var collection;
And the function:
function getTextByValue(data) {
console.log(data);
var dGrid = $("#the-dtl-grid").data("kendoGrid");
//change the index of the column with your index
valuesCollection = dGrid.options.columns[1].values;
//if the collection is empty - get it from the grid
if (!collection) {
collection = {};
//Set the correct FKColumn index
for (var value in valuesCollection) {
collection[valuesCollection[value].value] = valuesCollection[value].text;
}
}
return collection[data.G_ID];
}
Thanks, very helpfull. Just in my case I must change this row valuesCollection = dGrid.options.columns[1].values; to valuesCollection = dGrid.columns[1].values;
Related
I need to create a more advanced method of adding new elements to a kendo grid, so in short I have replicated the following example as it does exactly what I needed:
https://github.com/telerik/ui-for-aspnet-mvc-examples/tree/master/window/KendoWindow-Ajax-Form
And it works just fine. Only difference is the new row is added in it's correct spot in the grid, and not on the top as per usual. How can I, using the example linked to, place the new row on the top?
(I'm thinking it's not necessary to show my code here as it very closely resembles the code given in the link above)
So If you want to add a row up top I am thinking you could use a custom template. I may not be very clear on what you are doing but , I will attempt to help you.
Here is the grid in the code:`
#(Html.Kendo().Grid<OrderViewModel>()
.Name("grid")
.Columns(columns =>
{
columns.Bound(c => c.Message).EditorTemplateName("MessageEditor");
}
.DataSource(datasource => datasource
.Ajax()
.Read(read => read.Action("GetOrders", "OrdersData"))
)
)`
Then write the template like this:
<script type="text/x-kendo-template" id="MessageEditor">
<div class="k-header k-grid-toolbar">
<div style="display: inline-block; font-size:1.25em; padding:
</div>
</div>
</script>
Well this may not be the best solution , however it is the only way I know to create a custom column in a Kendo grid
Ended up finding the solution myself eventually. Going by the example in the link I made in the original post, this is what I did:
Firstly when a new "order" is made, I make sure that the model returned in the "Create" method in OrdersDataController has an ID from when the model is added to the DB.
So when this part gets executed in "_OrdersCreate.cshtml":
#if (Model != null && ViewData.ModelState.IsValid)
{
<script>
closeCreatePopup();
</script>
}
I send information on the new Order created. So to that end I have modified "closeCreatePopup()" to handle arguments.
So for the finished results I will just use a piece of code from my own project, the following is my implementation of "closeCreatePopup()":
function closeCreateEmployeeWindow(name, rHPersonID, personID, organizationID) {
if (name !== undefined
&& rHPersonID !== undefined
&& personID !== undefined
&& organizationID !== undefined) {
var grid = $("#grid").data("kendoGrid");
grid.dataSource.insert({ Name: name, RHPersonID: rHPersonID, PersonID: personID, OrganizationID: organizationID });
grid.dataSource.sync();
}
var wnd = $("#createEmployeeModal").data("kendoWindow");
wnd.refresh({ url: '#Url.Action("CreateEmployee", "Employee", new { Area = "Administration" })' });
wnd.close();
}
The important part is this:
var grid = $("#grid").data("kendoGrid");
grid.dataSource.insert({ Name: name, RHPersonID: rHPersonID, PersonID: personID, OrganizationID: organizationID });
grid.dataSource.sync();
What is happening here is I use the "insert" method from the grid, and add a new object. "Insert" inserts the new object to the very top of the grid. Remember to call the "sync" method right after.
By doing it like this, the normal "create" method built into the grid is replicated.
I have a form in a View that brings together a number of pieces of information (address, telephone etc). All these elements are wrapped up in a view model. There is one section that asks the user to select a county. On selection, I want to be able to show a price based on the county selected.
I came across the following SO question which is close to what I want, but it looks like the action submits the form to a 'change controller'. I naively need to be able to basically call two controllers - one onSelectedChange and the other onSubmit. I'm pretty sure ya can't do this!
Here' what I'm after:
#model ViewOrder
#using (Html.BeginForm("Order", "Home"))
{
#* - textboxes et al - *#
<p>
#Html.DropDownListFor(x => x.Counties,
new SelectList(Model.Counties, "CountyId", "County"),
new { #class = "form-control input-sm" })
</p>
<p>
#* - £Price result of dropdown list selection and
add to View Model to add to sub total - *#
</p>
<input type="submit" text = "submit"/>
}
I'm very new to MVC - Could do this easily in webforms (but I'm sticking with MVC!) There must be some form of Ajax action that would allow this. Any suggestions?
First you have a problem with you #Html.DropDownListFor() method. Model.Counties is a complex object (with properties CountyId and County) but you cannot bind a <select> (or any control) to a complex object, only a value type. Your model needs a property (say) public int SelectedCountry { get; set; } and then #Html.DropDownListFor(x => x.SelectedCountry, new SelectList(Model.Counties, "CountyId", "County"), ...)
To display the price, you need to handle the .change event of the dropdown, pass the selected value to a controller method, and update the DOM.
Script (based on the property being SelectedCountry)
var url = '#Url.Action("GetPrice", "yourControllerName")';
$('#SelectedCountry').change(function() {
$.getJSON(url, { ID: $(this).val() }, function(data) {
// do something with the data returned by the method, for example
$('#someElement').text(data);
});
});
Controller
public JsonResult GetPrice(int ID)
{
// ID contains the value of the selected country
var data = "some price to return";
return Json(data, JsonRequestBehavior.AllowGet);
}
Below is the Kendo grid
#(Html.Kendo().Grid<CS.Web.Models.People.GroupDetailModel>()
.Name("Grid")
.Events(e => e.DataBound("LineItems_Databound"))
.HtmlAttributes(new { style = "overflow:hidden;", #class = "normalgrid" })
.Columns(columns =>
{
columns.Bound(p => p.GroupID).Hidden();
columns.Bound(p => p.GroupName).Title("Group Name").Width(30);
columns.Bound(p => p.Department).Title("Department Name").Width(30);
columns.Bound(p => p.IsBlindSettingsEnable).Title("Blind Group")
.ClientTemplate("<input type=\"checkbox\" #= IsBlindSettingsEnable ? \"checked=checked\": \"\" # enabled=\"enabled\" />")
.Width(30);
columns.Bound("Department").Title("Remove")
.ClientTemplate("<a href='javascript:void(0)' Title='Remove' onclick='return removeUserGroupRelation(+#=GroupID#+);'> <img alt='Remove' src='" + #Url.Content("~/Content/Images/delete_icon.png") + "' /></a>")
.Width(30);
})
.Sortable()
.Scrollable(scrollable => scrollable.Virtual(false))
.DataSource(dataSource => dataSource
.Ajax()
.Read(read => read.Action("getAssignedGroups", "People")
.Data("setRoutesValues")
)
//new { MerchantId = ViewBag.MerchantId, StartDate = Model.StartDate, EndDate = Model.EndDate }
)
.TableHtmlAttributes(new { #class = "grid_1" })
)
Below is the javascript code
var userID = '#ViewBag.UserID'
$.ajax({
url: '#Url.Action("SaveGroupsUserDetails")',
type: "POST",
dataType: "json",
data: { models: kendo.stringify($("#Grid").data("kendoGrid").dataSource.view()), UserID: userID },
success: function (result) {
}
});
Here in my kendo grid there is checkbox column.When i check or uncheck checkbox at CLIENT sied(in browser).And Do post via give javascript $.ajax post,it will not post the values of checkboxes which I have changed on client browser,it shows the values which it was binded from server side.
so,my question is to I want updated values to post on server which are modified on client browser.
I shall be very thankfull if you provide me answer.
You should just update your datasource on checkbox checked :
...
.ClientTemplate("<input type=\"checkbox\" #= IsBlindSettingsEnable ? \"checked=checked\": \"\" # enabled=\"enabled\" onclick='setChecked(this)' />")
...
function setChecked(cb) {
var row = $(cb).closest("tr");
var item = grid.dataItem(row);
item.IsBlindSettingsEnable = cb.checked;
}
and now your datasource is synced with the view
I believe this is because your looking at the actual value of the dataSource and not the grid itself. Your grid is non-editable. You are manually throwing the inputs into your grid and these will not effect the dataSource.
You can take two approaches do this kind of update.
You can leave the grid the way you have it set up and handle this update solely though Java Script.
To do this you will need to look up all the dataItems you need to update manually with JQuery.
You can lookup all of your check boxes with in that grid that are check, then get the relevant dataItem manually. Here is a short example showing how to get a dataItem from a row in the grid.
//checkbox is a JQuery object referencing one of your checkboxes
var row = $(checkbox).closest("tr");
var grid = $("#grid").data("kendoGrid");
var data = grid.dataItem(row);
Once you have all of your dataItems that are relevant you can then post your update. You would then have to reload your grid to get the updated status of these items.
Overall this is not the preferred way to do this kind of update with a kendo grid.
I suggest this second method.
This is the site where I will be pulling examples from: http://demos.telerik.com/aspnet-mvc/grid/editing
First you will need to make your kendo grid editable .Editable(editable => editable.Mode(GridEditMode.InCell)). You will not need the custom template that adds the checkbox anymore. It will automatically add them when you are editing your grid now.
You will need to then set the datasource to have an update function and have your server expect this update.
Your dataSource binding
.DataSource(dataSource => dataSource
.Ajax()
.Batch(true)
.Read("Editing_Read", "Grid")
.Update("Editing_Update", "Grid")
)
And your server side code
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Editing_Update([DataSourceRequest] DataSourceRequest request, [Bind(Prefix = "models")]IEnumerable<ProductViewModel> products)
{
if (products != null && ModelState.IsValid)
{
foreach (var product in products)
{
productService.Update(product);
}
}
return Json(products.ToDataSourceResult(request, ModelState));
}
By returning this Json object your grid will auto update to the new values. This is the preferred way to edit a grid.
I have the following html for a Kendo MVVM DropDownList:
<select id="responseTypeDDL"
data-role="dropdownlist"
data-text-field="SystemResponseTypeCode"
data-value-field="SystemResponseTypeId"
data-bind="value: selectedSystemResponseTypeCode, source: responseTypes">
</select>
This is my view model:
SC.ViewModels.Reference.ResponseTypeDataSource.read();
var responseTypeDDL = kendo.observable({
responseTypes: SC.ViewModels.Reference.ResponseTypeDataSource,
selectedSystemResponseTypeCode: null,
setSelectedSystemResponseTypeCode: function (code) {
this.selectedSystemResponseTypeCode = code;
},
});
kendo.bind($("#responseTypeDDL"), responseTypeDDL);
// after reading data, I call the method to set the selected value like this:
self.ResponseTypeDDL.setSelectedSystemResponseTypeCode(results.code);
The ResponseTypeDataSource.read() method returns a list of "XML", "JSON". This is the SystemResponseTypeCode field. I also read another data item from the database
and check its response type. Let's say it is "JSON". How do I set the drop down to have "JSON" selected?
First of all this part seems to be wrong
setSelectedSystemResponseTypeCode: function (code) {
this.selectedSystemResponseTypeCode = code;
},
You should make sure to call set() method while modifying an observed variable, otherwise it might not update the bindings:
this.set("selectedSystemResponseTypeCode", code);
And for your actual question
You need to set data-value-primitive="true" in order to work with just the id (Kendo Docs) (Please note changes below, value: selectedSystemResponseTypeId)
<select id="responseTypeDDL"
data-role="dropdownlist"
data-text-field="SystemResponseTypeCode"
data-value-field="SystemResponseTypeId"
data-value-primitive="true"
data-bind="value: selectedSystemResponseTypeId, source: responseTypes">
</select>
SC.ViewModels.Reference.ResponseTypeDataSource.read();
var responseTypeDDL = kendo.observable({
responseTypes: SC.ViewModels.Reference.ResponseTypeDataSource,
selectedSystemResponseTypeCode: null,
selectedSystemResponseTypeId: null,
setSelectedSystemResponseTypeId: function (id) {
this.set("selectedSystemResponseTypeId", id);
},
});
kendo.bind($("#responseTypeDDL"), responseTypeDDL);
// Get your id
var id = ...
responseTypeDDL.setSelectedSystemResponseTypeId(id);
Working example: http://dojo.telerik.com/AbIm/8
I've managed to manually set the value in dropdownlist without resorting to
data-value-primitive="true"
because i need to access the selected value and display other fields.
Here's the solution:
var id = 1004;
var dataItem = responseTypeDDL.responseTypes.get(id); //get the id in your datasource
responseTypeDDL.set("selectedsystemResponse", dataItem);
I want to implement following:
A combobox/DropDownListFor named "target" in a view. It contains (e.g.) A and B as choice.
In the same view I have another combobox named "medium". Its content depends on the chosen target, e.g.:
- if target = "A", combobox "medium" will show 1 and 2 as choice.
- if target = "B", combobox "medium" will show 3 and 4 as choice.
I have implemented combobox "target" successfully, but I don't know how to implement combobox "medium" related to "target". If I am not wrong, the logic should be: get the chosen targetid -> find all medium related to the targetid -> fill combobox "medium" with the result.
Here is snippet of my current view (combobox "target"):
<div class="editor-label">
#Html.LabelFor(model => model.TargetId)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.TargetId, (ViewData["targets"] as SelectList).MakeSelection(Model.TargetId))
</div>
Thx in advance.
You could use the javascript OnChange of the first drop to do an ajax call to obtain the values based from the choice A or B.
Then with the JSon response you get from the controller you fill the dropdown "Medium"
in the JS file do something like this:
$(document).ready(function () {
$("#target").change(function () { GetMediumValues("#target", "#medium"); });
});
function ClearDrop(objSource) {
$(objSource).empty();
}
function GetMediumValues(objSource, objDest) {
var url = '/mySite/GetMediumValues/';
$.getJSON(url, { id: $(objSource).val() }, function (data) {
ClearDrop(objDest);
$.each(data, function (index, optionData) {
$(objDest).append("<option value='" + optionData.Value + "'>" + optionData.Text + "</option>");
});
});
}
While in the controller
public ActionResult GetMediumValues(string id)
{
int myId = 0;
int.TryParse(id, out myId);
var select = new SelectList(repository.GetMediumValues(myId), "Id", "Name");
return Json(select, JsonRequestBehavior.AllowGet); //allow get needed to allow get calls
}