Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS: how to use a factory with two-way data binding

Tags:

angularjs

EDIT: Working plunker: http://plnkr.co/edit/iInh7TnbGvSHSPOWuWPk?p=preview

====================================================================

In the following plunker: http://plnkr.co/edit/TIfkYE?p=preview

A very simple example compares the usage of a factory and a service. Two way data-binding works using the service but not the factory. Why?

With the service:

<button btn-radio="item.nb" ng-model="fromService.current>

clicking the button correctly updates the property current of the service fromService.

However, using a factory:

<button btn-radio="item.nb" ng-model="fromFactory.current>

clicking the button does not update the property current of the factory fromFactory.

My use case is the following: I want to use a service/factory to share data across controllers and other services.

I have read a lot references, including:

  • http://iffycan.blogspot.be/2013/05/angular-service-or-factory.html
  • http://docs.angularjs.org/api/AUTO.$provide
  • https://gist.github.com/Mithrandir0x/3639232
  • What is the 'new' keyword in JavaScript?
  • http://zeekat.nl/articles/constructors-considered-mildly-confusing.html
like image 498
apairet Avatar asked Dec 27 '13 00:12

apairet


People also ask

Does AngularJS support two way binding?

AngularJS creates a two way data-binding between the select element and the $ctrl.

What technique does AngularJS used for two way binding?

Two-way data binding is achieved by using the ng-model directive. The ng-model directive transfers data from the view to the model and from the model to the view.

Is two way binding possible in Angular?

The two-way data binding in Angular is used to display information to the end user and allows the end user to make changes to the underlying data using the UI. This makes a two-way connection between the view (the template) and the component class.

How is 2 way data binding implemented?

For two-way data binding, declare a private property and access its value using get and set methods in the component class. Then, assign that property to [(ngModel)] . For example, declare a private property with a get and set method, as shown below. Now, assign userName to [(ngModel)] in the template.


2 Answers

The problem is var current is a primitive and when you initialize the object using it as a value, it will not create a reference to intial variable, the object property will just take it's value.

WIthin your isCurrent function you are then making comparison to the original variable, which never changes. The current property however is changed by the 2 way binding you created with ng-model

Simple example ( can paste this in your browser console to confirm):

var current=0;
var obj={
  current: current
}

current=10;
alert(obj.current)// hasn't changed, is still 0

To fix your factory you need to make your comparisons to the object returned from factory

myApp.factory('fromFactory', function() {
  console.log("factory is called");
    var current = 0;
    return {
        current: current,
        isCurrent: function (nb) {

           /* change return nb === current;*/

          /* compare to the object version of "current" which is bound to ng-model*/
          return nb === this.current;
          },
        printCurrent: function () {
          console.log("print fromFactory", this.current);
        }
    };
});
like image 101
charlietfl Avatar answered Sep 28 '22 06:09

charlietfl


Another Solution is to construct an object and return it:

myApp.factory('fromFactory', function() {

    console.log("factory is called");

    var exports = {};
    exports.current = 0;
    exports.isCurrent = function (nb) {
          return nb == exports.current;
    };
    exports.printCurrent = function () {
        console.log("print fromFactory", exports.current);
    };

    return exports;
});

Both this and charlietfl solutions work perfectly. Working plunker: http://plnkr.co/edit/iInh7TnbGvSHSPOWuWPk?p=preview

like image 21
apairet Avatar answered Sep 28 '22 06:09

apairet