This is a migrated thread and some comments may be shown as answers.

DropDownList parameter to Grid DataSource

12 Answers 872 Views
MVVM
This is a migrated thread and some comments may be shown as answers.
Kevin
Top achievements
Rank 1
Kevin asked on 28 Mar 2014, 12:43 PM
I want to have a DropDownList that provides a parameter to a DataSource that is used to populate a grid.  Following the example in this thread, I've got something like this.

<div id="MainDiv">
   @* This hidden input is what I'd like to get rid of. *@
   <input id="url" type="hidden" data-bind="value: Url" />
   <select id="ListsSelect" data-bind="value: selectedListID, source: lists" />
   <div id="AlbumsGrid" />
</div>
<script>
   (function ($, kendo) {
      var appAddr='@Url.Content("~/")';
 
      var viewModel = kendo.observable({
         albumsReadUrl: "",
         selectedListID: 1,
         lists: new kendo.data.DataSource({
            type: "odata",
            transport: { read: appAddr+"PickDataService.svc/Lists" },
            schema: { data: wcfData, total: wcfTotal }
         }),
         Url: function() {
            this.set("albumsReadUrl", appAddr+"PickService.svc/Foos?$filter=ListID%20eq%20"+this.get("selectedListID"));
            this.albums.read();
            return this.get("albumsReadUrl");
         },
         albums: new kendo.data.DataSource({
            type: "odata",
            transport: { read: { url: function() { console.log("read url"); return viewModel.albumsReadUrl; } } },
            schema: { data: wcfData, total: wcfTotal },
         })
      });
 
      $("#ListsSelect").kendoDropDownList({
         valuePrimitive: true, dataTextField: "Name", dataValueField: "ID"
      });
 
      $("#AlbumsGrid").kendoGrid({
         dataSource: viewModel.albums, scrollable: false, autobind: false, pageable: true,
      });
 
      kendo.bind($("#MainDiv"), viewModel);
   })(jQuery, kendo);
</script>


I'd like to see an example of how to rearrange it without using the hidden input.

12 Answers, 1 is accepted

Sort by
0
Petur Subev
Telerik team
answered on 01 Apr 2014, 10:59 AM
Hello Kevin,

I would suggest you to use the change event of the DropDownList and perform dataSource.read() request. You can pass an object to the read method whcih will be send as additional data.

Similar approach (however using the filter() instead of read()) is used in the following example:

http://demos.telerik.com/kendo-ui/web/grid/toolbar-template.html

You can still bind a function to the change event the same through data-bind attribute like demonstrated here:

http://demos.telerik.com/kendo-ui/web/dropdownlist/mvvm.html

Kind Regards,
Petur Subev
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
0
Kevin
Top achievements
Rank 1
answered on 10 Apr 2014, 12:45 PM
Thanks, Petur.  I have a related question about how the MVVM works.  My DataSource in my viewModel  now looks something like this: 

albums: new kendo.data.DataSource({
   transport: {
      read: { url: function() { return viewModel.albumsReadUrl); } },

and my DropDownList looks like this:

$("#ListsSelect").kendoDropDownList({
   valuePrimitive: true, dataTextField: "Name", dataValueField: "ID",
   cascade: function(e) {
      viewModel.set( "albumsReadUrl",
                     appAddr+"PickService.svc/Foos?$filter=ListID%20eq%20"+e.sender.value());
      viewModel.albums.read();
   }
});

Ideally, I'd like to not have to say "viewModel.albums.read()" after I update "albumsReadUrl" in the viewModel.  The MVVM engine, ideally, should note that albums.transport.read has a dependency on albumsReadUrl and call read itself.  I tried rewriting it like this:

         read: { url: function() { return viewModel.get("albumsReadUrl"); } },
 
$("#ListsSelect").kendoDropDownList({
   valuePrimitive: true, dataTextField: "Name", dataValueField: "ID",
   cascade: function(e) {
      viewModel.set( "albumsReadUrl",
                     appAddr+"PickService.svc/Foos?$filter=ListID%20eq%20"+e.sender.value());
      //viewModel.albums.read();
   }
});

but read doesn't get called.  Is there a way to introduce dependencies such that Kendo will call read automatically when the DropDownList changes?
0
Petur Subev
Telerik team
answered on 14 Apr 2014, 07:43 AM
Hello Kevin,

You could create function inside the viewModel which does both operations, instead of doing them inside the cascade handler.

e.g.

http://trykendoui.telerik.com/@pesho/Ahof

Kind Regards,
Petur Subev
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
0
Kevin
Top achievements
Rank 1
answered on 15 Apr 2014, 12:46 PM
So is there so no support in Kendo MVVM for something like WPF's IPropertyChanged?  In other words, there's no direct way for an observable to fire an event (or cause a function to run) when one of its properties changes?
0
Petur Subev
Telerik team
answered on 16 Apr 2014, 10:46 AM
Hello Kevin,

You can triggered your own event or the "change" event (which will notify all dependencies) like so:

http://docs.telerik.com/kendo-ui/api/framework/observable#methods-trigger

I am not sure I understand your question, basically if a field is changed, all other fields or functions that used it inside of it (they should use get("propertyName") ) will be notified, if they depend on something.

Here is an example:

http://trykendoui.telerik.com/@pesho/Ahof/2

Please have a detailed look and see that the function is not invoked at all if the depending field is not bound to the HTML.

Kind Regards,
Petur Subev
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
0
Kevin
Top achievements
Rank 1
answered on 03 May 2014, 09:38 PM
I realize this may seem to be a bit of an esoteric point and I hope I'm not belaboring it, but I'm just trying to confirm whether Kendo can support having a clean separation of the View and ViewModel.  In my examples it looks like the View is dependent upon the ViewModel and the ViewModel is also dependent upon the View.

Let me try to make this clear.  This example shows one way to make my grid update based upon a dropdown changing:

http://trykendoui.telerik.com/@illgble/ezIv/2

When the dropdown changes, the grid gets updated, but the update depends upon the cascade event handler, which is View logic, to do this.  The dropdown sets viewModel.selectedListID, but there's no way for the ViewModel to recognize itself that it has changed and to update its albums DataSource itself.  It's dependent upon the View to call viewModel.albums.read().

Another implementation is this one:

http://trykendoui.telerik.com/@illgble/ezIv/3

In this one there is no cascade event handler.  Instead we have viewModel.refreshAlbums, but it's necessary to add an element with 'data-bind="text: refreshAlbums"' to guarantee that refreshAlbums gets called.  refreshAlbums has a dependency on "selectListID" but unless some element is bound to it, it won't get called.

What's common in both of these cases is that the albums DataSource has a dependency upon selectedListID, but there's no way for the viewModel *itself* to keep its members updated.  The viewModel is dependent upon the View to do something extra (which the View isn't strictly interested in) to trigger the necessary changes in the viewModel.

I think that once the ListsSelect has notified the viewModel of a change to selectedListID, the View has fulfilled its responsibilities.  It shouldn't then have to tell the ViewModel, "Oh, by the way, since I've updated selectedListID your albums DataSource is now out of date."  The ViewModel itself should be able to respond to the selectedListID change and update albums on its own.  Is this possible?
0
Petur Subev
Telerik team
answered on 06 May 2014, 01:41 PM
Hello Kevin,

I understand what you are trying to achieve just from the first code snippet that you shared, however it is not possible to make the Grid 'know' about that the URL might change and when it changes it should perform a read.

Consider using the work-arounds that I shared.

I am sorry for any inconvenience caused.

Kind Regards,
Petur Subev
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
0
Kevin
Top achievements
Rank 1
answered on 06 May 2014, 02:38 PM
I think I'm still not being understood.  I'm not trying to make the Grid know anything.  The Grid already responds perfectly when the DataSource changes.  I'm trying to find a way to make the ViewModel, the observable, able to respond to changes to its own properties without involving the View.  In other words, can the observable observe itself?  Can I set up a function that observes an observable?
0
Petur Subev
Telerik team
answered on 07 May 2014, 07:16 AM
Hello Kevin,

My apologies, what I meant to say is DataSource not Grid. The observable object will observe its nested properties yes, however the DataSource that is part of your observable is not observable. 

Check the following example:

http://trykendoui.telerik.com/@pesho/AXOR


Kind Regards,
Petur Subev
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
0
Kevin
Top achievements
Rank 1
answered on 07 May 2014, 12:46 PM
That's interesting, but still not quite what I'm after.  Let me try asking this a different way.  In this example:

http://trykendoui.telerik.com/@illgble/ezIv/4

is there something I can bind to that will run when viewModel.selectedListID changes?

kd
0
Petur Subev
Telerik team
answered on 07 May 2014, 01:28 PM
Hello Kevin,

Please keep in mind that the URL that you shared in not reachable on our side.

Yes you can use the change event of the ViewModel:

http://trykendoui.telerik.com/@pesho/Afos

I hope this is what you are looking for.

Kind Regards,
Petur Subev
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
0
Kevin
Top achievements
Rank 1
answered on 10 May 2014, 09:01 PM
I've worked out what I was trying to do.  I don't know why this was like pulling teeth.  Here's an example:

http://trykendoui.telerik.com/@illgble/ezIv/5

The magic is that you can simply bind to the "change" event of an Observable and then check e.field for the Observable field you're interested in.  Like so:

viewModel.bind("change", function(e) { if (e.field=="selectedListID") alert("foo")})

Evidently, whenever something in the viewModel changes, the "change" event files and the event param "field" property will be set to the name of the thing that changed.  That's all I wanted.  Why isn't this documented in the Observable api?  I'm definitely not a javascript veteran so maybe my question was just so obvious it wasn't being understood.  I don't know.  Regardless, this seems to be the way to go about having the viewModel keep itself consistent without unnecessary support from the View.  If I'm doing something terribly wrong, I'd love for someone to explain to me how to do this properly.  But everything I've seen so far strikes me as ungood.
Tags
MVVM
Asked by
Kevin
Top achievements
Rank 1
Answers by
Petur Subev
Telerik team
Kevin
Top achievements
Rank 1
Share this question
or