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

时间:2019-03-01 11:33:28

标签: angularjs binding scope attributes 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>
  • 当我从控制器更新vm.mymodel时,data-value属性必须更改。
  • 当我更新数据值时,也必须更新vm.mymodel。
  • 我不能在自定义输入上使用ng-mmodel指令(它使用数据值,并且已应用内部函数)

所以这是我尝试做的事情:

  • 在我的指令的编译功能中,将scope.propbind属性值设置为“ {{propmodel}}”,然后删除“ mydirective”属性。但我似乎无法在此处访问范围。但是,如果我使用element.attr('data-value','hello world'),我可以看到我的data-value设置正确
  • 我尝试在链接函数中执行相同的操作,但是我的范围的值未定义
  • 我也尝试过使用控制器功能,但我的范围也为空,而且我无法访问attr或element。

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>

你能帮我吗?我的逻辑对我的问题有益吗?我认为,如果我设法在链接函数中获取范围值,那么一切都可以。

谢谢

2 个答案:

答案 0 :(得分:0)

这应该有效:

exists
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
        }
      }
    });

答案 1 :(得分:0)

我终于设法使它起作用。这是我的解决方案:

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>

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