Gabriel Ok
Gabriel Ok

Reputation: 87

How to dynamically change data between controllers in AngularJS

I have a factory on my script which returns an empty array. I want to be able to access this array from two different controllers and modify its data, like insert an object or a string.

'use strict';

var app = angular.module('invoiceApp');

app.factory('InvoiceFactory',[function() {
return {
  invoices: []
};

}]);

app.controller('MainCtrl',['$scope','InvoiceFactory', function ($scope, $http, socket, InvoiceFactory) {
 $scope.applyUnpaidFilter = function() {
    //filter invoices by unpaid
 }

 $scope.applyAllFilter = function() {
    //filter invoices by all
 }

}])
 .controller('InsertInvoiceController', function($scope, $modal) {
var modalInstance;

$scope.insertInvoice = function() {
  modalInstance = $modal.open({
    templateUrl: 'modals/InsertInvoice.html',
    controller: 'InvoiceModalController'
  });
};
 })
 .controller('InvoiceModalController',
          ['$scope','$modalInstance','InvoiceFactory', function($scope, $modalInstance, InvoiceFactory) {

$scope.ok = function() {
  InvoiceFactory.invoices = $scope.loadInvoices();
  $modalInstance.close('closing dialog');

};
$scope.cancel = function() {
  $modalInstance.dismiss('cancel');
};

$scope.loadInvoices = function() {
  var xlf = document.getElementById('xlf');
  handleSpreadsheet(xlf);
  var results = [];

  function handleSpreadsheet(e) {
    var files = e.files;
    var i, f;
    for(i = 0, f=files[i]; i != files.length; i++) {
      var reader = new FileReader();
      reader.onload = function(e) {
        var data = e.target.result;
        var wb;
        wb = XLSX.read(data, {type:'binary'});
        to_json(wb);
      };

      reader.readAsArrayBuffer(f);
    }
  }

  function to_json(workbook) {
    var result = {};
    workbook.SheetNames.forEach(function(sheetName) {
      var roa = XLSX.utils.sheet_to_row_object_array(workbook.Sheets[sheetName]);
      if(roa.length > 0) {
        result = roa;
      }
    });
    results = result;
  }

  function fixdata(data) {
    var o="", l=0, w=10240;
    for(; l<data.byteLength/w; ++l)
      o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l*w, l*w+w)));

    o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l*w)));
    return o;
  }
  return results;
}

 }])
 .controller('InvoiceDisplayController',['$scope', 'InvoiceFactory', function($scope, InvoiceFactory) {
  $scope.invoices = InvoiceFactory.invoices;
  console.log($scope.invoices.length);
 }]);

Sorry code is messy.

Upvotes: 0

Views: 261

Answers (1)

Logan Murphy
Logan Murphy

Reputation: 6230

Let me start of by saying that your declaration of the MainCtrl controller is incorrect

app.controller('MainCtrl',['$scope','InvoiceFactory', function ($scope, $http, socket, InvoiceFactory) {

Should be

app.controller('MainCtrl',['$scope','$http', 'socket', 'InvoiceFactory', function ($scope, $http, socket, InvoiceFactory) {

Otherwise the variable $http would store an InvoiceFactory singleton.

Anywhere you inject the InvoiceFactory you can alter its invoices like so

InvoiceFactory.invoices.push("Hello World");
InvoiceFactory.invoices.push("Goodbye Cruel World");
InvoiceFactory.invoices.splice(0, 1);

Or you can alter the scoped variable

$scope.invoices = InvoiceFactory.invoices;

$scope.invoices.push("Hello World");
$scope.invoices.push("Goodbye Cruel World");
$scope.invoices.splice(0, 1);

Keep in mind that you are actually not creating a factory here but a service. Note that angular.factory == angular.service evaluates to true. So you can replace your call to factory with service and it will work exactly the same but be a bit more readable.

Here is a simple filddle demonstrating this

http://jsfiddle.net/m3grjo9t/

Upvotes: 1

Related Questions