I need that all links inside a certain section of my app open in the system browser. The trick is that those links come from an external source (an API) so I can't add the ng-click
function that helps me to open the links externally.
I'm using in-app-browser plugin (ng-cordova). In fact I have other links that open externally but in this case the links can be in any part of the content so my question would be how could I add the ng-click directive to all links after they are loaded? or if it's possible, how to config in-app-browser plugin to open ALL links in system browser?
By the way, the simple links don't open even in the inappbrowser: I tap on them and nothing happens.
Thanks for the help
If you want to open an URL in a so called in-app browser you can use the Browser API ( @capacitor/browser plugin): Capacitor 2: https://capacitorjs.com/docs/apis/browser. Capacitor 3 (soon to be released): https://capacitorjs.com/docs/v3/apis/browser.
Ionic Portals offers a supercharged native Web View component for iOS and Android that enables teams to add web-based experiences to native mobile apps.
Ionic 4 represents the culmination of more than two years of research and hard work transforming Ionic from “mobile for Angular” into a powerful UI Design System and app framework for every web developer in the world.
AFAIK there isn't a way of doing that automatically, you must use the in app browser js code to open links externally consistently in every platform.
Your question doesn't give a clear example of what the server returns so I'm assuming you are getting a full block of html and are just rendering it on the screen. Assuming a request return something basic like :
<div id="my-links">
<a href='http://externallink.com'> External Link 1 </a>
<a href='http://externallink.com'> External Link 2 </a>
<a href='http://externallink.com'> External Link 3 </a>
</div>
And your request looks like:
$http.get('givemelinks').success(function(htmlData){
$scope.myContent = htmlData;
})
If you have access to the server side and can make changes:
Add a "inappbrowser" parameter to your request to detect if it should return inappbrowser compatible links and change the response from your server to be something like:
if (inappbrowser) {
<div id="my-links">
<div ng-click='openExternal($event)' data-external='http://externallink.com'> External Link 1 </div>
<div ng-click='openExternal($event)' data-external='http://externallink.com'> External Link 2 </div>
<div ng-click='openExternal($event)' data-external='http://externallink.com'> External Link 3 </div>
</div>
} else {
<div id="my-links">
<a href='http://externallink.com'> External Link 1 </a>
<a href='http://externallink.com'> External Link 2 </a>
<a href='http://externallink.com'> External Link 3 </a>
</div>
}
And have a generic openExternal method:
$scope.openExternal = function($event){
if ($event.currentTarget && $event.currentTarget.attributes['data-external'])
window.open($event.currentTarget.attributes['data-external'], '_blank', 'location=yes');
}
If you can't change the server side
Parse the response and replace the links with ng-clicks:
$http.get('givemelinks').success(function(htmlData){
htmlData = htmlData.replace(/href='(.*)'/,'ng-click="openExternal($event)" data-external="$1"').replace(/<a/,"<div").replace(/a>/,"div>")
$scope.myContent = htmlData;
})
And use the same openExternal method as above.
I'm replacing the anchors with divs to prevent changing the app routes. That might not be necessary in every app.
To make this even better you should bundle it in a open-external
directive so you can use it in multiple controllers and keep them cleaner.
Because the HTML is already rendered when it comes to Angular, and the inAppBrowser plugin only works if called by explicit Javascript, there is nothing you can do that doesn't involve manually changing the HTML or using plain javascript.
Changing the HTML is just a Bad Idea®, especially if you try to do it by using regex matching.
That leaves javascript:
Restangular.all('stories').getList().then(function(stories){
$scope.stories = stories;
updateLinks();
});
function updateLinks(){
//use $timeout wait for items to be rendered before looking for links
$timeout(function(){
var $links = document.querySelectorAll(".stories .story a");
for(var i =0; i < $links.length; i++) {
var $link = $links[i];
var href = $link.href;
console.log("Hijacking link to ", href);
$link.onclick = function(e){
e.preventDefault();
var url = e.currentTarget.getAttribute("href");
window.cordova.inAppBrowser.open(url, "_system");
}
}
});
}
Install next plugin:
cordova plugin add https://git-wip-us.apache.org/repos/asf/cordova-plugin-inappbrowser.git
Now, you can use _system
, _blank
or _self
for destination:
window.open(url, '_blank');
More info: https://www.thepolyglotdeveloper.com/2014/07/launch-external-urls-ionicframework/
You can override the default link tag functionality as seen here:
https://www.thepolyglotdeveloper.com/2014/12/open-dynamic-links-using-cordova-inappbrowser/
Best,
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With