Pietro Coelho Pietro Coelho - 3 months ago 12
AngularJS Question

Stop two way data binding on angular directive

I want to pass information to a directive like this:

<ui-message data="{{app}}"></ui-message>


Where in my controller I have the following:

app.controller("testCtrl", function($scope) {
$scope.app = "Hello World!"
})


And my directive:

app.directive("uiMessage", function() {
return {
template: "<h1>{{message}}</h1>",
scope: {
message: "@data"
}
}
})


That works fine, except that if
app
is bound to a model, it'll update the content inside the directive:

<input ng-model="app"> //typing here changes the content inside ui-message
<ui-message data="{{app}}"></ui-message>


How can I prevent this from happening?

gyc gyc
Answer

You can use the one time binding expression with ::

function uiMessage() {
  return {
    template: "<h1>{{::msg}}</h1>",
    scope: {
      msg: "="
    }
  }
}
function myController($scope) {
  $scope.message = "one way";
}
angular.module('myApp', []);
angular
    .module('myApp')
    .controller('myController', myController)
    .directive('uiMessage', uiMessage);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<div ng-app="myApp">
  <div ng-controller="myController">
    <input type="text" ng-model="message" />
    <ui-message msg="message"></ui-message>
  </div>
</div>

If it's really a one time thing you're after and you're not going to need the variable, you can use ng-transclude instead of creating a scope:

function uiMessage() {
  return {
    transclude: true,
    template: "<h1 ng-transclude></h1>"
  }
}
function myController($scope) {
  $scope.message = "one way";
}
angular.module('myApp', []);
angular
    .module('myApp')
    .controller('myController', myController)
    .directive('uiMessage', uiMessage);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<div ng-app="myApp">
  <div ng-controller="myController">
    <input type="text" ng-model="message" />
    <ui-message>{{::message}}</ui-message>
  </div>
</div>

Comments