0

I use a factory as a singleton. I want to access the scope of a controller from this factory. It boils down to following code:

angular.module('foo', [])
.controller('fooCtrl', function($scope, testFac) {
    $scope.example = "I wanna change";

    testFac.change = function(change){
        $scope.example = change;
    }
})

.factory('testFac', function($timeout){
    var testFac= {}

    $timeout(function(){
        testFac.change("You changed")
    }, 3000)

    return testFac;
})

at the moment im declaring the function in the controller, because then im in the right scope, and i can call the function from the factory. but it doesnt seem to be a very elegant solution. Is there a better way to solve this? For testing purposes, see this fiddle

2 Answers 2

2

I use a factory as a singleton

Factories/Services/Providers are singletons

I want to access the scope of a controller from this factory.

Its not good practice to manipulate with scopes inside factory. In angular the scopes for controllers only to bind View to Controller.

About your code:

.factory('testFac', function($timeout){
    var testFac= {}

    $timeout(function(){
        testFac.change("You changed")
    }, 3000)

    return testFac;
})

Its not purpose of factory. You can write second controller or directive

Is there a better way to solve this?

Yes, you can use $broadcast

Dispatches an event name downwards to all child scopes (and their children) notifying the registered $rootScope.Scope listeners.

Sign up to request clarification or add additional context in comments.

1 Comment

well you might as well use factories with return function(){...} and let obj = new testFac()` as classes - which is not a singleton. I want to avoid using broadcast in this case, because it complicates debugging. especially broadcasting from $rootscope, as it affects every childscope - which I consider bad practise
0

Push Values from a Service with RxJS

I want to avoid using broadcast

Build a service with RxJS Extensions for Angular.

<script src="//unpkg.com/angular/angular.js"></script>
<script src="//unpkg.com/rx/dist/rx.all.js"></script>
<script src="//unpkg.com/rx-angular/dist/rx.angular.js"></script>
var app = angular.module('myApp', ['rx']);

app.factory("DataService", function(rx, $timeout) {
  var subject = new rx.Subject(); 
  var data = "I wanna change";

  $timeout(function(){
      subject.onNext("You changed");
  }, 3000);
  
  return {
      set: function set(d){
        data = d;
        subject.onNext(d);
      },
      get: function get() {
        return data;
      },
      subscribe: function (o) {
         return subject.subscribe(o);
      }
  };
});

Then simply subscribe to the changes.

app.controller('displayCtrl', function(DataService) {
  var $ctrl = this;

  $ctrl.data = DataService.get();
  var subscription = DataService.subscribe(function onNext(d) {
      $ctrl.data = d;
  });

  this.$onDestroy = function() {
      subscription.dispose();
  };
});

Clients can subscribe to changes with DataService.subscribe and producers can push changes with DataService.set.

The DEMO.

angular.module('app', ['rx'])

.factory("DataService", function(rx, $timeout) {
  var subject = new rx.Subject(); 
  var data = "I wanna change";

  $timeout(function(){
      subject.onNext("You changed");
  }, 3000);

  return {
      set: function set(d){
        data = d;
        subject.onNext(d);
      },
      get: function get() {
        return data;
      },
      subscribe: function (o) {
         return subject.subscribe(o);
      }
  };
})

.controller('ctrl', function(DataService) {
  var $ctrl = this;

  $ctrl.data = DataService.get();
  var subscription = DataService.subscribe(function onNext(d) {
      $ctrl.data = d;
  });

  this.$onDestroy = function() {
      subscription.dispose();
  };
})
<script src="//unpkg.com/angular/angular.js"></script>
<script src="//unpkg.com/rx/dist/rx.all.js"></script>
<script src="//unpkg.com/rx-angular/dist/rx.angular.js"></script>


<body ng-app="app" ng-controller="ctrl as $ctrl">
    <h1>RxJS DEMO</h1>
    <p>Data= {{$ctrl.data}}</p>
</body>

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.