Angularjs: пользовательская директива атрибута двустороннего связывания - PullRequest
0 голосов
/ 01 марта 2019

Я должен написать директиву, которая будет иметь следующее поведение:

Контроллер:

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 должен измениться.
  • Когда я обновляю data-значение, vm.mymodel также должен быть обновлен.
  • Я не могу использовать директиву ng-mmodel для пользовательского ввода (он использует значение данных и к нему применены внутренние функции)

Итак, вот что я пытался сделать:

  • В функции компиляции моей директивы установите значение атрибута scope.propbind равным "{{propmodel}}", а затем удалите "mydirective""атрибут.Но у меня, похоже, нет доступа к этой области.Однако, если я использую element.attr ('data-value', 'hello world'), я вижу, что мои data-value правильно установлены
  • Я попытался сделать то же самое в функции link, но значения моей области видимостине определены
  • Я также пробовал в функции контроллера, но моя область также пуста, плюс у меня нет доступа к 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>

Можете ли вы мне помочь?Моя логика хороша для моей проблемы?Я думаю, что если мне удастся получить значения моей области в моей функции ссылки, все мысли могут работать.

Спасибо

Ответы [ 2 ]

0 голосов
/ 01 марта 2019

Мне наконец удалось заставить это работать.Вот мое решение:

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.Однако вы можете нажать две кнопки, чтобы обновить модель в контроллере или атрибут data-value.Вы можете видеть, что если я изменю значение в моем контроллере, значение данных будет обновлено.Также, если вы обновите значение данных ввода, модель будет обновлена ​​в контроллере.

0 голосов
/ 01 марта 2019

Это должно работать:

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>
...