使用AngularJS在textarea中的插入位置

Mar*_*rek 6 data-binding scope caret angularjs

我问自己,我做得对不对.我遇到的问题是我想在AngularJS更新textarea值后保留插入位置.

HTML看起来像这样:

<div ng-controlle="editorController">
    <button ng-click="addSomeTextAtTheEnd()">Add some text at the end</button>
    <textarea id="editor" ng-model="editor"></textarea>
</div>
Run Code Online (Sandbox Code Playgroud)

我的控制器看起来像这样:

app.controller("editorController", function($scope, $timeout, $window) {

    $scope.editor = "";

    $scope.addSomeTextAtTheEnd = function() {
        $timeout(function() {
            $scope.editor = $scope.editor + " Period!";
        }, 5000);
    }

    $scope.$watch("editor", function editorListener() {

        var editor = $window.document.getElementById("editor");
        var start = editor.selectionStart;
        var end = editor.selectionEnd;

        $scope.$evalAsync(function() {
            editor.selectionStart = start;
            editor.selectionEnd = end;
        });

    });
});
Run Code Online (Sandbox Code Playgroud)

假设我开始在textarea中输入一些文本.然后我按下按钮,很快就会添加"期间!" 在$scope.editor价值的最后.在5秒超时期间,我再次关注textarea并编写更多文本.5秒后,我的textarea值会更新.

我正在关注$scope.editor价值.该editorListener会在每个执行$digest周期.在这个循环中也会发生双向数据绑定.我需要在数据绑定后纠正插入位置.是$scope.$evalAsync(...)我应该在哪里做,或者不正确的地方?

SoE*_*zPz 0

这是我用来操纵插入符位置的指令;然而,正如我在评论中所说,IE 存在问题。

以下内容可以帮助您制定计划。我在您的问题中注意到的一件事是,您提到了一种情况,即用户可以重新聚焦输入框以键入其他文本,我认为这会重置超时;这个条件是真的吗?

您是否愿意不使用按钮来添加文本,而是直接添加文本?就像每当用户从输入框中取消焦点时运行 addSomeTextAtTheEnd 函数一样?

如果您必须使用该按钮,并且用户重新关注输入框并输入更多内容,您应该取消按钮超时。

喜欢:

    myVar = setTimeout(function(){ alert("Hello"); }, 3000);

    // Then clear the timeout in your $watch if there is any change to the input.
    clearTimeout(myVar);
Run Code Online (Sandbox Code Playgroud)

如果您这样做,也许您甚至不需要知道光标位置,因为 addSomeTextAtTheEnd 函数超时将在 5 秒超时之前重置任何输入更改。如果发生 5 秒超时,则 addSomeTextAtTheEnd 将运行并“将文本附加到末尾”,就像它应该做的那样。请提供更多信息,我将根据需要进行更新。

app.directive('filterElement', ['$filter', function($filter){

  return {
    restrict:'A', // Declares an Attributes Directive.
    require: '?ngModel', // ? checks for parent scope if one exists.

    link: function( scope, elem, attrs, ngModel ){
      if( !ngModel ){ return }

      var conditional = attrs.rsFilterElement.conditional ? attrs.rsFilterElement.conditional : null;

      scope.$watch(attrs.ngModel, function(value){
        if( value == undefined || !attrs.rsFilterElement ){ return }

        // Initialize the following values
        // These values are used to set the cursor of the input.
        var initialCursorPosition = elem[0].selectionStart
        var initialValueLength = elem[0].value.length
        var difference = false

        // Sets ngModelView and ngViewValue
        ngModel.$setViewValue($filter( attrs.rsFilterElement )( value, conditional ));
        attrs.$$element[0].value = $filter( attrs.rsFilterElement )( value, conditional );

        if(elem[0].value.length > initialValueLength){ difference = true }
        if(elem[0].value.length < initialValueLength){ initialCursorPosition = initialCursorPosition - 1 }
        elem[0].selectionStart = difference ? elem[0].selectionStart : initialCursorPosition
        elem[0].selectionEnd = difference ? elem[0].selectionEnd : initialCursorPosition
      });
    } // end link
  } // end return
}]);
Run Code Online (Sandbox Code Playgroud)