Textarea ng-bind,其中value有一个前缀和后缀

Textarea ng-bind, where value has a prefix and suffix

本文关键字:前缀 后缀 有一个 value ng-bind 其中 Textarea      更新时间:2023-09-26

我正在尝试完成一些在我看来应该相当简单的事情。当使用像文本输入这样的东西时,它也是。我试图创建模型绑定,在一个文本区,其中的值,当用户键入,显示一个前缀和后缀。前缀和后缀为引号:

“My awesome quote”

问题是,我目前正在使用ng模型,我当然不能使用这个。我在考虑绑定到一个变量,保留不带前缀和后缀的值,然后观察该变量。当具有原始值的变量发生变化时,我将带前缀和后缀的值写入作用域上的另一个变量。当用户键入时,该变量将显示在文本区域中。唯一的问题是,与输入字段不同,textarea没有value属性。

这可能吗?

编辑

如果我想通过输入文本字段实现这一点,我将创建一个名为a的变量,以保存用户键入时更改的原始值。当A发生变化时,它将获取原始值,在其周围加上引号,并将新值存储在另一个变量中,也在作用域中。这个新变量叫做B

然后输入字段将对A变量使用ng-bind,并使用输入字段值属性显示来自B变量的内容。如下所示:

<input type="text" ng-bind="A" value="{{B}}">

我现在没有时间创建小提琴,但我将在本周晚些时候尝试这样做。以上描述都是理论上的,因为我还没有测试过。

您的需求非常有趣,可以分为两个主要功能:

1。在不影响模型值的情况下为视图值添加前缀和后缀

这已经通过NgModelController实现了。我在ngModelController.$viewValue上创建了一个监视器,每当它发生变化时,如果它不包含前缀或后缀,我就添加这些值。

2。不要让用户干扰前缀或后缀

这有点棘手,但我找到了一个聪明的方法来获取和设置输入或文本区域元素的插入符号位置。

下面是一个工作示例:

angular
  .module('myApp', [])
  .directive('beautifyText', function() {
    return {
      link: function(scope, iElement, iAttrs, ngModelController) {
        // Adds the prefix and suffix
        (function() {
          var prefix = iAttrs.beautifyTextWithPrefix;
          var suffix = iAttrs.beautifyTextWithSuffix;
          ngModelController.$parsers.push(function(value) {
            if (angular.isString(value)) {
              return value.replace(new RegExp('^' + prefix), '').replace(new RegExp(suffix + '$'), '');
            }
            return '';
          });
          scope.$watch(function() {
            return ngModelController.$viewValue;
          }, function(newValue) {
            if (angular.isString(newValue) && newValue.length > 0) {
              if (angular.isString(ngModelController.$modelValue) && ngModelController.$modelValue.length === 0 && newValue.length === 1) {
                ngModelController.$viewValue = '';
                ngModelController.$render();
                return;
              }
              if (!isBeautifiedWithPrefix(newValue)) {
                ngModelController.$viewValue = prefix + newValue;
              }
              if (!isBeautifiedWithSuffix(newValue)) {
                ngModelController.$viewValue = newValue + suffix;
              }
              ngModelController.$render();
            } else {
              ngModelController.$viewValue = '';
              ngModelController.$render();
            }
          });
          function isBeautifiedWithPrefix(value) {
            return value.match(new RegExp('^' + prefix)) !== null;
          }
          function isBeautifiedWithSuffix(value) {
            return value.match(new RegExp(suffix + '$')) !== null;
          }
        })();
        // Changes the caret position
        (function() {
          var element = iElement[0];
          // https://stackoverflow.com/questions/7745867/how-do-you-get-the-cursor-position-in-a-textarea#answer-7745998
          function getCursorPos() {
            if ("selectionStart" in element && document.activeElement == element) {
              return {
                start: element.selectionStart,
                end: element.selectionEnd
              };
            } else if (element.createTextRange) {
              var sel = document.selection.createRange();
              if (sel.parentElement() === element) {
                var rng = element.createTextRange();
                rng.moveToBookmark(sel.getBookmark());
                for (var len = 0; rng.compareEndPoints("EndToStart", rng) > 0; rng.moveEnd("character", -1)) {
                  len++;
                }
                rng.setEndPoint("StartToStart", element.createTextRange());
                for (var pos = {
                  start: 0,
                  end: len
                }; rng.compareEndPoints("EndToStart", rng) > 0; rng.moveEnd("character", -1)) {
                  pos.start++;
                  pos.end++;
                }
                return pos;
              }
            }
            return -1;
          }
          // https://stackoverflow.com/questions/7745867/how-do-you-get-the-cursor-position-in-a-textarea#answer-7745998
          function setCursorPos(start, end) {
            if (arguments.length < 2) {
              end = start;
            }
            if ("selectionStart" in element) {
              element.selectionStart = start;
              element.selectionEnd = end;
            } else if (element.createTextRange) {
              var rng = element.createTextRange();
              rng.moveStart("character", start);
              rng.collapse();
              rng.moveEnd("character", end - start);
              rng.select();
            }
          }
          iElement.bind('mousedown mouseup keydown keyup', function() {
            if (ngModelController.$viewValue.length > 0) {
              var caretPosition = getCursorPos();
              if (caretPosition.start === 0) {
                setCursorPos(1, caretPosition.end < 1 ? 1 : caretPosition.end);
              }
              if (caretPosition.end === ngModelController.$viewValue.length) {
                setCursorPos(caretPosition.start, ngModelController.$viewValue.length - 1);
              }
            }
          });
        })();
      },
      restrict: 'A',
      require: 'ngModel'
    }
  });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<div ng-app="myApp">
  <textarea ng-model="myVariable" beautify-text beautify-text-with-prefix="“" beautify-text-with-suffix="”"></textarea>
  <p>myVariable: {{ myVariable }}</p>
</div>

UPDATE

所以我使用了ng focus和blur来删除和添加引号,当他使用文本区域时,它不会是实时的,但它会工作

angular.module('myApp', [])
  .controller('demoCtrl', ['$scope',
    function($scope) {
      $scope.myModel = '';
      $scope.removeQuotes = function() {
        $scope.myModel = $scope.myModel.replace(/“|”/gm, ''); // remove the quotes
      }
      $scope.addQuotes = function() {
        if ($scope.myModel == '') {
          $scope.myModel = ''; // dont add the quotes for an empty value
          return;
        }
        $scope.myModel = "“" + $scope.myModel + "”" // add the quotes again
      }
    }
  ])
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
  <div ng-controller="demoCtrl">
    <textarea ng-model="myModel" ng-focus='removeQuotes()' ng-blur='addQuotes()'></textarea>
  </div>
</div>