2

I have a requirement of showing the excel data on UI, for this i used ui-grid and was able to show the excel data in ui-grid. But only one sheet data gets load in ui-grid. If I am using the excel which has multiple sheets, I want to show all the sheet names in dropdown on UI and on the basis of the sheet selected the data respective to that sheet should get populated. I am able to see the data in JSON form in the directive being used but I am not able to populate the sheet names in dropdown This is the plunker for what have been done yet

http://plnkr.co/edit/9oU2dcOWtke8dt7PWSk6?p=preview

This is the directive code and controller code:

angular.module('app', ['ui.grid'])

.controller('MainCtrl', ['$scope', function ($scope) {
  var vm = this;

  vm.gridOptions = {};

  vm.reset = reset;
  //I want to use that JSON in controller so that i can show the values in grid
  function reset() {
    vm.gridOptions.data = [];
    vm.gridOptions.columnDefs = [];
  }
}])

directive("fileread", [function () {
  return {
    scope: {
      opts: '='
    },
    link: function ($scope, $elm, $attrs) {
      $elm.on('change', function (changeEvent) {
        var reader = new FileReader();

        reader.onload = function (evt) {
          $scope.$apply(function () {
            var data = evt.target.result;

            var workbook = XLSX.read(data, {type: 'binary'});

//I want to pass the workbook object to controller, as it has all the required data

            var headerNames = XLSX.utils.sheet_to_json( workbook.Sheets[workbook.SheetNames[0]], { header: 1 })[0];
            //I get all the sheet names of excel through workbook.SheetNames, I want to show this sheet names in dropdown and on basis
            //of the sheet selected it should load data of that sheet in the ui-grid, workbook.Sheets consists of data of all the Sheets present in Excel 

$scope.sheetName=workbook.SheetNames;//Passed the sheet names to scope variable var data = XLSX.utils.sheet_to_json( workbook.Sheets[workbook.SheetNames[0]]);

            $scope.opts.columnDefs = [];
            headerNames.forEach(function (h) {
              $scope.opts.columnDefs.push({ field: h });
            });

            $scope.opts.data = data;

            $elm.val(null);
          });
        };

        reader.readAsBinaryString(changeEvent.target.files[0]);
      });
    }
  }

enter image description here

In sheetNames I am able to see all the sheet names, but in the dropdown I get a blank dropdown

enter image description here

This is the HTML:

<!DOCTYPE html>
<html ng-app="app">

  <head>
    <link data-require="bootstrap-css@*" data-semver="3.3.1" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.16/angular.js"></script>
    <script src="https://cdn.rawgit.com/SheetJS/js-xlsx/v0.8.0/dist/xlsx.full.min.js"></script>
    <script src="https://cdn.rawgit.com/SheetJS/js-xlsx/v0.8.0/dist/ods.js"></script>
    <script src="http://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/release/3.0.0-rc.22/ui-grid.min.js"></script>
    <link rel="stylesheet" href="http://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/release/3.0.0-rc.22/ui-grid.min.css" />
    <link rel="stylesheet" href="main.css" type="text/css" />
  </head>

  <body>
    <div ng-controller="MainCtrl as vm">
      <button type="button" class="btn btn-success" ng-click="vm.reset()">Reset Grid</button>
      <br />
      <br />
      <div id="grid1" ui-grid="vm.gridOptions" class="grid">
        <div class="grid-msg-overlay" ng-show="!vm.gridOptions.data.length">
          <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="true" />
            </div>
          </div>
        </div>
          <select ng-model="names" ng-options="names as names for names in sheetName"></select>
    <pre>
      {{sheetNames | json}}
    </pre><!-- Dropdown is coming blank-->
    </div>
      </div>
    </div>
    <script src="app.js"></script>
  </body>

</html>

Please suggest how can i achieve the requirement, how can i pass the Json or object from directive to controller. It would be a great help.

3 Answers 3

1

You need to pass the sheetNames varible to directive. like how you pass opts.

I updated the plnkr check the below

http://plnkr.co/edit/RQJW1D6iYjZmMEeSedCU?p=preview
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you!! Your solution worked. But is there any way i can pass the workbook object to controller or can store it in services as I need to show the respective sheet data on ui-grid whenever any sheetname is selected. So need to store the workbook object temporarily so that i can fetch the data from there easily and on other pages too. Please suggest
This is what exactly, i was trying to achieve.. Thank you so much for your help.!! :)
0

The only idea that pops in my mind is to use a service to do that. Even if it's the simplest one, just give it a property and a get/setter, and you should be able to send your data from the directive to your controller (assuming, of course, that you injected its dependency in both components).

here it is :

angular
    .module('app')
    .factory('dataExchanger', dataExchanger);

dataExchanger.$inject = ['dependencies'];

/* @ngInject */
function dataExchanger(dependencies) {

    var data = {};

    var service = {
        getData: getData,
        setData: setData
    };
    return service;
    ////////////////
    function getData() {
        return data;
    }

    function setData(param) {
        data = param;
    }
}

4 Comments

Thank you for your help, can you please show me how this can be used by editing in plunker, it tried your solution but not able to get the exact result. This is the plunker I am using plnkr.co/edit/9oU2dcOWtke8dt7PWSk6?p=preview. It would be a great help from your side
TypeError: Cannot read property 'setData' of undefined at app.js:33 at Scope.$eval (angular.js:14547) at Scope.$apply (angular.js:14646) at FileReader.reader.onload (app.js:28) Getting this error, while running the plunker
and my error is Error: data is not defined, which is pretty much the same. The error comes from your directive, which uses link, and has no controller. You need to add a controller to your directive in order to make it work.
0

I think your controller is not aware of the change you made.

You are calling $scope.apply but this only get the directive to update it's values?

Try calling $scope.$root.$apply(). This fixed the issue in this case but I am not sure whether this is a good pattern.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.