web-dev-qa-db-fra.com

Définir la position du curseur en entrée avec AngularJS

Je dois modifier la position du curseur d'une entrée, où un nombre donné de chiffres est ajouté ( Exemple ). 

app.controller('MainCtrl', function($scope, $element, $timeout, $filter) {
  //$scope.val = '12';
  $scope.$watch('val', function(newValue, oldValue) {
    if (!isNaN(newValue)) {
      if (newValue.length > 3) {
        //Set Caret Position  
      }
    }
  });
});

Est-il possible de faire quelque chose comme ceci exemple ?

J'ai besoin par exemple:

Entrée: 1234.

la position du curseur sera donc 2. 

Nouveau chiffre: 9

finale: 12934

Merci d'avance.

9
JohnPortella

Je pense que ce genre de choses semble mieux dans les directives. Par exemple:

app.directive('caret', function() {

    function setCaretPosition(elem, caretPos) {
        if (elem !== null) {
            if (elem.createTextRange) {
                var range = elem.createTextRange();
                range.move('character', caretPos);
                range.select();
            } else {
                if (elem.setSelectionRange) {
                    elem.focus();
                    elem.setSelectionRange(caretPos, caretPos);
                } else
                    elem.focus();
            }
        }
    }

    return {
        scope: {value: '=ngModel'},
        link: function(scope, element, attrs) {
            var caret = Number(attrs.caret);
            scope.$watch('value', function(newValue, oldValue) {
                if (newValue && newValue != oldValue && !isNaN(newValue) && newValue.length > (caret + 1)) {
                    setCaretPosition(element[0], caret);
                }
            });
        }
    };
});

Usage:

<input ng-model='val' caret="2" />

J'ai utilisé la fonction setCaretPosition pour positionner le curseur de plusieurs navigateurs entre this answer.

Démo: http://plnkr.co/edit/5RSgzvyd8YOTaXPsYr8A?p=preview

25
dfsq

J'ai aussi eu le même problème.

J'ai pensé résoudre le problème en créant une directive appropriée. Vous pouvez le trouver ici . Profitez-en!

Usage

Inclure la directive, la déclarer par l'attribut caret-aware

<script src="https://cdn.rawgit.com/leodido/ng-caret-aware/master/caretaware.min.js"></script>
<script type="text/javascript">
  var app = angular.module('myModule', ['leodido.caretAware']);
</script>
...
<div data-ng-app="app">
    <input type="text" name="myname" caret-aware="cursor"/>
</div>

Ensuite, dans le champ d'application, vous aurez une variable cursor contenant la position du curseur dans l'entrée nommée myname.

Néanmoins, le contrôleur de cette directive expose une API

  • getPosition
  • setPosition

Pour d'autres exemples d'utilisation, voir le répertoire example du référentiel github lié ci-dessus.

1
leodido

Je pense que la meilleure approche à cet égard est de créer une directive réutilisable car nous traitons de la manipulation DOM.

Lien vers la démo: http://plnkr.co/edit/qlGi64VO1AOrNpxoKA68?p=preview

var app = angular.module('angularjs-starter', []);

app.controller('MainCtrl', function($scope, $element, $timeout, $filter) {
  $scope.$watch('val', function(newValue, oldValue) {
    if (!isNaN(newValue)) {
      if (newValue.length > 3) {
      // $element.find('input')[0].selectionEnd  = 2;
      }
    }
  });
});

app.directive('setCaret', function() {

  return {
    restrict: 'A',
    link: function(scope,element,attrs) {
      var changed = false;
      element.bind('keypress', function() {
        if(element[0].selectionStart > 3 && !changed) {
          changed = true;
          element[0].selectionEnd = parseInt(attrs.position, 10);
        }
      })

    },
  }

})

Vous pouvez voir dans la partie commentée du contrôleur que nous pouvons y accéder en utilisant $ element, mais comme il s'agit de DOM et que les contrôleurs ne sont pas destinés à la manipulation du DOM, nous devons en faire une directive.

1
Sten Muchow

I jsfiddled une solution qui marche. Donc, en gros, vous devez créer une directive:

app.directive('keypressdetector', function($compile){
    return {
    restrict:'AEC',
    link: function(scope, element, attrs){
        element.bind("keypress", function (event) {
            if(event.which === 13) {
                            var selectionStart = element[0].selectionStart;
              var value = element.val();
              var valueLength = value.length;
              var newValue= '';
              if (selectionStart == valueLength){
                newValue = value;
              } else {
                newValue = value.substring(selectionStart, valueLength);
              }
              var newElement = angular.element('<input type="text" value="' + newValue +'"/>')
              angular.element(document.body).append(newElement);
            }
        });
    }
  };
});

Votre contrôleur serait inutilisable dans cette situation. Vous pouvez invoquer la directive comme ceci (voir: keypressdetector):

<div ng-app="myapp">
<div ng-controller="LoginController">
    <div>Hello {{ user.firstName }}</div>
    <input ng-model="user.firstName" keypressdetector />
    <input type="submit" ng-click="login()" value="Login"/>
    <div ng-repeat="login in logins">{{ login }}</div>
</div>
</div>

Voir la démo: https://jsfiddle.net/Lt7aP/3468/

0
Zakaria

Je pense que vous pourriez le faire en utilisant .setSelectionRange() dans votre entrée. J'ai mis à jour votre exemple - voyez si c'est ce que vous vouliez: http://plnkr.co/edit/bIJAPPAzkzqLIDUxVlIy?p=preview

Remarque: setSelectionRange n'est pas pris en charge par IE8 (voir https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement.setSelectionRange ). Si vous devez prendre en charge IE <9, vous aurez besoin de chercher des cales.

0
Michael Bromley