1

What is the best practise to create a get/set property in an angular factory that will be set by a controller in view X and get by the same controller using view Y? Should I be using $rootScope like below?

Factory:

angular.module('start.services').factory('bluetoothFactory', ['$q', '$window', '$rootScope', function($q, $window, $rootScope) {
 return {

  connectedDeviceSet:  function(device)
  {
    $rootScope.connectedDevice = device;
  },
  connectedDeviceGet: function()
  {
    return $rootScope.connectedDevice;
  },
...

Controller:

angular.module('start.controllers',[]).controller('bluetoothCtrl', function($scope, $ionicModal, $timeout, bluetoothFactory) 
{
...
$scope.list = function()
  {
    bluetoothFactory.list().then(function(data)
    {
      $scope.info = data;
      if (data.length > 0)
      {
        bluetoothFactory.connectedDeviceSet = data[0];
      }
    }, 
    function(error) 
    { 
      $scope.error = error;
    });
  };
$scope.readEPCForEncoding = function() 
{
   var device = bluetoothFactory.connectedDeviceGet;
   ....
}
Sonu Kapoor
  • 1,567
  • 3
  • 16
  • 34

3 Answers3

1

you should write in this way.

angular.module('start.services').factory('bluetoothFactory', ['$q', '$window', '$rootScope', function($q, $window, $rootScope) {

 return {
  connectedDevice : null,       
  connectedDeviceSet:  function(device)
  {
    this.connectedDevice = device;
  },
  connectedDeviceGet: function()
  {
    return this.connectedDevice;
  },

There is no need of $rootScope as it violate global scope.

Please refer this Plunker for better understanding.Check script.js

To set

bluetoothFactory.connectedDeviceSet(dataishere);

To get

var dataishere = bluetoothFactory.connectedDeviceGet();
RIYAJ KHAN
  • 15,032
  • 5
  • 31
  • 53
  • Thanks. I would then be able to use it my controller simply as bluetoothFactory.connectedDeviceGet? – Sonu Kapoor Jul 22 '15 at 10:15
  • I see. The problem is that the controller is first used from view X to set the connectedDevice, and then from view Y to get the connectedDevice. When I am in in Y to get the connectedDevice, I get a back a null object. – Sonu Kapoor Jul 22 '15 at 10:22
1

You should be using a service rather than a factory. Services should be defined as a prototype -- which translates to a class in other languages. Try not to access the $rootScope in your factories or services. This means you are not properly encapsulating your properties. This will cause collisions and strange errors.

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

function Bluetooth() {
  this.connectedDevice;
}

Bluetooth.prototype.setConnectedDevice = function(value) {
  this.connectedDevice = value;
}

Bluetooth.prototype.getConnectedDevice = function() {
  return this.connectedDevice;
}
app.service('bluetooth', Bluetooth);


DeviceController.$inject = ['bluetooth'];
function DeviceController(bluetooth) {
  this.bluetooth = bluetooth;
  
  this.device;
}

DeviceController.prototype.getDevice = function() {
  this.device = this.bluetooth.getConnectedDevice(); 
}

app.controller('DeviceController', DeviceController);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
  
  <div ng-controller="DeviceController as vm1">
    
    Controller 1: <br><br>
    
    <button ng-click="vm1.bluetooth.setConnectedDevice('Device set from instance one')">Set Device</button>     
    <br/><br>
    <button ng-click="vm1.getDevice()">Get Device</button>
    <br/><br>
    Device: {{vm1.device}}
    
    <br>
    Device in Service: {{vm1.bluetooth.connectedDevice}}
    
  </div>
  
  <br/> <br/>
  
  <div ng-controller="DeviceController as vm2">
    
    Controller 2: <br><br>
    
    <button ng-click="vm2.bluetooth.setConnectedDevice('Device set from instance Two')">Set Device</button>     
    <br/><br>
    <button ng-click="vm2.getDevice()">Get Device</button>
    <br/><br>
    Device: {{vm2.device}}
    
    <br>
    Device in Service: {{vm2.bluetooth.connectedDevice}}
    
  </div>

</div>

Then in your controller if you can either proxy the set and get methods or expose the bluetooth service to the view.

Click on the buttons in the two instances of the controller and watch how the device is set.

Martin
  • 15,820
  • 4
  • 47
  • 56
  • My answer still stands. Don't use the $rootScope. Use a service with a constructor function and methods added to the prototype of the constructor. – Martin Jul 22 '15 at 16:09
  • When I call getConnectedDevice, I get null back though. The setConnectedDevice is populating the object. But remember that the set is happening from controller X and get is executing from controller Y. – Sonu Kapoor Jul 22 '15 at 17:50
  • So yo can run the example in my answer. You will see there are two instances of the controller. Each exposes the device in the service as well as can set the device. For another working example, see: http://stackoverflow.com/questions/27720707/how-to-communicate-between-controllers-of-two-different-modules-in-angularjs/27721056#27721056 – Martin Jul 22 '15 at 18:33
0

simple and effective if you want same data in every controller.and you dont need to store data in $rootScope its worst.

app.factory('bluetoothFactory', function($http) {
    function Test() {
        var context = this;
        this.data= [];
        this.connectedDeviceGet= function() {
                return this.data;
        };
       this.connectedDeviceSet= function(data) {
                this.data = data;
        };
    }
    //get instance
    var self;

    function get() {
        if (self) {
            return self;
        } else {
            var self = new Test();
            return self;
        }
    }

    return {
        get: get
    };

});


//can access like this.
app.controller('testCtrl',function(bluetoothFactory){
    var service = bluetoothFactory.get();
    service.connectedDeviceSet([1,2]);
});
Joseph Persico
  • 602
  • 7
  • 20
ngLover
  • 4,439
  • 3
  • 20
  • 42