Sebastian Hernandez
Sebastian Hernandez

Reputation: 2376

Open all links using system browser inside an ionic app

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

Upvotes: 16

Views: 15510

Answers (5)

Nic Raboy
Nic Raboy

Reputation: 3153

You can override the default link tag functionality as seen here:

https://www.thepolyglotdeveloper.com/2014/12/open-dynamic-links-using-cordova-inappbrowser/

Best,

Upvotes: 2

Avneesh Kumar
Avneesh Kumar

Reputation: 35

<ul>
<li> <a href="#"  ng-click='openlink($event)' data-link='https://www.link1.com'> Link 1 </a></li>  
<li> <a href="#"  ng-click='openlink($event)' data-link='https://www.link2.com'> Link2 </a></li>  
<li> <a href="#"  ng-click='openlink($event)' data-link='https://www.link3.com'> Link 3 </a></li>  
</ul>

In controller -

 angular.module('app', [])
    .controller('LinkCtrl', function($scope) {
         $scope.openlink = function($event)
            {               
              if ($event.currentTarget && $event.currentTarget.attributes['data-link'])
                    {
                   window.open($event.currentTarget.attributes['data-link'], '_system', 'location=yes');
                    }
                }

    })

Upvotes: 0

Eduardo Cuomo
Eduardo Cuomo

Reputation: 18937

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/

Upvotes: 2

you786
you786

Reputation: 3550

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");
        }
      }
    });
}

Upvotes: 2

caiocpricci2
caiocpricci2

Reputation: 7798

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.

Upvotes: 6

Related Questions