0

I need to populate an angular table when data from a websocket is received: I tried with:

<div ng-controller="MyCtrl" ng-app="myapp">
        <table ng-table="commentsTable">
            <tr ng-repeat="item in obj track by $index">
            <td class="plantCell">{{item.nome}}: </td>
            <td class="statusCell">{{item.status}}</td>
            <td class="statusCell">{{item.testo}}</td>
        </tr>
        </table>
        </div>
<script>
    var app=angular.module('myapp', []);
    var printOperation;
    function GetFromLocalStorage(key) {
        var items=localStorage.getItem(key);
        console.log(items);
        if (items===null){
            console.log("item null");
            return null;
        } else {
            if (typeof items!= "string") {items = JSON.stringify(items);}
                    return items;
        }
    }
    app.controller('MyCtrl',    
                function ($scope) {
                    $scope.printComments=function (){
                        $scope.obj=GetFromLocalStorage("AllComments");
                        console.log("ricevo evento e ricarico tabella");
                        console.log($scope.obj);
                        //$scope.commentsTable.reload();
                    }

                    console.log("assegno print operation");
                    printOperation=$scope.printComments;
                }
            );  
            var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
            var eventer = window[eventMethod];
            var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
            eventer(messageEvent,function(e) {
                console.log("ricevo messaggio");
                printOperation();
            },false);
<script>

Uncaught TypeError: Cannot read property 'reload' of undefined at $scope.printComments ((index):68) at (index):80

Fabrizio Bartolomucci
  • 4,948
  • 8
  • 43
  • 75

1 Answers1

1

If you are using ngTable you should inject it into your app module like angular.module("myapp", ["ngTable"]);.

UPDATE: So after discussing the issue and getting more context on this I can assume that the data is modified outside of AngularJS context in event listener so the view doesn't show the updated value, so I assume wrapping printOperation with $applyAsync should help:

printOperation = $scope.$applyAsync($scope.printComments);

Also I think that the logic should be in one place - inside the controller for example, since it will make the code more readable and maintainable.

Stanislav Kvitash
  • 4,614
  • 18
  • 29
  • And how do I reload it? angular.module("myapp", ["ngTable"]).reload(); produces the same error. Moeover I am inside the module, I should not need to reference it. Moreover I need to update it each time a new push is received. – Fabrizio Bartolomucci Aug 03 '17 at 14:45
  • You need to inject it on this line `var app=angular.module('myapp', ['ngTable']);`. But are you really using the [`ngTable`](http://ng-table.com)? Since you will also need to inject [`NgTableParams`](http://ng-table.com/api-docs/classes/ngtableparams.html) into your controller and properly initialize them to use together with the `ng-table` directive. Or do you want to simply render the table using `ng-repeat`? The why you ever need to call `reload()` on something? Simply updating `$scope.obj` should do the trick. – Stanislav Kvitash Aug 03 '17 at 14:52
  • Unfortunately it does not, if I update obj after the table is rendered empty nothing is shown when the data arrives. I need to update the table each time the server submits updated data by websocket. Perhaps if I dynamically create the table the first time I am done, but I am back at the beginning when I need to update the table again. – Fabrizio Bartolomucci Aug 03 '17 at 15:24
  • Does `console.log($scope.obj);` shows the updated data? Can you also try removing `track by` for now to see if it plays some role? – Stanislav Kvitash Aug 03 '17 at 15:29
  • Moreover if I insert ['ngTable'] I get error: [$injector:modulerr] – Fabrizio Bartolomucci Aug 03 '17 at 15:32
  • Yes, the console.log shows the data is there. Removing track by index changes nothing. – Fabrizio Bartolomucci Aug 03 '17 at 15:33
  • So there is something definitely with your code. Can you post a bit more about the part where data comes via websockets and how you are trying to update the scope object? `[$injector:modulerr]` this error comes because you are not using `ngTable` and haven't added its sources into your code base. – Stanislav Kvitash Aug 03 '17 at 15:38
  • That is not a problem. When new data arrives that is saved in the localStorage and an even is sent. At the time I receive the event I correctly load the data on the table bound variable and I would like to reload it. – Fabrizio Bartolomucci Aug 03 '17 at 16:02
  • I modified the code to show the event triggering the reload. – Fabrizio Bartolomucci Aug 03 '17 at 16:03
  • @FabrizioBartolomucci please check the updated answer and see if this helps you. – Stanislav Kvitash Aug 04 '17 at 06:50
  • I submitted a more specific question at: https://stackoverflow.com/questions/45500905/reloading-angular-table-does-not-work-when-the-data-is-loaded-in-response-to-an – Fabrizio Bartolomucci Aug 04 '17 at 07:41
  • @FabrizioBartolomucci But still my update should answer your question, you are trying to modify data outside of agularjs application, in this case to sync the view the digest cycle should run, so you have to tell angularjs to run it and update the view. Take a look at this question - [How do I use $scope.$watch and $scope.$apply in AngularJS?](https://stackoverflow.com/questions/15112584/how-do-i-use-scope-watch-and-scope-apply-in-angularjs), its detailed answers should help you to understand how it works. – Stanislav Kvitash Aug 04 '17 at 09:17
  • I am not going to watch something in the page, but rather to change a table when an asyncronous event from an outside page arrives. – Fabrizio Bartolomucci Aug 04 '17 at 09:24
  • When writing something like `` or `{{item.nome}}` you are already forcing angularjs to create watchers for the variables, that is how 2-way data binding works. But to update the view, $digets cycle should run and dirty checking should be performed. Have you tried to use `$scope.$applyAsync` or `$scope.$apply` and see if it works for you? – Stanislav Kvitash Aug 04 '17 at 09:30
  • Of course, I use that mechanism elsewhere. How do I use $scope.$applyAsync? – Fabrizio Bartolomucci Aug 04 '17 at 09:38
  • @FabrizioBartolomucci added the working snippet in your second question. – Stanislav Kvitash Aug 04 '17 at 09:54