0

I am having some trouble binding an input box to a controller in Angular. I have set this up as I have seen in various tutorials but when I access the property or I check the scope using AngularJS Batarang I see the model never updates.

When I submit the form $scope.licenceKey is always empty!

<div ng-app="licenceApp" ng-controller="licenceController">
    <form name="licenceForm" ng-submit="applyKey()" novalidate>
        <span ng-if="!Applying">
            <input type="text" ng-model="licenceKey" ng-disabled="Applying" ng-model-options="{ debounce : { 'default' : 150 } }" username-available-validator required />
            ...

JS:

angular.module('licenceApp.controllers', [])
    .controller('licenceController', function ($scope, licenceAPIservice, $filter) {
        $scope.licenceKey = "";
        $scope.Applying = false;
        ...
        $scope.applyKey = function () {
            $scope.Applying = true;

            // $scope.licenceKey is always empty here!!
            licenceAPIservice.applyKey($scope.licenceKey).then(function (data) {
                console.log(data);

                // Update model once we have applied the key
                $scope.update();
            }, function () {
                $scope.Applying = false;
            });
        };

And the username directive (I need to change the name to reflect its function but havent yet)

angular.module('licenceApp.directives', [])
    .directive('usernameAvailableValidator', function ($http, $q, licenceAPIservice) {
        return {
            require: 'ngModel',
            link: function ($scope, element, attrs, ngModel) {
                ngModel.$asyncValidators.usernameAvailable = function (username) {
                    var deferred = $q.defer();

                    licenceAPIservice.validateKey(username).then(function (data) {
                        if (data.data) {
                            deferred.resolve();
                        }
                        else {
                            deferred.reject();
                        }
                    }, function () {
                        deferred.reject();
                    });

                    return deferred.promise;
                };
            }
        }
    });

When I access $scope.licenceKey anywhere its always empty even if I have typed in the input, although the custom validation I have on the input works correctly

Note that interestingly, when I bind to Applying to control view states that works!

Update

I can get the value out if I use $scope.licenceForm.licenceKey.$modelValue but I dont understand why this is necessary?

Update 2

Also if I set $scope.licenceKey = "test"; initially then it is shown in the textbox on page load, but that value then never updates when I modify the textbox

5
  • What if you remove ng-model-options attribute? Can we see your validator pipeline of username-available-validator Commented Nov 12, 2014 at 13:04
  • @RahilWazir Hey, unfortunateley removing ng-model-options doesnt change the functionality. I added my directive code as you asked. Commented Nov 12, 2014 at 13:07
  • So the validation is working for you? Make sure validation should not be in pending state. Commented Nov 12, 2014 at 13:13
  • Validation is working fine, the problem is when I come to submit the form my submit code uses $scope.licenceKey but that is always empty! Commented Nov 12, 2014 at 13:19
  • @RahilWazir using Batarang it shows that the licenceKey is set, but in a sub-scope (not sure why, or how) Commented Nov 12, 2014 at 13:32

1 Answer 1

1

It is probably because you are using ng-if and not ng-show directive.

This is because ng-if remove the element from the DOM while ng-show uses css rules to hide the element.

Here is a fiddle demonstrating this http://jsfiddle.net/q9rnqju5/.

HTML

<div ng-app="app">
    <div ng-controller="controller">
        <div ng-show="!applying1">
            <input ng-model="value1" />
            <button ng-click="apply1()">Submit</button>
        </div>
        <div ng-if="!applying2">
            <input ng-model="value2" />
            <button ng-click="apply2()">Submit</button>
        </div>
    </div>
</div>

JS

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

app.controller("controller", ["$scope", "$timeout", function($scope, $timeout) {
    $scope.apply1 = function() {
        $scope.applying1 = 1;
        $timeout(function() {
            console.log($scope.value1);
            $scope.applying1 = 0;
        }, 1000);
    };
    $scope.apply2 = function() {
        $scope.applying2 = 1;
        $timeout(function() {
            console.log($scope.value2);
            $scope.applying2 = 0;
        }, 1000);
    };
}]);

You can see that upon submission the first input (using ng-show) keeps its value while the second input (using ng-if) loses its value.

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

1 Comment

@Chris now dont make the mistake of only using ng-show now. they both have their purposes. ng-if can be helpful if you have a bunch of different layouts and since elements are removed from the dom you can reuse ids in the different layouts (although ng-switch may be better), while ng-show is better for your scenario. hope this makes sense :)

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.