Chris
Chris

Reputation: 27384

Angular form binding issue

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

Upvotes: 0

Views: 136

Answers (1)

Logan Murphy
Logan Murphy

Reputation: 6230

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.

Upvotes: 1

Related Questions