Marco Pompei
Marco Pompei

Reputation: 1080

I'm using Angular, how I transform a model value before it's validated?

I have an input[text] that you type an URL and it will use an async validator to check if it is a valid RSS feed.

The URL is something like this, where feed-url is a directive for the async validation:

<input type="text"
    name="url"
    ng-model="url"
    ng-model-options="{ updateOn: 'default blur', debounce: { default: 500, blur: 0 } }"
    placeholder="http://"
    feed-url
    >

I want to add the protocol ('http://') if the user forgets to. This must be done before it's validated (because it won't apply the model in case the user forgets because the URL is invalid).

I can't find any way to do it. Anyone has any idea?

Upvotes: 0

Views: 477

Answers (2)

New Dev
New Dev

Reputation: 49590

Indeed, as suggested in a comment, this is what $parsers are used for - i.e. take the value coming from the View and "parse" it to make it model-compatible.

Parsers run before validators.

To add a parser, you need to add a directive:

.directive("fixUrl", function(){
  return {
    require: "?ngModel",
    link: function(scope, element, attrs, ngModel){
      if (!ngModel) return;

      ngModel.$parsers.push(function(val){
        // poor man's implementation
        if (url.indexOf("http") !== 0){
          url = "http://" + url;
        }
        return url;
      });
    }
  };
});

Usage:

<input ng-model="url" fix-url>

Upvotes: 1

Tahsis Claus
Tahsis Claus

Reputation: 1919

Add this directive to your element:

ng-change="validateURL()"

then in your controller, have $scope.validateURL be a function which looks at the scope value that ng-model points to and alter it accordingly.

Example code: http://jsfiddle.net/tsclaus/skq2ubce/2/

The logic in my example could use improvement, but that's a basic idea. Ng-change on text inputs is somewhat annoying to handle due to it firing with every keystroke, so there might be a better way. The 30s delay on the timeout is an example of a way to handle that, and generally works provided they delete all of the "http://" string.

Upvotes: 0

Related Questions