Rebind datasource and pass additional parameter to action method

7 posts, 0 answers
  1. Patrick
    Patrick avatar
    7 posts
    Member since:
    Jul 2016

    Posted 02 Nov 2018 Link to this post

    Hey,

    So i have a very simple form 2 controls on it,

    1 DropdownList

    1 DropDownTree

    <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
            @Html.Kendo().DropDownListFor(a => a.BranchId).OptionLabel("Select Branch").DataTextField("Text").DataValueField("Value").BindTo(Model.BranchList).HtmlAttributes(new { @class = "ff_required ff_control", @required = "required" })
        </div>
        <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
            <label class="ff_label">Select a parent category (optional)  <span class="ParentCategoryTip"><img src="~/Images/icons/help.png" /></span></label>
        </div>
        <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
     
        @(Html.Kendo().DropDownTreeFor(a => a.ParentCategoryId)
                                            .DataTextField("Name")
                                            .DataValueField("id")
                                            .Placeholder("Select Category")
                                            .HtmlAttributes(new { style = "width: 100%" })
                                                .Events(events => events
                                                .Change("DropdownTreeChange"))
        )

     

    By default when the page loads i do not want to DropdownTree to bind to anything, it must be blank. Only once a selection is made from the BranchId DropDownList then i want the DropDownTree to be populated by passing the BranchId to the action method.

    Here is what i have so far

    $("#BranchId").on("change", function () {
     
            var tree = $("#ParentCategoryId").data("kendoDropDownTree");
            var val = tree.value();
     
     
            tree.refresh({
                url: "/Setting/GetCategorylist",
                data: {
                    Id: val,
                    BranchId: $("#BranchId").val()
                }
            });
        });

     

    [HttpGet]
           //public async Task<ActionResult> GetCategorylist([DataSourceRequest] DataSourceRequest request, int BranchId)
           public async Task<ActionResult> GetCategorylist(int? Id, int BranchId)
           {
               var Result = await new _GetCategoryTreeList(new FF_ErrorLogger()).GetIdAsync(null,BranchId);
               return Json(Result, JsonRequestBehavior.AllowGet);
           }

     

    i cannot get the DropDownTree to rebind its data.

     

  2. Patrick
    Patrick avatar
    7 posts
    Member since:
    Jul 2016

    Posted 02 Nov 2018 in reply to Patrick Link to this post

    So i have managed to get this to work for the most part, but now i have run into an interesting issue.

    Like i mentioned i have 2 controls on the form 1 standard dropdown list which provides a list of [Branches] and 1 DropDownTree which has is used to populate my list of [Categories}.

    If i select a [Branch] from the standard dropdown list and then click on the DropDownTree,a request is made to the server and everything loads 100% correctly within the [Category] DropDownTree.

    A [Branch] must be selected before any [Categories] are displayed within the DropDownTree, So here is the interesting part if i refresh my page and click on the [Category] DropDownTree a request is made to the server and no data is returned which is correct up until this point and i even get a friendly message stating that there is no data. but if i then select a [Branch] and click on the [Category] DropDownTree again i can see a request is sent to the server and the correct data is obtained BUT the [Category] DropDownTree is never repopulated, i just get a message within the control saying 'Loading...'.

    I tried switching off the caching, i can see that in the response the data is coming back to the page, but the data is  just not binding to the control.

    <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
                            @Html.Kendo().DropDownListFor(a => a.BranchId).OptionLabel("Select Branch").DataTextField("Text").DataValueField("Value").BindTo(Model.BranchList).HtmlAttributes(new { @class = "ff_required ff_control", @required = "required" })
                        </div>
                        <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
                            <label class="ff_label">Select a parent category (optional)  <span class="ParentCategoryTip"><img src="~/Images/icons/help.png" /></span></label>
                        </div>
                        <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
     
     
                            @(Html.Kendo().DropDownTreeFor(a => a.ParentCategoryId)
                                        .DataTextField("Name")
                                        .DataValueField("id")
                                        .Placeholder("Select Category")
                                        .HtmlAttributes(new { style = "width: 100%" })
                                        .DataSource(dataSource =>
                                        dataSource.Read(read =>
                                            read.Action("GetCategorylist", "Setting").Type(HttpVerbs.Post).Data("filterCategories"))
                                            .ServerFiltering(true))
                                        .AutoBind(false)
                                        .Events(events => events
                                        .Change("DropdownTreeChange"))
                            )
     
     
     
                        </div>

     

    <script>
     
        function DropdownTreeChange() {
            var dropdowntree = $("#ParentCategoryId").data("kendoDropDownTree");
            $("#ParentCategoryId").val(dropdowntree.value());
        }
     
        function filterCategories(args) {
     
            return {
                BranchId: $("#BranchId").val()
            };
        }
     
    </script>

     

    [HttpPost]
     public async Task<ActionResult> GetCategorylist(int? Id,int? BranchId)
            {
                var Result = await new _GetCategoryTreeList(new FF_ErrorLogger()).GetIdAsync(Id,BranchId);
                return Json(Result, JsonRequestBehavior.AllowGet);
            }

     

    Any thoughts on this one?

     

  3. Patrick
    Patrick avatar
    7 posts
    Member since:
    Jul 2016

    Posted 06 Nov 2018 Link to this post

    Any response to this?

    from what i gather once the dropdowntree control is bound with data,this cannot be cleared / reset and rebound to new data.

  4. Dimitar
    Admin
    Dimitar avatar
    676 posts

    Posted 06 Nov 2018 Link to this post

    Hello Patrick,

    I am attaching an ASP.NET MVC solution, where you can find a simple DropDownTreeimplementation that demonstrates a similar scenario to the one described. With it, based on a DropDownList selection, the data source of the DropDownTree is being dynamically changed.

    To set the data source of the widget and also rebind it, the setDataSource() method is used as follows:
    <script>
        function onCategoryChange(ev) {
            var ddt = $("#HierarchicalID").getKendoDropDownTree();
            var ddtVal = ddt.value();
     
            $.ajax({
                type: "POST",
                url: "/Home/GetEducationAvailableTree",
                data: { CategoryId: ev.sender.value() },
                dataType: "json",
                success: function (result) {
                    var ds = new kendo.data.HierarchicalDataSource({
                        data: result
                    });
     
                    ddt.setDataSource(ds);
                }
            });      
        }
    </script>

    With the above modification, I am not able to reproduce the scenario where the DropDownTree is never populated. Could you test the example by selecting "Category 1" or "Category 2" which return data from the end-point and let me know if everything is working successfully on your end?

    Regards,
    Dimitar
    Progress Telerik
    Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
  5. Patrick
    Patrick avatar
    7 posts
    Member since:
    Jul 2016

    Posted 06 Nov 2018 in reply to Dimitar Link to this post

    Hi Dimitar,

    This solution sort of works apart from the fact that no child nodes are rendered, this is even the case within the project that you attached.

    My old DropDownTree was written as follows.

    @(Html.Kendo().DropDownTreeFor(a => a.ParentCategoryId)
                                                .DataTextField("Name")
                                                .DataValueField("id")
                                                .Placeholder("Select Category")
                                                .HtmlAttributes(new { style = "width: 100%" })
                                                .DataSource(dataSource =>
                                                dataSource.Read(read =>
                                                    read.Action("GetCategorylist", "Setting").Type(HttpVerbs.Post).Data("filterCategories"))
                                                    .ServerFiltering(true))
                                                .AutoBind(false)
                                                .Events(events => events
                                                .Change("DropdownTreeChange"))
                            )

     

    Take note of the following DataSource.Type(HttpVerbs.Post).Data("filterCategories"), i was using this additional .Data() to pass the BranchId to the controller action method and by removing this based on the solution you provided when clicking on the DropDownTree i got an error stating "Request Failed".

     

    The new DropDownTree view was written as follows

    @(Html.Kendo().DropDownTreeFor(a => a.ParentCategoryId)
                                                .DataTextField("Name")
                                                .DataValueField("id")
                                                .Placeholder("Select Category")
                                                .HtmlAttributes(new { style = "width: 100%" })
                                                .LoadOnDemand(false)
                                                .DataSource(dataSource =>
                                                dataSource.Read(read =>
                                                    read.Action("GetCategorylist", "Setting"))
                                                    .ServerFiltering(true))
                                                .AutoBind(false)
                                                .Events(events => events
                                                .Change("DropdownTreeChange"))
                            )

     

    Even by switching .LoadOnDemand(true) does not ever obtain any child nodes.

     

  6. Dimitar
    Admin
    Dimitar avatar
    676 posts

    Posted 08 Nov 2018 Link to this post

    Hi Patrick,

    Indeed you are correct that the children nodes are not being bound correctly when using the setDataSource() method. In order to workaround the issue, I would suggest to use the .data() method of the DataSource (the HierarchicalDataSource inherits all of the methods of the DataSource) to change the data set as follows:
    $.ajax({
      ...         
      success: function (result) {
        ddt.dataSource.data(result);
      }
    });

    If you modify the previously attached solution with the above, you will notice that when selecting the "Category 1" or "Category 2" values from the DropDownList, the DropDownTree will be successfully populated with the required data.

    I will also continue my investigation on the setDataSource() method issue and update you in this thread with additional details about my findings. 

    Regards,
    Dimitar
    Progress Telerik
    Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
  7. Dimitar
    Admin
    Dimitar avatar
    676 posts

    Posted 21 Nov 2018 Link to this post

    Hi Patrick,

    I have investigated the issue with the setDataSource further - what the method actually does is completely replace the existing dataSource of the widget and rebind it. Thus, it modifies the previously set remote transport and leads to the observed result.

    Instead of the above, you could try the following approach:

    1) Pass a custom parameter with the read request to the server through the Data() method as follows:
    @(Html.Kendo().DropDownTreeFor(m => m.HierarchicalID)
      ...
      .DataSource(d => d
        .Read(read =>
        {
          read.Action("GetEducationAvailableTree", "Home").Data("onData");
        })
      )
    )
     
    <script>
      function onData(e) {
        var ddl = $("#CategoryID").getKendoDropDownList();
     
        return {
          categoryId: ddl.value() !== "" ? ddl.value() : 0
        }
      }
    }

    2) On DropDownList change event, just call the DropDownTree's dataSource.read() method, which will trigger a request to the already defined remote end-point by passing the desired parameter:
    unction onCategoryChange(ev) {
      var ddt = $("#HierarchicalID").getKendoDropDownTree();
      var selectedValue = ev.sender.value();
     
      ddt.dataSource.read();
    }


    Regards,
    Dimitar
    Progress Telerik
    Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
Back to Top