Dynamic ListViews/Datasources

4 posts, 1 answers
  1. Brian
    Brian avatar
    4 posts
    Member since:
    Jan 2016

    Posted 03 Jun Link to this post

    I am using Kendo UI 2016.1.226, Windows 7 Enterprise SP 1, Google Chrome 51.0.2704.79 m, SQL Server 2012

    I created a ListView for available report filters (Filter List), which loads from a stored procedure and uses the HTML ListView wrapper.  On Filter List databound, I am dynamically creating 2 more listviews (Available items and Selected items) for each item in the primary ListView.  When an item is selected from the primary, if no items are currently in the available list, the datasource is read from a stored procedure, passing the report filter ID, and returns a list of KeyIndex (int) and Value (string) items from various DB tables.  These are supposed to be loaded in the Available ListView's databound event.  However, there are no items in the datasource after return from the stored procedure call.

     

    I suspect the issue is a JSON vs. OData format issue (see 12/5/2011 post here: http://www.telerik.com/forums/connect-grid-to-mvc-controller-method).  I don't care about grouping, filtering, and sorting of the items, but it seems like I may need to send a request object to the controller in order to call ToDataSourceResult, which I'm guessing converts JSON to OData format.  The Available datasource has AutoBind set to false, so that I can load only the report filters as needed.  When I try to pass information in the request, I get the following error because there is no data to group, filter, or sort yet:

        jquery.min.js:3 Uncaught TypeError: Cannot read property 'length' of undefined

     

                    var availableDataSource = listViewAvailable.dataSource;
                    var parameterMap = availableDataSource.transport.parameterMap;
                    var request = parameterMap({ filter: availableDataSource.filter(), group: availableDataSource.group(), sort: availableDataSource.sort() });
                    availableDataSource.transport.options.read.url = 
                        "/ReportCategory/GetFilterValues?FilterID=" + dataItem.ReportFilterID + "&TplNum=" + @ViewBag.TplNum + "&request=" + request;
                    availableDataSource.read();

    If I leave the parameterMap empty, my controller routine is called, the JSON data is populated and returned to the client, but the number of items in the datasource is 0:

                   var request = parameterMap({  });

     

            public async Task<ActionResult> GetFilterValues([DataSourceRequest]DataSourceRequest request, int FilterID = 0, int TplNum = 0)
            {
                var url = string.Format("{0}{1}/{2}", GlobalVariables.ApiBaseUrl.Replace("api", "GetFilterValues"), FilterID, TplNum);

                var jsonResult = await Request.GetSerializedJsonResult<FilterValues>(url);
                IList listFilterValues = (IList)jsonResult;

                return Json(listFilterValues.ToDataSourceResult(request),JsonRequestBehavior.AllowGet);
            }

    Datasource definition:

                        filterDataSource = new kendo.data.DataSource({
                            type: "odata",
                            transport: {
                                read: {
                                    url: "/api/GetFilterValues/" + filterRecord.ReportFilterID + '/' + @ViewBag.TplNum,
                                    type: "GET",
                                    dataType: "json"
                                },
                            },
                            schema: {
                                model: {
                                    fields: {
                                        KeyIndex: { type: "number" },
                                        Value: { type: "string" }
                                    }
                                },
                                data: function(data) { return data.value; },
                                total: function(data) { return data["odata.count"]; }
                            },
                            serverFiltering: true,
                            serverGrouping: true,
                            serverSorting: true
                        });

    Available ListView:

                idString = "Filters_1_" + filterIndex;
                divString = '<div id="' + idString + '" class="filterlist1" style="display: none;"><h2>Available Values</h2></div>';
                divStringInner = '<div class="filterlist1_inner"></div>';
                $(divString).insertAfter('#ReportFilters');
                $(divStringInner).insertAfter('#' + idString + ' h2').kendoListView({
                    dataSource: filterDataSource,
                    dataBound: onAvailableDataBound,
                    autoBind: false,
                    pageable: false,
                    selectable: selectableType,
                    template: kendo.template($('#' + templateName).html())
                });

    ListView item template (TBD being eventually replaced by the Value string in the datasource):

    <script type="text/x-kendo-tmpl" id="options">
    <div class="filter2">
        <h3 value='0'>TBD</h3>
    </div>
    </script>

     

    I saw something for SQL Server called FOR JSON AUTO that may help make the stored procedure OData compliant (https://msdn.microsoft.com/en-us/library/dn921897.aspx), but that is for SQL Server 2016 on.  Any ideas?

  2. Answer
    Boyan Dimitrov
    Admin
    Boyan Dimitrov avatar
    1746 posts

    Posted 07 Jun Link to this post

    Hello Brian,

    The ToDataSourceResult method stores the data items in "Data" field of the response (it is one of the things which ToDataSourceResult actually does) . It does not convert the JSON to OData format. This is why the setting type: "odata" will not work as expected in your case. When type is set to "odata" the DataSource will try to read the data items from specific field (since it expects the response to be in OData format). 

    My suggestion is to remove the type: "odata" from the DataSource configuration settings and use the following: 

       - schema.data - the field of the server response which contains the data items. 

        - schema.errors - the field from the server response which contains the errors (if any). 

        - schema.total - the field from the server response which contains the total number of data items. 

     

    Please refer to the attached project that shows how to configure the Kendo UI DataSource to read the data from the response when ToDataSourceResult method is used in the action method on the server.

    Regards,
    Boyan Dimitrov
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  3. UI for ASP.NET MVC is VS 2017 Ready
  4. Brian
    Brian avatar
    4 posts
    Member since:
    Jan 2016

    Posted 08 Jun in reply to Boyan Dimitrov Link to this post

    The combination of using type: 'aspnetmvc-ajax' in my datasource and using the empty parameter map to send a DataSourceRequest worked.  I'm not sure why I have to send a request object rather than just invoke a URL that returns JSON, but that's the only way I could get it to work.

    Also, I was able to use the following syntax in my template to auto populate the results:

    <script type="text/x-kendo-tmpl" id="options">
    <div class="filter2">
        <h3 value=#:KeyIndex#>#:Value#</h3>
    </div>
    </script>

    I thought maybe this was Razor code and had to be rendered before the HTML was downloaded to the client.

  5. Brian
    Brian avatar
    4 posts
    Member since:
    Jan 2016

    Posted 09 Jun Link to this post

    It turns out that ToDataSourceResult does not have to be used and a request object does not have to be passed to the controller.  I modified my data and total in the schema section and it's working.

     

                        filterDataSource = new kendo.data.DataSource({
                            type: 'aspnetmvc-ajax',
                            transport: {
                                read: {
                                    url: function(filterID, tplNum){
                                        var url = "/api/GetFilterValues/" + filterID + '/' + tplNum;
                                        return url;
                                    },
                                    type: "GET",
                                    dataType: "json"
                                },
                            },
                            schema: {
                                data: function (data) { return data; },
                                total: function (data) { return data.length; },
                                model: {
                                    fields: {
                                        KeyIndex: { type: "number" },
                                        Value: { type: "string" }
                                    }
                                },
                            },
                            serverFiltering: true,
                            serverGrouping: true,
                            serverSorting: true
                        });

Back to Top
UI for ASP.NET MVC is VS 2017 Ready