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

问题描述 投票:0回答:2

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

控制器:

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-model指令(它使用数据值,并且应用了内部函数)

所以这就是我试图做的事情:

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

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>

你能帮我么 ?我的逻辑对我的问题有好处吗?我认为,如果我设法在我的链接功能中获取我的范围值,那么每个方面都可以工作。

谢谢

angularjs binding scope attributes directive
2个回答
0
投票

这应该工作:

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>

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>

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

© www.soinside.com 2019 - 2024. All rights reserved.