mamsoudi
mamsoudi

Reputation: 4059

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/[email protected]/bundles/ng-table.min.css',
        'https://unpkg.com/[email protected]/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/[email protected]/bundles/ng-table.min.css',
        'https://unpkg.com/[email protected]/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?!

Upvotes: 1

Views: 536

Answers (1)

mamsoudi
mamsoudi

Reputation: 4059

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 :)

Upvotes: 1

Related Questions