Search code examples
javascriptangularjsangular-ui-gridui-grid

Using controller in a directive


Angular newbie here. I am trying Brian's example of importing data into UI Grid from Excel. This works like a charm. Brian uses a custom directive. I am able to read the excel file perfectly. After reading excel data in the directive i want to check the excel data columns with the existing UI-grid table in the controller. After confirming that all the columns are present in the excel i need to save it in my database.

To do that, I am not able to access gridApi from the directive. Not sure where i am going wrong. Any help is highly appreciated! Thanks in advance!

Here's the simplified version of the code which just logs the GridApi / any Scope variable ( from controller) in the directive.

app.js

var crApp_WCF = angular.module('crApp_WCF', ['ngRoute', 'crApp_WCF_Ctrls', 'crServices', 'ui.grid', 'crApp_WCF_Drtvs', 'ui.grid.edit', 'ui.grid.exporter', 'ui.grid.selection']);

controller.js

var crApp_WCF_Ctrls = angular.module('crApp_WCF_Ctrls', ['crServices', 'ui.grid.exporter']);

crApp_WCF_Ctrls.controller('crHomeCtrl', function ($scope,$rootScope, $http, uiGridConstants, CrCRUD, uiGridExporterService, uiGridExporterConstants) {
$scope.crGrid = {
$scope.crGrid.onRegisterApi = function (gridApi) {
columnDefs: [
     { name: 'OppName', field: 'OppName', enableFiltering: false, minWidth: 100, headerTooltip: true, enableCellEdit: false },
            { name: 'AcCode', field: 'AcCode', enableFiltering: false, minWidth: 60, headerTooltip: true, enableCellEdit: false },
            ]}
        $scope.gridApi = gridApi;
    };

directives.js

var crApp_WCF_Drtvs = angular.module('crApp_WCF_Drtvs', ['crApp_WCF_Ctrls']);

crApp_WCF_Drtvs.directive("fileread", [function () {
    return {
controller: 'crHomeCtrl',
       scope: {
            gridApi: '='
        },
        link: function ($scope, $elm, $attrs, $rootScope) {
            $elm.on('change', function (changeEvent) {

                     Console.log(($scope.gridApi) //displays Undefined; I want the gridApi from the controller to be displayed here.
});
        }
    }
}]);

Index.html

<div ng-controller="crHomeCtrl">
    <form class="form-inline">
        <button type="button" class="btn btn-success" ng-click="exportXLSX()">Export as XLSX</button>
        <button type="button" class="btn btn-success" ng-click="showImport=true">Import from excel</button>
        <button type="button" class="btn" ng-click="showImport=false" ng-show="showImport">Close</button>
        <br />
        <br />

        <div ui-grid="crGrid" ui-grid-edit ui-grid-exporter ui-grid-selection class="CrGrid">
            <div class="grid-msg-overlay" ng-show="showImport">
                <div class="msg">
                    <div class="center">
                        <span class="muted">Select Spreadsheet File</span>
                        <br />
                        <input type="file" accept=".xls,.xlsx,.ods" fileread opts="vm.gridOptions" multiple="false" />
                        <br/>
                        {{msg}}
                    </div>
                </div>
            </div>
        </div>
</div>
</form>

Solution

  • Solution no. 1: why not inject the controller instead in link function. This returns the parent controller of the directive where it was placed.

    crApp_WCF_Drtvs.directive("fileread", [function () {
      return {
       scope: {
            gridApi: '='
        },
        link: function ($scope, $elm, $attrs, controller) {
          $elm.on('change', function (changeEvent) {
    
            // console.log(controller.gridApi);
          });
        }
      }
    }]);
    

    Solution no. 2: You already set scope: { gridApi: '=' } why not make use of it.

    // JS
    crApp_WCF_Drtvs.directive("fileread", [function () {
      return {
       scope: {
            gridApi: '='
        },
        link: function ($scope, $elm, $attrs) {
          $elm.on('change', function (changeEvent) {
    
            // console.log($scope.gridApi);
          });
        }
      }
    }]);
    
    // HTML
    <input type="file"
           accept=".xls,.xlsx,.ods"
           fileread
           opts="vm.gridOptions"
    // give gridApi scope variable for fileread directive to get
           grid-api="gridApi"
           multiple="false" />
    

    hope that helps