Angularjs:自定义双向绑定属性指令

Angularjs: custom two-way binding attribute directive

我必须编写一个具有以下行为的指令:

控制器:

vm.mymodel = 'Hello World'

Html:

<custom-input mydirective="{propbind: 'data-value', propmodel: vm.mymodel}"></custom-input>

我希望我的自定义输入转换如下:

<custom-input data-value="{{vm.mymodel}}"></custom-input>

这就是我尝试做的事情:

var app = angular.module('myApp', []);
app.controller('myctrl', function($scope) {
  var vm = this;
  this.mymodel = 'Hello world !';
});

app.directive('mydirective', function () {
      return {
        restrict: 'A',
        replace: false,
        transclude: false,
        scope: {
          bindingvalue: '='
        },
        compile: function(element) {
          //remove the element for clarity
          element.removeAttr('mydirective'); 
        },
        link: function($scope, elem, attr) {
          //set the attribute
          attr.$set($scope.bindingvalue.propbind, $scope.bindingvalue.propmodel);
          //Observe the attribute value for changes
          attr.$observe($scope.bindingvalue.propbind, function(value) {
            $scope.bindingvalue.propmodel = value;
          })
        },
        controller: function($scope, $element) {
          //Nothing here yet
        }
      }
    });
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>

<div ng-app="myApp" ng-controller="myctrl as vm">
  <input mydirective="{propbind: 'data-value', propmodel: vm.mymodel}" type="text"/>
  model value : {{vm.mymodel}}
</div>

你能帮帮我吗?我的逻辑对我的问题有好处吗?我认为如果我设法在我的 link 函数中获得我的范围值,everythink 就可以工作。

谢谢

这应该有效:

var app = angular.module('myApp', []);
app.controller('myctrl', function($scope) {
  var vm = this;
  vm.mymodel = 'Hello world !';
});

app.directive('customInput', function () {
      return {
        restrict: 'EA',
        scope: {
          value: '='
        },
        template: '<input type="text" ng-model="value" />',
        controller: function($scope, $element) {
          //Nothing here yet
        }
      }
    });
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>

<div ng-app="myApp" ng-controller="myctrl as vm">
  <custom-input data-value="vm.mymodel"> </custom-input>
  model value : {{vm.mymodel}}
</div>

我终于成功了。这是我的解决方案:

var app = angular.module('myApp', []);
app.controller('myctrl', function ($scope) {
  var vm = this;
  vm.mymodel = 'Hello world !';
  vm.changeModel = function() {
    vm.mymodel = 'New Value'
    console.log(document.getElementById('myinput'))
  }
  vm.changeAttribute = function() {
    document.getElementById('myinput').setAttribute('data-value', '123456789');
    console.log(document.getElementById('myinput'))
  }
});

app.directive('mydirective', function ($timeout, $interval) {
  return {
    restrict: 'A',
    replace: false,
    transclude: false,
    scope: {
      propbind: '@',
      model: '='
    },
    link: function (scope, elem, attr) {
      attr.$set(scope.propbind, scope.model);

      //Watch model for changes, and update attribute
      scope.$watch(function () {
        return scope.model
      }, function () {
        attr.$set(scope.propbind, scope.model);
      });

      //Watch for changes in attribute, and update model
      scope.$watch(function () {
        return elem[0].getAttribute(scope.propbind);
      }, function (value) {
        $timeout(function () {
          scope.model = value;
        });
      });

      //Get attribute value for angularjs to reevaluate dom
      $interval(function () {
        var val = elem[0].getAttribute(scope.propbind)
      }, 100);
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>

<div ng-app="myApp" ng-controller="myctrl as vm">
  <input id="myinput" mydirective propbind="data-value" model="vm.mymodel" type="text"/>
  model value : {{vm.mymodel}}
  <div>
  <button ng-click="vm.changeModel()">change model value</button>
  <button ng-click="vm.changeAttribute()">change model value</button>
  </div>
  {{document.getElementById('myinput')}}
</div>

该演示使用基本输入而不是我的自定义输入,因此它实际上并未绑定到数据值属性。 但是,您可以单击这两个按钮来更新控制器中的模型或数据值属性。 您可以看到,如果我更改控制器中的值,数据值就会更新。 此外,如果您更新输入的数据值,模型会在控制器中更新。