0
votes

I have a kendo dropdownlist on a Kendo grid (more specifically, it is using the Telerik MVC wrappers). When the "Edit" button is clicked on the row for the grid, the dropdownlist gets its data from an ajax jsonresult DataSource in my controller. I want to pass an Id to this datasource method so I can filter the results based on this id. However, this ID exists against the row in the table which contains the inline dropdownlist editor.

I'm looking to get the dataItem of the row which contains the dropdownlist through it's transport.read.data() function. I passed in e as a parameter to the function, but it doesn't seem to contain anything useful like e.sender. The this object doesn't reference the element, therefore I can't seem to use it for anything useful either. The best I've done so far is to get a reference to the grid (so I have access to the grid.dataItem function, but I can't pass anything meaningful into it to get the dataItem of the currently active row.

Here's a simplified version of the grid, excluding other unnecessary fields, etc.

    @(Html.Kendo().Grid<Grants.ViewModels.ScheduleOfWorkItemViewModel>()
        .Name("NewScheduleOfWorkItems")
        .Columns(columns =>
        {
            columns.Bound(col => col.ScheduleOfWorkItemID).Visible(false);                  
            columns.Bound(col => col.PercentageItemComplete).HtmlAttributes(new { @class = "cell-percentage-item-complete" }).Title("% Comp").Width(100).Format("{0:P2}").EditorTemplateName("SORREFPercentageItemComplete");             
            columns.Command(commandCol =>
            {
                commandCol.Edit();
                commandCol.Destroy();
            }).Width(100);                  
        })
        .Sortable()
        .Pageable(pageable => pageable.Refresh(true).PageSizes(new List<object> { 10, 20, "all" }).ButtonCount(5))
        .DataSource(dataSource => dataSource
            .Ajax()
            .Create(create => create.Action("Add_ScheduleOfWorkItem", "ScheduleOfWork"))
            .Update(create => create.Action("Add_ScheduleOfWorkItem", "ScheduleOfWork"))
            .Read(read => read.Action("GetScheduleOfWorkItems", "ScheduleOfWork").Data("GetIDForGetScheduleWorkItems"))
            .Model(model =>
            {
                model.Id(c => c.ScheduleOfWorkItemID);
                model.Field(c => c.ConcatenatedRenderedDescription).Editable(false);
                model.Field(c => c.UnitTypeName).Editable(false);
                model.Field(c => c.Cost).Editable(false);
                model.Field(c => c.AdjustedTotal).Editable(false);
            })
            .Destroy(delete => delete.Action("RemoveScheduleItemFromScheduleOfWork", "ScheduleOfWork"))
            .Sort(sort => sort.Add("ScheduleItemOrderNo").Ascending()) // <-- initial sort expression
        )                
        .Editable(editable => editable.Mode(GridEditMode.InLine))
        .Events(events =>
        {                    
            events.Edit("onSORREFEdit");
            events.Save("onSORREFSave");
            events.DataBound("onSORREFDataBound");
        })
    )

Here's the Dropdown list editor template

  @(Html.Kendo().DropDownList()
    .Name("SORREFPercentageItemCompleteId")
    .DataTextField("PercentageGrantItemCompleteText")
    .DataValueField("PercentageGrantItemCompleteId")
    .DataSource(source => {
        source.Read(read =>
        {
            read.Action("GetPercentageGrantItemCompleteLookups", "ScheduleOfWork").Data("SORREFPercentageItemCompleteData");
        });
    })
    .HtmlAttributes(new { style = "width: 100%" })
    .OptionLabel("Percentage complete...")
    .Events(events =>
    {
        events.Select("onSORREFPercentageItemCompleteSelect");
    })
    )

and here's my JS function for returning data, so far, which doesn't work.

var SORREFPercentageItemCompleteData = function (e) {    
    var $tr = $($(this)[0].element).closest("tr"); // "this" is useless? - how can i get my tr?
    var grid = $("#NewScheduleOfWorkItems").data("kendoGrid"); // grid id ok
    var dataItem = grid.dataItem($tr);
    return { scheduleOfWorkItemId: dataItem.ScheduleOfWorkItemID };
}
2

2 Answers

0
votes

Change the dropDownList dataSource transport read from a URL string to a configuration item that contains

  • the URL
  • a custom container field that refers to the edit row container
  • the data item as a function that returns the additional parameters for the URL
    • the function will use the container to find the row to find the grid and the rows model ID value

The following code is in dojo https://dojo.telerik.com/@RichardAD/uZIguWAn which is based on demo https://demos.telerik.com/kendo-ui/grid/editing-custom.

The end-game is that the drop down ajax data query will contain the extra parameter
productID = productID of row selected

            function categoryDropDownEditor(container, options) {
                $('<input required name="' + options.field + '"/>')
                    .appendTo(container)
                    .kendoDropDownList({
                        autoBind: false,
                        dataTextField: "CategoryName",
                        dataValueField: "CategoryID",
                        dataSource: {
                            type: "odata",
                            transport: {

// originally
// read: "https://demos.telerik.com/kendo-ui/service/Northwind.svc/Categories"

// magical tweakage
read: 
{
  container: container, // make container available to data function
  url: "https://demos.telerik.com/kendo-ui/service/Northwind.svc/Categories"
// see API documentation for transport.read.data
// https://docs.telerik.com/kendo-ui/api/javascript/data/datasource/configuration/transport.read#transport.read.data
, data: function (e) {

    grid = this.container.closest(".k-grid").data("kendoGrid");
    rowuid = this.container.closest("tr").data("uid");
    rowIdField = grid.dataSource.options.schema.model.id;

    result = {};
    result [rowIdField] = grid.dataSource.getByUid(rowuid)[rowIdField];

    return result;    
  }
}
0
votes

What I do for this case is just use the Edit event of the grid. When the user goes and tries to edit a row the event will give you the id you want. Pass it to a global variable in your js like

var selectedRowId = // the row id

and add this parameter to be returned on your dropdownlist read.

return { scheduleOfWorkItemId: selectedRowId };

I know it is not the most elegant solution but it has worked for me and I believe is quite easy.