javascriptangularjsngtableangular-componentsoclazyload

lazyloading ngTable using ocLazyLoad


In one our projects we're trying to write a wrapper around ngTable library! in this component's controller, we're loading ngTable using ocLazyLoad. Here's what we've written:

Datagrid Component

(function() {

  'use strict';

  angular
    .module('CommonApplication')
    .component('datagrid', {
      scope: true,
      bindings: {
        basepath: '@',
        title: '@',
        dataset: '<'
      },
      templateUrl: '/frontend/components/global/datagrid/templates/datagrid.html',
      controller: 'DataGridController',
    });

})();

Datagrid Controller with $ocLazyLoad (Doesn't work :~| )

(function() {

  'use strict';

  angular
    .module('CommonApplication')
    .controller('DataGridController', 
    [ '$scope', '$injector', '$ocLazyLoad', DataGridController ]);

  function DataGridController($scope, $injector, $ocLazyLoad) {

    var vm = this;
    var components = {
      datagrid: [
        'https://unpkg.com/ng-table@2.2.0/bundles/ng-table.min.css',
        'https://unpkg.com/ng-table@2.2.0/bundles/ng-table.min.js'
      ]
    };

    $ocLazyLoad.load(components.datagrid).then(function() {
      var NgTableParams = $injector.get('NgTableParams');
      vm.data = [{name: "Moroni", age: 50},{name: "Moroni", age: 50},{name: "Moroni", age: 50},{name: "Moroni", age: 50}];
      vm.tableParams = new NgTableParams({
        page: 1,
        count: 10
      }, {
        dataset: vm.data
      });
    });
  }

})();

Datagrid Controller without $ocLazyLoad (Works)

(function() {

  'use strict';

  angular
    .module('CommonApplication')
    .controller('DataGridController', 
    [ '$scope', '$injector', '$ocLazyLoad', DataGridController ]);

  function DataGridController($scope, $injector, $ocLazyLoad) {

    var vm = this;
    var components = {
      datagrid: [
        'https://unpkg.com/ng-table@2.2.0/bundles/ng-table.min.css',
        'https://unpkg.com/ng-table@2.2.0/bundles/ng-table.min.js'
      ]
    };

    var NgTableParams = $injector.get('NgTableParams');
    vm.data = [{name: "Moroni", age: 50},{name: "Moroni", age: 50},{name: "Moroni", age: 50},{name: "Moroni", age: 50}];
    vm.tableParams = new NgTableParams({
      page: 1,
      count: 10
    }, {
      dataset: vm.data
    });
  }

})();

Using ocLazyLoad, If I set a breakpoint on the line that we're defining vm.tableParams when it get populated by new NgTableParams the settings and other properties of it have this particular error in their arguments properties.


Here's the Exception Error which points to the end of $ocLazyLoad.then function callback! It's datagrid.js:47:7 because we concat these js file and another one into datagrid.js:

TypeError: 'caller' and 'arguments' are restricted function properties and cannot be accessed in this context.
    at Function.remoteFunction (<anonymous>:3:14)
    at http://localhost:8081/frontend/components/global/datagrid/datagrid.js:47:7
    at http://localhost:8081/frontend/javascripts/head.min.js:136:20
    at m.$eval (http://localhost:8081/frontend/javascripts/head.min.js:150:347)
    at m.$digest (http://localhost:8081/frontend/javascripts/head.min.js:147:420)
    at http://localhost:8081/frontend/javascripts/head.min.js:150:434
    at e (http://localhost:8081/frontend/javascripts/head.min.js:50:444)
    at http://localhost:8081/frontend/javascripts/head.min.js:53:300

Any Thoughts on this?!


Solution

  • Apparently, lazy loading even using its promise .then(callback) doesn't make Angular wait for its completion!

    What I was doing is to initialize a table using ngTableParams when loading of ng-table finishes! With this on mind, I decided to use a simple trick!

    I attached ngTableParams to a Scope variable called vm.tableParams which later I will use to initialize the table in the view with it right when using ng-table's directive. So even before calling the directive which hasn't been loaded yet we check if the lazy loading is completed or not using ng-if and tableParams:

    View: datagrid.pug

    // Load Directive if Params in the controller were attached to the scope!
    .row.expanded(ng-if="table.tableParams")
        .small-12.columns 
          table.data-table.hover.stacktable.table-condensed.table-bordered.table-striped(ng-table-dynamic="table.tableParams with table.headers",template-pagination="custom/pager", show-filter="true")
            tr(ng-repeat="(rowIndex, row) in $data ")
              td(ng-repeat="column in $columns", ng-switch="column.field")
                input.selectSwitch( ng-switch-when="selector", type="checkbox", ng-model="table.checkboxes.items[row.id]") 
                div(ng-switch-when="id") {{ rowIndex + 1 }}
                div(ng-switch-when="body") {{ row }}
                span(ng-switch-default) {{row[column.field]}}
    

    Controller: datagrid.controller.js

    // Lazyload datagrid components and Initialize headers and parametres!
        $ocLazyLoad.load(components.datagrid).then(function (){
          self.headers = self.dataset.headers;
          self.dataset.headers.forEach(function( header ) {
            header.title = header.headerTitle;
          });
          var NgTableParams = $injector.get('NgTableParams');
          self.tableParams = new NgTableParams({
            count: 5
          }, {
            dataset: self.dataset.data
          });
        });
    

    This way we won't be using $compile manually to re-render the view and we let angular handle the compilation itself, not affecting the Performance :)