nickdnk
nickdnk

Reputation: 4300

$watch does not watch model when using scope attribute

I'm working on a directive made for <input> that watches what the user types. When the user types in a valid phone number it should re-format the input model object and set a variable to true, indicating to the parent scope that the model now contains a valid phone number.

CountryISO is depency injected as constant and contains - surprise - the country code of the user. The functions used inside the directive are from phoneformat.js

UPDATED: Now the valid = true/false assigment works. But how do I then update the actual model value? This needs to be changed to the properly formatted phone number.

app.directive('phoneFormat', ['CountryISO', function (CountryISO) {
            return {
                restrict: 'A',
                require: 'ngModel',
                scope: {
                    valid:'='
                },
                link: function (scope, element, attrs, ngModel) {

                scope.$watch(function() {
                return ngModel.$viewValue; //will return updated ng-model value
                }, function(v) {

                if (isValidNumber(v, CountryISO)) {

                    // What do I do here? This doesn't work.
                    v = formatE164(CountryISO, v);
                    // This neither
                    ngModel.$viewValue = formatE164(CountryISO, v);

                    console.log("valid");
                    scope.valid = true;

                } else {

                    console.log("invalid");
                    scope.valid = false;
                }
                });
                }
            };
        }]);

as the directive

and the html looks like:

<input data-phone-format data-valid="user.validPhoneNumber" data-ng-model="user.info.ph">

The problem is that as soon as I include scope: {valid:'='}, as part of the directive, the $watch stops working. How do I get both? I want the directive to be able to point to a variable in the parent scope that should change from true to false depending on the validity of the phone number.

Upvotes: 0

Views: 117

Answers (1)

Pankaj Parkar
Pankaj Parkar

Reputation: 136134

Because as you declaring watcher the variable are parsing with the directive scope which becomes isolated scope after you have added scope: {valid:'='} to make it working you could place watch on the ngModel.$viewValue

To updated the ngModel value you could set $viewValue of ngModel using $setViewValue method of ngModel & then to update that value inside $modelValue you need to do $render() on ngModel.

Read on $viewValue & $modelValue

Link

link: function(scope, element, attrs, ngModel) {

    scope.$watch(function() {
        return ngModel.$viewValue; //will return updated ng-model value
    }, function(v) {

        if (isValidNumber(v, CountryISO)) {

            // What do I do here? This doesn't work.
            v = formatE164(CountryISO, v);
            // This neither
            ngModel.$setViewValue(formatE164(CountryISO, v));
            ngModel.$render(); //to updated the $modelValue of ngModel
            console.log("valid");
            scope.valid = true;

        } else {

            console.log("invalid");
            scope.valid = false;
        }
    });
}

Upvotes: 1

Related Questions