I need to launch an external website in Onsen Ui - onsen-ui

I need to launch to launch an external url / website in Onsen Ui without leaving the app. I can use an iframe I guess between the ons-page tags where I need it but not very reliable perhaps.
Its my first Onsen Ui project.
Jimmy

Simply using the method below on OnsenUI
Link
will destroy and replace the whole app (web view) with external HTML resources.
Solution: so you may need the helps of cordova-plugin-inappbrowser plugin.
In your case,
launch an external url / website in Onsen Ui without leaving the app,
you need "_self" or "_blank" ("_blank" is used for example codes below)
// opts is optional depend on your requirements
var opts = 'location=yes';
var ref = cordova.InAppBrowser.open('http://www.example.com', '_blank', opts);
or you can use ngCordova's $cordovaInAppBrowser
angular.module('app')
.controller('ctrl', ['$cordovaInAppBrowser', function($cordovaInAppBrowser) {
var opts = {location: 'yes'};
$cordovaInAppBrowser.open('http://www.example.com', '_blank', opts);
}]);

i faced the same problem and i use this method its not fancy but it workes for me
<a class="name" href="#" onclick="window.open('https://www.youtube.com/watch?v=_OOWhuC_9Lw', '_system', 'location=yes'); return false;">
Watch
</a>

Related

Angular. Execute a angular function from a popup window

I have an angluar module.
In that module I have a controller with a function.
I need to execute that function in popup on href click.
As the popup content is not initially part of DOM or angular context, how can make a angular function to be executed by that generated code?
Here is what I try to code: codepen
app.controller('AppCtrl', ['$scope', 'myPopup', function($scope, myPopup) {
...
var infoWindow = new google.maps.InfoWindow({
content: "<a href='#' onclick='myPopup.show();'>this is my link</a>"
});
To retain is that I don't try to make execute exactly this code, I just search a way to execute an angular service function from a generated "on-fly" html code (a dynamic popup content, in my case).
First of all here's the working codepen: http://codepen.io/anon/pen/vKRWYy?editors=1010
So, the solution(just A solution. Not THE solution) is to add modal open function on window or global scope. And invoke that function on clicking the map.
window.showPopup = function(){
myPopup.show();
};
<a href='#' onclick='showPopup();return false;'>this is my link</a>
On a side note, it's generally not good practice to use non angular code with angular. It might be worth looking at an angular google maps implementation like: http://angular-ui.github.io/angular-google-maps/#!/. Maybe?

open InAppBrowser on ionicModal

I want open a web page in my app, I know I should use ngCordova InAppBrowser plugin, but how can I open the webpage in $ionicModal ? like twitter, facebook mobile apps and ...
I have this button :
<button class="button button-block button-assertive" ng-click="doPay()">Pay</button>
and in doPay() I have :
$scope.doPay = function(){
window.open(url, '_system', 'location=no');
};
but this code use external app (Safari), I want open in my application.
To open the web inside your app you have to use the _blank option instead of _system
$scope.doPay = function(){
window.open(url, '_blank', 'location=no');
};
Edit: window.open no longer works as default, to re enable it you’ll need to add this code
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
window.open = cordova.InAppBrowser.open;
}
Or use cordova.InAppBrowser.open instead of window.open

Cordova + Angularjs + Device Ready

I am developing a mobile application using Cordova and AngularJS. How do I restrict bootstrapping of AngluarJS before Cordova device ready. Basically I don't want to use any of AngularJS controllers before device ready.
Manually bootstrap your Angular app:
Remove your ng-app attribute from your HTML code, so Angular doesn't start itself.
Add something like this to you JavaScript code:
document.addEventListener("deviceready", function() {
// retrieve the DOM element that had the ng-app attribute
var domElement = document.getElementById(...) / document.querySelector(...);
angular.bootstrap(domElement, ["angularAppName"]);
}, false);
Angular documentation for bootstrapping apps.
I'm using the following solution, which allows AngularJS to be bootstrapped when running with Cordova as well as when running directly in a browser, which is where much of my development takes place. You have to remove the ng-app directive from your main index.html page since that's what the manual bootstrapping is replacing.
UPDATE: I've since switched to the following method, which I think is cleaner. It works for Ionic as well as vanilla Cordova/PhoneGap. It should be the last bit of JavaScript to run - perhaps inside a script tag before the /body tag.
angular.element(document).ready(function () {
if (window.cordova) {
console.log("Running in Cordova, will bootstrap AngularJS once 'deviceready' event fires.");
document.addEventListener('deviceready', function () {
console.log("Deviceready event has fired, bootstrapping AngularJS.");
angular.bootstrap(document.body, ['app']);
}, false);
} else {
console.log("Running in browser, bootstrapping AngularJS now.");
angular.bootstrap(document.body, ['app']);
}
});
Here's the older solution I used:
// This is a function that bootstraps AngularJS, which is called from later code
function bootstrapAngular() {
console.log("Bootstrapping AngularJS");
// This assumes your app is named "app" and is on the body tag: <body ng-app="app">
// Change the selector from "body" to whatever you need
var domElement = document.querySelector('body');
// Change the application name from "app" if needed
angular.bootstrap(domElement, ['app']);
}
// This is my preferred Cordova detection method, as it doesn't require updating.
if (document.URL.indexOf( 'http://' ) === -1
&& document.URL.indexOf( 'https://' ) === -1) {
console.log("URL: Running in Cordova/PhoneGap");
document.addEventListener("deviceready", bootstrapAngular, false);
} else {
console.log("URL: Running in browser");
bootstrapAngular();
}
If you run into problems with the http/https detection method, due to, perhaps, loading a Cordova app into the phone from the web, you could use the following method instead:
function bootstrapAngular() {
console.log("Bootstrapping AngularJS");
// This assumes your app is named "app" and is on the body tag: <body ng-app="app">
// Change the selector from "body" to whatever you need
var domElement = document.querySelector('body');
// Change the application name from "app" if needed
angular.bootstrap(domElement, ['app']);
}
// This method of user agent detection also works, though it means you might have to maintain this UA list
if (navigator.userAgent.match(/(iOS|iPhone|iPod|iPad|Android|BlackBerry)/)) {
console.log("UA: Running in Cordova/PhoneGap");
document.addEventListener("deviceready", bootstrapAngular, false);
} else {
console.log("UA: Running in browser");
bootstrapAngular();
}
Note that you still need the same bootstrapAngular function from the first example.
Why manually bootstrap AngularJS with Cordova/PhoneGap/Ionic?
Some people getting here might not know why you would want to do this in the first place. The issue is that you could have AngularJS code that relies on Cordova/PhoneGap/Ionic plugins, and those plugins won't be ready until after AngularJS has started because Cordova takes longer to get up and running on a device than the plain old Javascript code for AngularJS does.
So in those cases we have to wait until Cordova/PhoneGap/Ionic is ready before starting up (bootstrapping) AngularJS so that Angular will have everything it needs to run.
For example, say you are using the NG-Persist Angular module, which makes use of local storage for saving data on a browser, iOS Keychain plugin when running on iOS, and the cordova-plugin-file when running on Android. If your Angular app tries to load/save something right off the bat, NG-Persist's check on window.device.platform (from the device plugin) will fail because the mobile code hasn't completed startup yet, and you'll get nothing but a white page instead of your pretty app.
If you are using Ionic, this solution works for browsers and devices. Credit to romgar on this thread.
window.ionic.Platform.ready(function() {
angular.bootstrap(document, ['<your_main_app']);
});
Still need to remove ng-app from your DOM element.
This solution became more robust when I used:
angular.element(document).ready(function () {
var domElement = document.getElementById('appElement');
angular.bootstrap(domElement, ["angularAppName"]);
});
UPDATE
My suggestion was to put the above within the appropriate deviceready function, e.g.:
document.addEventListener("deviceready", function() {
angular.element(document).ready(function () {
var domElement = document.getElementById('appElement');
angular.bootstrap(domElement, ["angularAppName"]);
});
}, false);
On using the solution from TheHippo:
document.addEventListener("deviceready", function() {
// retrieve the DOM element that had the ng-app attribute
var domElement = document.getElementById(...) / document.querySelector(...);
angular.bootstrap(domElement, ["angularAppName"]);
}, false);
It doesn't work in the browser because "cordova.js" gets resolved by the Cordova or Phonegap building process and is not available in your localhost or emulated testing environment.
Thus the "deviceready" event is never fired. You can simply fire it manually in your browsers console.
var customDeviceReadyEvent = new Event('deviceready');
document.dispatchEvent(customDeviceReadyEvent);
Also make sure, that the bootstrap of angular gets triggered after setting all of you angular modules/controllers/factories/directives etc.
In most cases you probably don't need to block loading your angular app until after deviceready (mind that it can take several seconds for deviceready to fire if you have a lot of plugins).
Instead you can use something like this lib (https://github.com/arnesson/angular-cordova) which solves the deviceready issues for you by automatically buffering calls and then execute them after deviceready has been fired.

AngularJS load tabbed content directive dynamicly

I have a tabbed navigtion in my webapp that looks like this
Now I want to Change the directive each time the user clicks on one of the Navigation points. My Idea was to init the page with the first template.
$scope.currentDirective = $compile('<div order-Sale></div>');
Then when the user clicks on a tab, I wanted to change and compile the content again with a new directive in it. But for some reason this is not working. How would you proceed in order to archive this dynamic content loading? I really want to only load the content on necessary need and not just to show or hide it. I think using directives is the right way to go for it, but I'm a but stuck at the implementation... Someone any pointer ? (I don't want to use any jQuery)
What I tried [Edit]:
The controller.js
app.controller('pageController',['$scope','$compile', function($scope, $compile){
var templates = ['<div first-template></div>','<div second-template></div>'];
$scope.currentTemplate = $compile(templates[0]);
$scope.changeTemplate = function(id) {
$scope.currentTemplate = $compile(templates[id]);
};
}]);
The HTML
<div ng-controller="pageController">
<li>
<a ng-click="changeTemplate('1')">Change Template</a>
</li>
{{currentTemplate}}
</div>
UPDATE
$compile returns a linking function not a value, you cannot just bind it to your template with interpolation.
You should use ngBindHtml instead of regular bindings ( ngBind & {{ }} ).
ngBindHtml does compiling, linking and watching all out-of-the-box.
With ng-bind-html-unsafe removed, how do I inject HTML?
Here is a plunker
app.controller('pageController',['$scope','$compile','$sce', function($scope, $compile, $sce){
var templates = ['<div>first-template</div>','<div>second-template</div>'];
$scope.currentTemplate = $sce.trustAsHtml(templates[0]);
$scope.changeTemplate = function(id) {
$scope.currentTemplate = $sce.trustAsHtml(templates[id]);
};
}]);
The markup:
<div ng-controller="pageController">
<button ng-click="changeTemplate('1')">Change Template</button>
<div ng-bind-html="currentTemplate"></div>
</div>
For more robust dynamic content loading you have two good alternatives:
ngRoute from angular team.
ui-router from angular-ui team.
If you want to change and compile the content again, well that's exactly what ng-view/ ui-view directives already do for you.
Why not just use a directive:
You probably need to load a different template (html partial) for each tab.
You probably need to change the url based on the tab (and vice versa)
You probably need to instantiate a different controller for each tab.
ngRoute and ui-router come with their own directives.
You can implement your own route module if you want but that's more than just a directive.

angular.js link behaviour - disable deep linking for specific URLs

I have a working Angular.js app with HTML5 mode enabled.
$location.Html5mode(true).hashbang("!");
What I want to achieve is to get some URLs or <a> tags to do the normal browsing behaviour instead of changing the URL in the address bar using HTML5 history API and handling it using Angular controllers.
I have this links:
<a href='/auth/facebook'>Sign in with Facebook</a>
<a href='/auth/twitter'>Sign in with Twitter</a>
<a href='/auth/...'>Sign in with ...</a>
And I want the browser to redirect the user to /auth/... so the user will be then redirected to an authentication service.
Is there any way I can do this?
Adding target="_self" works in Angular 1.0.1:
<a target="_self" href='/auth/facebook'>Sign in with Facebook</a>
This feature is documented (https://docs.angularjs.org/guide/$location - search for '_self')
If you're curious, look at the angular source (line 5365 # v1.0.1). The click hijacking only happens if !elm.attr('target') is true.
An alternative to Fran6co's method is to disable the 'rewriteLinks' option in the $locationProvider:
$locationProvider.html5Mode({
enabled: true,
rewriteLinks: false
});
This will accomplish exactly the same thing as calling $rootElement.off('click'), but will not interfere with other javascript that handles click events on your app's root element.
See docs, and relevant source
This is the code for turning off deep linking all together. It disables the click event handler from the rootElement.
angular.module('myApp', [])
.run(['$location', '$rootElement', function ($location, $rootElement) {
$rootElement.off('click');
}]);
To work off the Nik's answer, if you have lots of links and don't want to add targets to each one of them, you can use a directive:
Module.directive('a', function () {
return {
restrict: 'E',
link: function(scope, element, attrs) {
element.attr("target", "_self");
}
};
});
I've run into the same issue a few times now with angular, and while I've come up with two functional solutions, both feel like hacks and not very "angular".
Hack #1:
Bind a window.location refresh to the link's click event.
<a
href=/external/link.html
onclick="window.location = 'http://example.com/external/link.html';"
>
The downside and problems with this approach are fairly obvious.
Hack #2
Setup Angular $routes that perform a $window.location change.
// Route
.when('/external', {
templateUrl: 'path/to/dummy/template',
controller: 'external'
})
// Controller
.controller('external', ['$window', function ($window) {
$window.location = 'http://www.google.com';
}])
I imagine that you could extend this using $routeParams or query strings to have one controller handle all "external" links.
As I said, neither of these solutions are very satisfactory, but if you must get this working in the short term, they might help.
On a side note, I would really like to see Angular support rel=external for this type of functionality, much like jQueryMobile uses it to disable ajax page loading.
To add to Dragonfly's answer, a best practice I have found to limit the number of target="_self" attributes is to never put the ng-app attribute on the body tag. By doing that you are telling angular that everything within the body tags are a part of the angular app.
If you are working within a static wrapper that should not be affected by angular, put your ng-app attribute on a div (or other element) that surrounds only the location your angular app is going to be working in. This way you will only have to put the target='_self' attribute on links that will be children of the ng-app element.
<body>
... top markup ...
<div ng-app="myApp">
<div ng-view></div>
</div>
... bottom markup ...
</body>
In your routes try:
$routeProvider.otherwise({})

Resources