Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free.

Our app is being ported from jQuery to AngularJS with bootstrap (angular-ui bootstrap).

One handy feature that was covered by the following excellent post was to add "http://" prefix to a URL field if it did not already have a prefix: http://www.robsearles.com/2010/05/jquery-validate-url-adding-http/

I am trying to achieve the same in AngularJS via a directive, but cannot get the directive to alter the value of the ng-model as it is being typed.

I've started simple by trying to get a fiddle to add a "http://" prefix on EVERY change for now (I can add the logic later to only add it when needed). http://jsfiddle.net/LDeXb/9/

app.directive('httpPrefix', function() {
    return {
        restrict: 'E',
        scope: {
            ngModel: '='
        },
        link: function(scope, element, attrs, controller) {
            element.bind('change', function() {
                scope.$apply(function() {
                   scope.ngModel = 'http://' + scope.ngModel;
                });
            });
        }
    };
});

Can anyone please help me to get this to write back to the ngModel. Also, the field I need to apply this new directive to already has a directive on it with isolate scope so I'm assuming I can't have another one with isolate scope - if this is so can I achieve it without isolate scope?

share|improve this question

2 Answers 2

up vote 18 down vote accepted

A good way to do this is by using the parsers and formatters functionality of ng-model. Many people use use ng-model as just a binding on isolated scope, but actually it's a pretty powerful directive that seems to lack documentation in the right places to guide people on how to use it to its full potential.

All you need to do here is to require the controller from ng-model in your directive. Then you can push in a formatter that adds 'http://' to the view, and a parser that pushes it into the model when needed. All the binding work and interfacing with the input is done by ng-model.

Unless I can find a good blog on this (very much open to comments from anyone who finds them), an updated fiddle is probably the best way to describe this: http://jsfiddle.net/4czN2/

This also solves your second problem of not being able to have two isolated scopes on one element, as you no longer need to bind to anything.

share|improve this answer
    
Wow - I didn't even think of going down this path. This will fit perfectly, thanks. I am really glad I posted this question now! –  Matt Byrne Oct 20 '13 at 21:22
    
I can only get this to work if I set the field to type="text". This will not work with type="url" on the field because the value is invalid until it has a prefix and thus the value is not bound to scope. Is there a way to get these two to play together? jsfiddle.net/m4vnf –  Matt Byrne Oct 20 '13 at 22:10
4  
You can use splice to push your parser to the front. This seems to work, as the model hasn't been killed off by the validator yet. jsfiddle.net/ZaeMS/2 –  Andyrooger Oct 20 '13 at 22:30
    
That worked perfectly! –  Matt Byrne Oct 21 '13 at 0:15
    
Just a note: if someone enters another valid prefix like "https://", the "http://" will still get added in front of it. –  caleb Sep 17 '14 at 21:12

The previous comment provided by Matt Byrne doesn't work for the https prefix. Checkout the updated version based on previous answers that works with **https prefix too! This was missing there

/^(https?):\/\//i

http://jsfiddle.net/ZaeMS/13

share|improve this answer
    
thanks for this –  MURATSPLAT Feb 11 at 14:23

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.