19

I am combining Telerik Kendo grid with Angular using the Angular Kendo UI project.

I have the following markup:

<div kendo-grid="" k-options="thingsOptions" style="height: 600px;" />

and the following code in my controller:

    $scope.thingsOptions = {
        dataSource: {
            type: "json",
            transport: {
                read: "/OM/om/getAssets",
                dataType: "json"
            },
            schema: {
                model: {
                    id: "ProductID",
...

This all works fine however I would like to force a data source refresh of my grid from my controller. something like

 $scope.getTasks = function() {
    $scope.thingsOptions.dataSource.read();
};

Is this possible to do from the controller? I could always do something like

$("#taskGrid").data("kendoGrid").dataSource.read();

In my controller. But it seems a bit wrong to have to select a HTML element from my controller.

numaroth
  • 1,295
  • 4
  • 25
  • 36
David Kethel
  • 2,440
  • 9
  • 29
  • 49

3 Answers3

18

Just pass in a scope variable to the directive, then inside of your controller you can use the variable to call whatever widget methods you need.

<div kendo-grid="grid" ...></div>

<script>
  ...

  $scope.getTasks = function() {
    // scope.grid is the widget reference
    $scope.grid.refresh();
  }

  ...
</script>

Ref: http://blogs.telerik.com/kendoui/posts/14-02-26/a-few-angular-kendo-ui-best-practices

micjamking
  • 2,183
  • 1
  • 21
  • 24
  • 1
    Great answer, but unfortunately this doesn't work if you change dataSource and columns. The KendoUi-Grid doesn't support defining columns after the widget is created - as is stated here: http://kendo-labs.github.io/angular-kendo/#/grid-widget. Any idea how to achieve that? Probably you have to go to another route and thus reload the child template ... – Agent_K Jun 02 '15 at 21:58
  • I can confirm this as well. I had to use $scope.grid.dataSource.read(). I'm using the 2015.3.930 library. – Halcyon Oct 08 '15 at 21:30
  • You have to pass in $scope to use those methods. – micjamking Apr 20 '16 at 06:34
  • @micjamking somehow this doesn't work, I solved my problem with by [this answer](http://stackoverflow.com/a/28333323/2435473) – Pankaj Parkar Apr 22 '16 at 13:55
11

Your datasource must be a kendo object

$scope.thingsOptions = {
        dataSource: new kendo.data.DataSource({
                    type: "json",
                    transport: {
                        read: "/OM/om/getAssets",
                        dataType: "json"
                    },
                    schema: {
                        model: {
                            id: "ProductID",

then it is possible to call

$scope.thingsOptions.dataSource.read();
Vivz
  • 6,625
  • 2
  • 17
  • 33
Yakub
  • 205
  • 2
  • 9
-1

So I recently struggled with this as well.

The key, it seams is to call the .read() function on the Datasource object. Unfortunately, i've only found out how to do this from a jQuery style call like this:

angular.element('#theGrid').data("kendo-grid").dataSource.read(); 

Now of all that, the id selector "#theGrid" will depend on your implementation and what your containing div is Id'd as. Confusingly, the .data("kendo-grid") bit is hard coded in the Angular directive and will be the same regardless of your implementation.

I know you're not supposed to do Dom Manipulation in Angular, but needing to lazy-load a complex Kendo grid necessitated a bit of angular magic/hacking. I created a "refresh grid" function that enables a promise-based flow control over a dom-element so that I can refresh the grid after the grid has instantiated itself. Here's an example implementation of that:

#this is in a service called KendoGridService, so understand the context.
stop: undefined,
    refreshGrid: function() {
    // don't queue another refresh of the grid.
    if (angular.isDefined(KendoGridService.stop)) return;

    var element = angular.element("#kgrid");
        KendoGridService.stop = $interval(function() {
            if(angular.element("#kgrid").data("kendo-grid")){
            KendoGridService.stopRefreshLoop(element);
            }
        }, 100, 10);
    },
    stopRefreshLoop: function(element) {
        if (angular.isDefined(KendoGridService.stop)) {
        angular.element("#kgrid").data("kendo-grid").dataSource.read();
        $interval.cancel(KendoGridService.stop);
        KendoGridService.stop = undefined;
        }
    },

With this in place, you can now do the basic load of your grid data, then refresh it after your (presumably promised based) updates complete by calling (in this case):

KendoGridService.refreshGrid();

that method uses the $interval service built into Angular to run itself every 100ms, for a maximum of 10 iterations. IF during any of those iterations, the dom element is found, the stopRefreshLoop method is called.

As far as hacks go, i think it's on the "more elegant" side of hacks.

Kevin P
  • 189
  • 2
  • 9