0

I am trying to update a data stored in a controller (this.isUploaded) from a directive (I want to bind the update to an action on a DOM element (in this example, on a click, in my application, on a file upload through drag drop)). Based on what I read, the best way to do it is to inject a service which would act as a brdige between the two parts of the application with a data binding. The whole code I use is the following (inspired from this post, which do not work with directives) :

<body>
  <div ng-controller="navController as navCtrl">
    <p>isUploaded: {{navCtrl.isUploaded}}</p>
    <div test-view></div>
  </div>
</body>

And for the JavaScript:

angular.module('testApp', [])
  .directive('testView', ['CreateBindingService', function(createBindingService) {
    return {
      restrict: 'EA',
      template: '<a href="#">Incrementation</a>',
      link: function(scope, element, attrs) {
        element.bind('click', function(e) {
          createBindingService.incrementIsUploaded();
          console.log(createBindingService.getIsUploaded());
        });
      }
    };
  }])
  .factory('CreateBindingService', function() {
    var isUploaded = 1;
    return {
      getIsUploaded: function() {
        return isUploaded;
      },
      incrementIsUploaded: function() {
        isUploaded++;
        return isUploaded;
      }
    };
  })
  .controller('navController', ['CreateBindingService', function(createBindingService) {
    this.isUploaded = createBindingService.getIsUploaded();
  }]);

The log does behave as expected (each click on the increment changes the value stored in the service), but the value in the model is not updated.

I tried to have a look at $watch, but so far, nothing really happens, so it seems to be more of a binding problem than an update one.

Could it be because of my use of this.isUploaded instead of $scope.isUploaded? Indeed, most of the posts I've seen uses of the latter, while I use the former (I learnt the basis of Angular on Code School, where they don't use $scope).

I do know that there are simpler ways to do it (in this context, it's obious, and even my "fancy" drag and drop file upload thing could probably be replaced by a way simpler directive. However, I still think that getting an answer to my question would help me to better understand how Angular works.

But if, you suggest a fundamentally different way to tackle the problem, I'm interested :)

1
  • get a scope parameter into your controller, set the 'isUploaded' on the scope instead of the controller. Commented Nov 2, 2014 at 21:08

1 Answer 1

1

It seems that bind event ours outside Angular scope so you can use it scope.$apply inside your directive. And change isUploaded to complex type please see demo below.

angular.module('testApp', [])
  .directive('testView', ['CreateBindingService',
    function(createBindingService) {
      return {
        restrict: 'EA',
        template: '<a href="#">Incrementation</a>',
        link: function(scope, element, attrs) {
          element.bind('click', function(e) {
            scope.$apply(function() {
              createBindingService.incrementIsUploaded();
              console.log(createBindingService.getIsUploaded());
            });
          });
        }
      };
    }
  ])
  .factory('CreateBindingService', function() {
    var data = {
      isUploaded: 1
    };
    return {
      getIsUploaded: function() {
        return data.isUploaded;
      },
      incrementIsUploaded: function() {
        data.isUploaded++;
        return data;
      },
      data: data
    };
  })
  .controller('navController', ['CreateBindingService',
    function(createBindingService) {
      this.data = createBindingService.data;
    }
  ]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<body ng-app="testApp">
  <div ng-controller="navController as navCtrl">
    <p>isUploaded: {{navCtrl.data.isUploaded}}</p>
    <div test-view></div>
  </div>
</body>

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.