Hey there,
I’d like to share an implementation with you, partly as documentation for others and maybe to see if it can be improved in some way.
There are some cases in which you might have content that links to an external website. The problem is that projects wrapped in Cordova by default open all links in the wrapper browser, instead of opening them in the system browser.
The way around this is to use a Cordova plugin called inappbrowser. In the documentation it says you can open any link in the system browser by formatting the link like this:
<a href="http://test_url.com" target="_system">Link</a>
.
In my experience this doesn’t work: links are still opened in the Cordova wrapper.
Inappbrowser does work however when you open links with window.open(url, '_system')
. So you could write a function and tie it to ng-click like so:
<a ng-click="GotoLink('http://test_url.com')">Link</a>
,
and then set up a function in your controller (or turn it into a directive):
$scope.GotoLink = function (url) {
window.open(link,'_system');
}
The problem in my case was that I was loading in a piece of html from a CMS in a json file that could contain multiple links and they were in the default format of <a href="link">
. I had to find a way to automatically rewrite them to use ng-click. So I wrote a function in my loader module that find-replaced any links in the content.
This lead me to my next problem though. I’m using ngSanitize to display html content by using ng-bind-html. Like so:
<p ng-bind-html="'{{some_variable}}'">
The problem was ng-bind-html automatically filtered out ng-click. So when I used ng-bind-html to display the html content, the ng-click was no longer there on my a element.
I tried using ng-bind-html-unsafe, but that didn’t work either.
In the end I added two directives. The first is by @gregorypratt called browseTo. Any element that contains browse-to is now opened via window.open with target _system, so it opens in the system browser nicely.
That left with me with the problem of ngSanitize removing any angular in it’s output when using ng-bind-html.
So the second directive I added is compile. This keeps browse-To or ng-click in the ouput. So instead of using:
<p ng-bind-html="'{{some_variable}}'">
I now use:
<p compile="some_variable"> // Notice the lack of accolades and quotes!
And this works! In the fields that I choose, links to external sites are now opened in the system browser.
Full code of directives:
angular.module('MyApp.Directives').directive('browseTo', function ($ionicGesture) {
return {
restrict: 'A',
link: function ($scope, $element, $attrs) {
var handleTap = function (e) {
var inAppBrowser = window.open(encodeURI($attrs.browseTo), '_system');
};
var tapGesture = $ionicGesture.on('tap', handleTap, $element);
$scope.$on('$destroy', function () {
// Clean up - unbind drag gesture handler
$ionicGesture.off(tapGesture, 'tap', handleTap);
});
}
}
})
angular.module('MyApp.Directives').directive('compile', ['$compile', function ($compile) {
return function(scope, element, attrs) {
scope.$watch(
function(scope) {
return scope.$eval(attrs.compile);
},
function(value) {
element.html(value);
$compile(element.contents())(scope);
}
)};
}])
So this is quite a complicated way of achieving something relatively straightforward as opening a link in the system browser. So I was wondering if anyone else was running into the same problem and found another, perhaps more elegant solution?