AngularJS Custom Directive Two Way Binding

感情迁移 提交于 2019-12-02 21:58:42

Why is an isolate scope overkill? its pretty useful for exactly this kind of thing:

  scope: {
     "twoway": "=" // two way binding
  },

This is a pretty idiomatic angular solution to this problem, so this is what I'd stick with.

I'm surprised no one has mentioned ng-model, the default directive for doing two-data binding. Maybe it's not so well known, but the linking function has a fourth parameter:

angular.module('directive-binding', [])
  .directive('twoway', 
      function() {
        return {
          require: '?ngModel',
          link: function(scope, elem, attrs, ngModel) {
            elem.on('click', function() {
              var counter = ngModel.$viewValue ? ngModel.$viewValue : 0
              ngModel.$setViewValue(++counter);
              scope.$apply();
            });
          }
        };
      }
    );

On your view

<button twoway ng-model="counter">Click Me</button>
<p>Click Count: {{ counter }}</p>

The fourth parameter is an API for the ngModelController, which has many uses for handling (parsing and formatting, for instance) and sharing data between a directive and a scope.

Here's the updated Plunker.

You can definitely simplify it a bit like this without using $parse

angular.module('directive-binding', []).directive('twoway', [function () {
    return {
        scope: false,
        link: function (scope, elem, attrs) {
            elem.on('click', function () {
                scope[attrs.twoway] = scope[attrs.twoway] == null ? 1 : scope[attrs.twoway] + 1;
                scope.$apply();
            });
        }
    };
}]);

A great way to apply two way binding is to use directive components. Here is my solution. It allows use of ng-repeat and expandable data binding.

View Plunker

HTML

<body ng-controller='MainCtrl'>  
    Data: {{data}}
    <hr>
    <mydirective name='data[0]'></mydirective>
    <hr>
    <mydirective name='data[1]'></mydirective>
</body>

Controller

app.controller('MainCtrl', function($scope) {
  $scope.data = [];
  $scope.data[0] = 'Marco';
  $scope.data[1] = 'Billy';
});

Directive

app.directive("mydirective", function(){
    return {
        restrict: "EA",
        scope: {name: '='},
        template: "<div>Your name is : {{name}}</div>"+
        "Change your name : <input type='text' ng-model='name' />"
    };
});

In the case of the counter, it can be done using the same method.

Change template to:

<button twoway bind="counter">Click Me</button>
<p>Click Count: {{ counter.val }}</p>

and directive to:

.directive('twoway',
    function() {
        return {
            scope: {
                localValue: '=?bind'
            },
            link: function(scope, elem, attrs) {
                scope.localValue = {
                    val: 0
                };
                elem.on('click', function() {
                    scope.localValue.val = scope.localValue.val + 1;
                    scope.$apply();
                });
            }
        };
    }
);
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!