AngularJS Custom Directive Two Way Binding

前端 未结 5 1061
甜味超标
甜味超标 2020-12-29 08:17

If I have an AngularJS directive without a template and I want it to set a property on the current scope, what is the best way to do it?

For example, a directive tha

相关标签:
5条回答
  • 2020-12-29 08:49

    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();
                });
            }
        };
    }]);
    
    0 讨论(0)
  • 2020-12-29 09:05

    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();
                    });
                }
            };
        }
    );
    
    0 讨论(0)
  • 2020-12-29 09:09

    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.

    0 讨论(0)
  • 2020-12-29 09:11

    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.

    0 讨论(0)
  • 2020-12-29 09:12

    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.

    0 讨论(0)
提交回复
热议问题