AngularJS - add http prefix to url input field

Problem

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?

Problem courtesy of: Matt Byrne

Solution

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, this support for URL to be entered manually with 'http' or 'https', as well as auto-prefixing if none of them: http://jsfiddle.net/jrz7nxjg/

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.

Solution courtesy of: Andyrooger

Discussion

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

Discussion courtesy of: Andrej

This recipe can be found in it's original form on Stack Over Flow.