Persist data source set from JavaScript

12 posts, 0 answers
  1. Jaesoon
    Jaesoon avatar
    51 posts
    Member since:
    Oct 2012

    Posted 12 May Link to this post

    I'm trying to get a multi select box to refresh it's values after selecting a value from a drop down list. I am currently using server side filtering and paging (i.e. not all items are loaded when you load the control and so scrolling will keep loading items as needed)

     

    Initially the multi select is getting its data value set in the Read method like so

     

    transport.Read("GetItems", "Items", new { id = @Model.Id });

    At this stage, the ID parameter (from the model) it passes in is 0 and so no items are loaded in the Multi Select control.

     

    I now have a drop down box with a change event attached to it. On the change event I want to refresh the data on the multi select so I do the following using JavaScript:

    var multiSelect = $("#multiSelectControl").data("kendoMultiSelect");
     
    multiSelect.dataSource.read({ id: value });

     

    On the controller, i can see that the ID value is coming through correctly and the Multi Select loads the correct value items. (e.g. 25, 26 etc)

     

    However the problem comes in when i start scrolling the multi select list. When the next items are "loading" it seems the controller is being hit again with the value from the original datasource (i.e. 0) and so removes everything from the Multi Select control.

     

    How can I make it so any further reads of the data source uses the new parameter that i've set in JavaScript?

    t
     
     
     
    ransport.Read("GetItems", "Items", new { id = @Model.Id });
    transport.Read("GetItems", "Items", new { id = @Model.Id });
  2. Ianko
    Admin
    Ianko avatar
    1535 posts

    Posted 14 May Link to this post

    Hello Jaesoon,

    You should rather change the options of the DataSource widget. And then just call read() with no parameters. 

    For example:
    var multiSelect = $("#multiSelectControl").data("kendoMultiSelect");
    multiSelect.dataSource.options.transport.read.url = "/Items/GetItems/" + value;
    multiSelect.dataSource.read();

    The code might need to be fixed as I have tested the situation with different values, but the idea is the same. 

    Regards,
    Ianko
    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. Jaesoon
    Jaesoon avatar
    51 posts
    Member since:
    Oct 2012

    Posted 27 Jun in reply to Ianko Link to this post

    Hi Ianko

     

    Unfortunately, this does not seem to work for me as my extra parameters always comes up with the default value when the page is first loaded.

     

    My controller defines the following parameters:

    [DataSourceRequest] DataSourceRequest request, int objectId

     

    And so i have tried 

    multiSelect.dataSource.options.transport.read.url = "/Items/GetItems/" + value;

    multiSelect.dataSource.options.transport.read.url = "/Items/GetItems/GetItemsList=" + value;

    multiSelect.dataSource.options.transport.read.url = "/Items/GetItems?GetItemsList=" + value;

     

    But the passed in extra parameter is always set to 0.

     

    I can see on the network activity that the URL address is properly set but i can't get the extra parameter to pass over.

     

    As mentioned in my previous post, adding the parameter in the read method (like so: multiSelect.dataSource.read({ id: value });) will pass the data back to the controller, however the problem with this is that any sort of virtualisation will mess it up. (it will pass in the default value of 0 instead of the changed value).

     

    Thanks for your help.

  5. Jaesoon
    Jaesoon avatar
    51 posts
    Member since:
    Oct 2012

    Posted 27 Jun in reply to Jaesoon Link to this post

    Sorry, i cant edit my post, i was meant to say my javascript passes in the parameters 

    multiSelect.dataSource.options.transport.read.url = "/Items/GetItems/objectId=" + value;
    multiSelect.dataSource.options.transport.read.url = "/Items/GetItems?objectId=" + value;

    To be what the controller needs.

     

  6. Jaesoon
    Jaesoon avatar
    51 posts
    Member since:
    Oct 2012

    Posted 27 Jun in reply to Jaesoon Link to this post

    Sorry I can't edit my previous post as I didn't type it properly

     

    The script call i'm making is as follows:

    multiSelect.dataSource.options.transport.read.url = "/Items/GetItems/objectId=" + value;
    multiSelect.dataSource.options.transport.read.url = "/Items/GetItems?objectId=" + value;

     

    But the parameters are still not returning properly.

  7. Ianko
    Admin
    Ianko avatar
    1535 posts

    Posted 28 Jun Link to this post

    Hello Jaesoon,

    Can you provide a simple, locally runnable project that illustrates the difficulty encountered so that I can properly examine the exact situation? I suggest you using a single page solution with hard-coded values as I guess this should be a matter of a single action method to be called from the client.

    Regards,
    Ianko
    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
  8. Jaesoon
    Jaesoon avatar
    51 posts
    Member since:
    Oct 2012

    Posted 08 Jul in reply to Ianko Link to this post

    Hi Ianko

     

     

    I have attached a zip file containing the project folder,

     

    In the index.cshtml file, you will find a combobox and a multiselect control.

    The multi select control has got a default parameter defined in its read method (passes in 0).

    There is javascript on the file which gets hit on the combobox change event, from there you can see what the original URL is and the modified URL is.

    However when it hits the read method of the controller, the parameter does not get changed (e.g. drop down has selected 3 and the URL is set to use the right link, however the read method has 0 as the parameter still).

     

    Please have a look and let me know if theres anything else that's needed.

     

    I have removed the bin folder (which can be recreated when you build the solution) and also the kendo folder in the content and scripts folder (so that none of the kendo files will be exposed). Please add them back to the solution before running the sample The kendo scripts folder uses version 2016.2.607.

     

    Thanks

  9. Ianko
    Admin
    Ianko avatar
    1535 posts

    Posted 11 Jul Link to this post

    Hello Jaesoon,

    The problem is that the .Type("aspnetmvc-ajax") is configured. This type of setting is to be be used internally for wrappers utilizing the DataSourceRequest class. MultiSelect is not among them and I can only guess why this setting is used.

    With this setting, the mechanism of the request processed is different and this is why the request URL actually cannot be changed programmatically. 

    You can see that if you comment out the .Type() setting in the MultiSelect and the [HttpPost] attribute for the GetItems method the request will be properly sent with the changed ID. 

    Regards,
    Ianko
    Telerik by Progress
    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
  10. Jaesoon
    Jaesoon avatar
    51 posts
    Member since:
    Oct 2012

    Posted 12 Jul in reply to Ianko Link to this post

    Hi Ianko

     

     

    Unfortunately that is not possible as I have read your documentation for virtualisation (and also tested it), the [.Type("aspnetmvc-ajax")] is required for the controller to send back the data, as it is using [return Json(itemsList.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);]

     

    Removing the HttpPost and .Type settings will cause the filter to not work at all (i.e. typing in to filter items in the multi select, opening up a control with existing values in it).

     

    I have figured out another way which works partially but still has issues as shown below.

    multiSelect.dataSource.transport.parameterMap = function(data, type) {
        if (type == "read") {
            return { request: kendo.stringify(data), id: 3 }
        }
    };

     

    By doing this, i can get the id parameter to be passed in correctly, however the [DataSourceRequest] object has all the parameters missing, which also causes issues with filtering.

     

    This following method is more desirable than the one you've suggested above as at least with this one, virtualisation works when you open up this control with existing values.

     

    So if I can't get your method to work without having to remove the .Type and HttpPost values, how can i return the correct DataSourceRequest object when im using the parametermap option?

     

    Thanks

  11. Ianko
    Admin
    Ianko avatar
    1535 posts

    Posted 13 Jul Link to this post

    Hi Jaesoon,

    You are right, in order to have the DataSource utilities like sorting, filtering and so on you should use this type of technique.

    What I meant, however, is that you cannot programmatically change the DataSource instance from the client when it is of type aspnetmvc-ajax. This is because it is intended to be used internally and all options after the instance initialization are disregarded. Shortly, whatever is configured in the MVC wrapper it cannot be changed on the client by changing the options. 

    The solution to your case is to actually reinitilize the entire DataSource object assigned to the multiSelect.dataSource property. And this is how you could do that:

    function onChange(e) {
        var value = this.value();
     
        var multiSelect = $("#required").data("kendoMultiSelect");
         
        var newOptions = $.extend(multiSelect.dataSource.options, {
            transport: {
                read: {
                    url:"/Home/GetItems/" + value
                }
            }
        });
     
        multiSelect.dataSource = new kendo.data.DataSource(newOptions);
        multiSelect.dataSource.read();
    }

    I hope that helps.

    Regards,
    Ianko
    Telerik by Progress
    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
  12. Jaesoon
    Jaesoon avatar
    51 posts
    Member since:
    Oct 2012

    Posted 13 Jul in reply to Ianko Link to this post

    Hi Ianko

     

    Sorry but as i've stated before, i HAVE to use 

    return Json(items.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);

    [note the "ToDatSourceResult" method - which requires the control to have ".Type("aspnetmvc-ajax")" set]

     

    If i do not use ToDatSourceResult, the returning object i get is NULL. Again i have to use this for the server side virtualisation of the multi select list, which can have a large number of data.

     

    I have just tried your method that you have suggested, and I can see that the Json query returns data, but it does not populate the multi select list (I am guessing its due to the new data source?).

     

    The only way that I have got the multi select to populate (when i have server side virtualisation enabled) to work is by modifying the parameter map as posted above.

     

    I need to stress that the key point of difference here is that my multi select box has server side filtering enabled, this means:

    1) using just the ".read()" operation will NOT pass in any new parameters if the controller has "HttpPost" and multi select control has ".Type" enabled (as we have found out)

    2) using the ".read()" operation will NOT populate the multi select if i comment out the "HttpPost" on the controller and comment out the ".Type" enabled.

    and finally

    3) using the new data source options that you have suggested will NOT work, as I have virtualisation and server side filtering enabled, i.e. i need to use a custom source with parameter maps.

     

    Can you show me how to modify the parameter map as i have posted previously so that it passes in the correct "DataSourceRequest" item? This is the only way that my multi select with virtualisation and server side filtering will work.

     

    Thanks

  13. Ianko
    Admin
    Ianko avatar
    1535 posts

    Posted 13 Jul Link to this post

    Hello Jaesoon,

    As said, with this scenario it is difficult to achieve this. Indeed, the suggested solution does not help as actually miltiselect widget disregards the new DataSource.

    So, a much more complex solution would be to entirely wipe out the MultiSelect on the client and recreate a new one. Like so:
    function onChange(e) {
        var value = this.value();
     
        var multiSelect = $("#required").data("kendoMultiSelect");
        var wrapper = multiSelect.wrapper;
     
        var obj = {
            "dataSource": {
                "type": "aspnetmvc-ajax",
                "transport": {
                    "read": {
                        "url": "/Home/GetItems/" + value,
                        "data": function () { return kendo.ui.MultiSelect.requestData(jQuery("#required")); }
                    }
                },
                "pageSize": 80,
                "page": 0,
                "total": 0,
                "serverPaging": true,
                "serverFiltering": true,
                "filter": [],
                "schema": { "data": "Data", "total": "Total" }
            }
        };
     
        var newOptions = $.extend(multiSelect.options, obj);
     
        multiSelect.destroy();
        wrapper.kendoMultiSelect(newOptions);
    }
     
    If you have UI issues with the widget, consider wiping out even the DOM element and create a new one. 


    Basically, it is not easy to have the power of the built-in DataSource features and have the possibility to manually control the binding mechanism programmatically.

    Regards,
    Ianko
    Telerik by Progress
    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
Back to Top
UI for ASP.NET MVC is VS 2017 Ready