Sonu Kapoor
Sonu Kapoor

Reputation: 1637

Correct way to set property in Angular Factory

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;
   ....
}

Upvotes: 1

Views: 3707

Answers (3)

ngLover
ngLover

Reputation: 4578

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]);
});

Upvotes: 0

Martin
Martin

Reputation: 16302

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.

Upvotes: 1

RIYAJ KHAN
RIYAJ KHAN

Reputation: 15292

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();

Upvotes: 1

Related Questions