0

I want to do simple "nick free or taken" validation. When using jquery I was resorting to "listeners" that would raise "changed" event every 1-2 seconds so that instead of issuing HTTP GET request for every keystroke I would issue HTTP GET every 1-2 seconds.

However I AngularJs I only have this:

<input id="nick" ng-model="nickSelected" ng-change="nickChanged()" />

And on controller:

$scope.nickChanged = function() {
    $log.log(this.nickSelected);
    // $http.get("/nickIsValid", {params : { nick: this.nickSelected }}).
    //    success(function (data, status, headers, config) { ... });
}

But obviously this executes for every keystroke.

So, is there any listener directive within AngularJS that would raise nickChanged every second or so instead of doing it for every keystroke? Or any way I can say to that particular $http.get to execute only every second or so?

1

3 Answers 3

1

You can use something like throttle() in underscore/lodash if you have have methods with the potential to run many times. Alternatively, you might consider using blur here depending on your requirements.

Sign up to request clarification or add additional context in comments.

Comments

1

I'd recommend writing your own directive for this. you should use $timeout to delay when you do your validation. Of course there is no reason to reinvent the wheel, so...

here is a directive that will do validation after the user finishes typing.

I didn't make this, but it works very well and is well written, so looking at the src may help you develop this sort of thing for yourself in the future.

Comments

0

OK,

This particular answer helped a lot - Call Function with Delay When Textbox Changes in AngularJS

Here is resulting directive:

app.directive('nickUnique', ['$http', '$timeout', function ($http, $timeout) {
    return {
        require: 'ngModel',
        link: function (scope, ele, attrs, c) {
            var timer = false; // for grouping calls
            scope.$watch(attrs.ngModel, function () {
                // for when $setPristine(true) is called
                if (c.$pristine) {
                    c.$setValidity('httpinprogress', true);
                    c.$setValidity('nickUnique', true);
                }

                // only execute for otherwise "valid" nick
                if (c.$viewValue != null && c.$dirty &&
                    c.$viewValue.length >= 4 && c.$viewValue.length <= 12) {
                    if (timer) {
                        $timeout.cancel(timer);
                    }

                    c.$setValidity('httpinprogress', false);
                    c.$setValidity('nickUnique', true);

                    timer = $timeout(function () {
                        $http.get("/path/to/service", { params: { Nick: c.$viewValue } })
                            .success(function (data, status, headers, cfg) {
                                if (data.RequestNick === c.$viewValue) {
                                    c.$setValidity('httpinprogress', true);
                                    c.$setValidity('nickUnique', data.Valid);
                                }
                            }).error(function (data, status, headers, cfg) {
                                c.$setValidity('nickUnique', false);
                            });
                    }, 250);
                }
            });
        }
    };
}]);

To use it, you just decorate your input like:

<input name="nick" ng-model="myCtrl.Nick" nick-unique />

Your service on /path/to/service should return JSON object like:

{ Valid: true/false, RequestNick: echo_nick_sent }

Finally, you just show validation errors depending on state of $error property. Like, if you also validate required, minlength and maxlength, you'll have something like this:

<span class="error" ng-show="myForm.Nick.$dirty && myForm.Nick.$invalid">
    <small class="error" ng-show="myForm.Nick.$error.required">is required field</small>
    <small class="error" ng-show="myForm.Nick.$error.minlength">is required to be at least 4 characters</small>
    <small class="error" ng-show="myForm.Nick.$error.maxlength">is required to be less than 12 characters</small>
    <small class="error" ng-show="!myForm.Nick.$error.required && 
        !myForm.Nick.$error.minlength && 
        !myForm.Nick.$error.maxlength && 
        myForm.Nick.$error.nickUnique">is taken, please try another</small>
</span>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.