Focus on the next input when reaching the maximum number of characters

Asked

Viewed 832 times

2

I created a directive to move the cursor to the next field when it reaches the maximum character size, this way below:

var app = angular.module("myApp", []);

app.directive("moverProximoCampo", function() {
    return {
        restrict: "A",
        link: function($scope, element) {
            element.on("input", function(e) {
                if(element.val().length == element.attr("maxlength")) {
                    var $nextElement = element.next();
                    if($nextElement.length) {
                        $nextElement[0].focus();
                    }
                }
            });
        }
    }
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<div ng-app="myApp">
    <form>
    <input type="text" id="part1" ng-model="form.part1" maxlength="3" placeholder="3 caracteres" mover-proximo-campo />
    <input  placeholder="2 caracteres"  type="text" id="part2" ng-model="form.part2" maxlength="2" mover-proximo-campo /> 
    <input  placeholder="7 caracteres"  type="text" id="part3" ng-model="form.part3" maxlength="7" mover-proximo-campo />
</form>
</div>

But if I put any element between these inputs, as a div, the next input is not focused. See:

var app = angular.module("myApp", []);

app.directive("moverProximoCampo", function() {
    return {
        restrict: "A",
        link: function($scope, element) {
            element.on("input", function(e) {
                if(element.val().length == element.attr("maxlength")) {
                    var $nextElement = element.next();
                    if($nextElement.length) {
                        $nextElement[0].focus();
                    }
                }
            });
        }
    }
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<div ng-app="myApp">
    <form>
    <input type="text" id="part1" ng-model="form.part1" maxlength="3" placeholder="3 caracteres" mover-proximo-campo />
    <div> Tem uma div aqui entre os inputs</div>
    <input  placeholder="2 caracteres"  type="text" id="part2" ng-model="form.part2" maxlength="2" mover-proximo-campo /> 
    <div> Tem outra div aqui entre os inputs</div>
    <input  placeholder="7 caracteres"  type="text" id="part3" ng-model="form.part3" maxlength="7" mover-proximo-campo />
</form>
</div>

In fact, the idea would be to focus on the next input, but not in the next element. What would be the most practical way to solve this?

2 answers

2


I take the parent element and search the input elements.
I search for the position of the current element and assign the element of the next index to a variable and then use it to focus.
I used the angular foreach to find the index, but if I cared the Jquery in html I could use the inArray. (included a commented example).
I changed the event of input for keyup.

var app = angular.module("myApp", []);
app.directive("moverProximoCampo", function() {
return {
    restrict: "A",
    link: function($scope, element) {
        var inputs = element.parent().find('input');
        //com JQlite
        var $nextElement = []; 
        angular.forEach(inputs, function(elem,index){
            if(elem == element[0]){
                $nextElement = inputs.eq(index+1);
            }
        })
        //Se usar o JQuery ao invés do JQlite
        //var index = angular.element.inArray(element[0], inputs);
        //var $nextElement = inputs.eq(index+1);
        
        element.on("keyup", function(e) {
            if(element.val().length == element.attr("maxlength")) {
                if($nextElement.length) {
                    $nextElement[0].focus();
                }
            }
        });
    }
}
});
<!-- <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<div ng-app="myApp">
    <form>
    <input type="text" id="part1" ng-model="form.part1" maxlength="3" placeholder="3 caracteres" mover-proximo-campo />
    <div> Tem uma div aqui entre os inputs</div>
    <input  placeholder="2 caracteres"  type="text" id="part2" ng-model="form.part2" maxlength="2" mover-proximo-campo /> 
    <div> Tem outra div aqui entre os inputs</div>
    <input  placeholder="7 caracteres"  type="text" id="part3" ng-model="form.part3" maxlength="7" mover-proximo-campo />
</form>
</div>

2

I particularly like to uncomplicate things. Why should the directive guess which is next input, and I can inform you myself in the directive statement mover-proximo-campo?

Look at the example I made:

var app = angular.module("myApp", []);

app.directive("moverProximoCampo", function() {
    return {
        restrict: "A",
        link: function($scope, element, attr) {
          
            var proximoId = attr.moverProximoCampo;
            
            element.on("input", function(e) {
                if(element.val().length == element.attr("maxlength")) {
                    
                    document.querySelector(proximoId).focus();
                }
            });
        }
    }
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<div ng-app="myApp">
    <form>
    <input type="text" id="part1" ng-model="form.part1" maxlength="3" placeholder="3 caracteres" mover-proximo-campo="#part2" />
    <div> Tem uma div aqui entre os inputs</div>
    <input  placeholder="2 caracteres"  type="text" id="part2" ng-model="form.part2" maxlength="2" mover-proximo-campo="#part3" /> 
    <div> Tem outra div aqui entre os inputs</div>
    <input  placeholder="7 caracteres"  type="text" id="part3" ng-model="form.part3" maxlength="7" />
</form>
</div>

Note that what I did was change the statement of your input directives, stating, as a parameter, which is the next element I should focus on. That is, in the directive, you pass the id of the next desired focus element, when the condition is met.

Sort of like this:

<input mover-proximo-campo="#campo2" id="campo1" />
<input id="campo2" mover-proximo-campo="#campo3" />
<input id="campo3"  />
  • The idea is good, but when I (after having filled in all fields) focus on the input (click on the field) and enter some character, it does not go to the next one. Maybe there is still some way to improve the code. + 1

  • I understand, it’s just that it wasn’t mentioned in the question, but I can see if I can edit the code to apply the desired effect.

  • 1

    I’m sorry, but I’ve been going over the @Viana comment and I didn’t see any problem like he said. Whenever the character limit is reached it is moving to the next normal field.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.