insert an iframe into page dynamically in AngularJS - angularjs

I am trying to dynamically insert an iframe into a page with Angular 1.2. Here is the code:
html:
<div id="player_wrapper" ng-cloak>
<div ng-bind-html="player"></div>
</div>
js:
$http({method: 'GET', url: url}).
success(function(data, status) {
$scope.player = data.html;
}.......
So the data.html is a string that has a valid HTML starting with
<iframe ...>
The string contains also some div. So it could look like:
<iframe src='...' ...></iframe><div>some stuf</div>
I use in app.js 'ngSanitize'. What it shows is the div (after the iframe) but not the iframe itself.
If I use jQuery, basically a
$(#'player_wrapper').html(data.html)
works fine... but trying to make it proper angularJS.
Any idea on why only the divs after the iframe are being displayed?
Many thanks all

ngBindHtml will pass your HTML through $sce.getTrustedHtml before displaying it. I suspect this is what would be removing your iframe.
According to the docs you can use $sce.trustAsHtml to avoid this check so long as you fully trust any HTML coming from this source - an iframe from an untrusted source could likely do a number on nasty things to visitors to your page.
$http({method: 'GET', url: url}).
success(function(data, status) {
$scope.player = $sce.trustAsHtml(data.html);
}.......
Be careful! :)

You need to use the $sce service as desribed in the documentation of ng-bind-html:
$scope.player = $sce.trustAsHtml('your html goes here');
See this plunk for an example:

After much trouble I managed to get a nice setup going where I can dynamically load iframes into my page and pass information through to it.
I made this a github project. It uses a single directive for passing raw input element information, and also uses ngSanatize for the $sce.trustAsResourceUrl function.
Here is the live demo

Related

Running angular app inside shadow dom

I am developing an application, where I've to load other angular(1.x) application inside current page (As per project requirement). I am trying to achieve it using shadow DOM concept (This could be done using iframe, but I am looking for better approach). I've tried below code:
var templateUrl = "angular-app.html",
templateReceivedCallback = function (response) {
var templateHolder = $("#template-holder"),
div = document.getElementById('template-holder'),
shadowRoot = div.attachShadow({
mode: 'open'
});
shadowRoot.innerHTML = response;
};
$.get(templateUrl, templateReceivedCallback);
I am expecting that the angular application should be loaded inside template holder element:
<div id="template-holder"></div>
The other app is loading in the div which I mentioned, but expressions are not compiled as expected. Example - Angular app having variable this.greeting = "Welcome!" and I am expecting this:
Welcome!
But it rendered as:
{{greeting}}
Is there any better way to achieve this? If yes, please share running example with me.
Thanks.
I think it's not possible because Angular parsing engine won't look inside the Shadow DOM.
As a workaround, you could put the {{greeting}} in the normal DOM.
If you want to use Shadow DOM, you will always be able to access it with <slot> tags.

How to refresh iframe url?

I am creating an app using ionic in which I am displaying a URL using iframe.
This is the HTML code:
<iframe id="myFrame" width="100%" height={{iframeHeight}}>
This is the angular js:
$scope.iframeHeight = window.innerHeight;
document.getElementById("myFrame").src = value['url'];
Everything is working, however when I make changes on the site from the backend and refresh the app the new changes are not appearing in the app.
The thing you are doing in your code is not a valid way of doing it. You are manipulating DOM using native method that will not run digest cycle, you need to run it manually by doing $scope.$apply(). That will solve your problem but generally you should not do DOM manipulation from controller which is considered as BAD practice. Rather I'd suggest you to use angular two way binding feature. Assign url in scope scope variable and add that on iframe tag using ng-src="{{url}}" so that src URL will be updated by angular and as url get updated iframe will load content from src URL in it.
HTML
<iframe id="myFrame" width="100%" ng-src="{{url}}" height={{iframeHeight}}>
Code
$scope.url = "http://example.com"
As you change scope variable in the controller the the src of iframe will also gets change and iframe will reload the content.
Update
To solve caching issue you need to append current date time to you url that will every time make a new URL and it won't be cached by the browser. Something like $scope.url = "http://example.com?dummyVar="+ (new Date()).getTime() by using this it will never harm your current behavior, only you need to append dummyVar with current time value which would be always unique.
$scope.url = "http://example.com?dummyVar="+ (new Date()).getTime()
Refreshing didn't work for me with timestamp as in Pankaj Parkar's answer, so I solved it in a bit of a hacky way, which just toggles ng-if element off and on again, and forces iframe to load.
Template:
<iframe ng-if="!vm.isRefreshing"></iframe>
Controller:
refreshIframe() {
this.isRefreshing = true;
$timeout(() => {
this.isRefreshing = false;
}, 50);
}
As #pankajparkar suggested in his answer, I'd suggest you using angular 2-way data binding.
In addition to that, you need to wrap the urls with $sce.trustAsResourceUrl function in order to your iframe to work.
<iframe id="myFrame" width="100%" ng-src="{{url}}" height={{iframeHeight}}>
And
$scope.url = $sce.trustAsResourceUrl("http://example.com");

Ionic / AngularJS base64 image won't display

I am trying to simply display a base64 image in an Ionic app.
The image won't display if I do this:
HTML:
<img ng-src="data:image/jpeg;base64,{{myImage}}"/>
Controller:
$scope.myImage= "/9j/4AAQSkZJ ...";
But the image WILL display if I just put the encoded string directly in the image element like this:
<img ng-src="data:image/jpeg;base64,/9j/4AAQSkZJ ..."/>
I have checked every unsafe security setting, looked at dozens of other SO posts, etc. If I put this small example in a CodePen, it works both ways.
What could be happening to the $scope.myImage variable that would prevent it from binding to the image element? Is it an ionic thing? An angular issue?
Use data-ng-src directive like this <img data-ng-src="{{data.image_url}}">.
In your controller set base64 string as this:
$scope.data.image_url=<your base64 image source>
Hope this helps!
i had the same issue, solved it by configuring the main angular module with whitelisting this way:
angular.module('app').config(function ($compileProvider) {
$compileProvider.imgSrcSanitizationWhitelist(/^\s*(https|ftp|mailto|file|tel|data)/);})
Sometimes I too face the issue, and use setTimeout or $timeout.
setTimeout(function(){
$scope.myImage= "/9j/4AAQSkZJ ...";
}, 2000);
In Angular way (add $timeout DI in controller)-
$timeout(function(){
$scope.myImage= "/9j/4AAQSkZJ ...";
}, 2000);
just use ng-if at the div, and then the img tag gets rendered as soon as the data is loaded

Fetching HTML in Angular

I am getting started with Angular, and I want to get HTML template from a file using JavaScript, I don't want to use ng-include or any other directive as I don't really have an html to play with, I have only JavaScript file with data rendered from REST service and I need to send HTML output to the page I am in, so I don't really have any existing elements in the DOM.
So how do I get HTML from another file and use it just from JavaScript, in an Angular way?
I think you should use directive and as James point out use the $compile.
You can look some doc https://docs.angularjs.org/guide/compiler
If for any reason you don't want to do that, I can put an exemple of a really BAD angular code I use on my app to show the CGU (an HTML from another domain).
Note that we use jQuery, and that's not a good thing in Angular world.
$http({
method: 'GET',
url: 'URL_HTML'
}).success(function (data, status, headers, config) {
var html_from_server = $.parseHTML(data);
data = $(html_from_server.find('#container'));//look for the content of an ID.
$('#content_cgu').html(data.html());// get an element on our page and replace the html content
});
Take a look at $compile - it sounds like that's what you're looking for. You can take the html from your service and compile it to work in your AngularJS application.
Let me rephrase it. How do I get HTML from another page and store it in a variable inside my JS file using Angular? What do I do? var returnedHTML = ???
Straightforward solution:
var returnedHTML;
var url = 'http://www.google.com';
$http.get(url, { cache: $templateCache }).then(function(result){
returnedHTML = result.data;
});
I was just dealing with this today. I think your question was misunderstood.
You simply include an ng-include into your code like so:
ng-include="'https://en.wikipedia.org/wiki/Special:Random'"
Angular will display your URL as directly in the page.

Linking to external URL with different domain from within an angularJS partial

All I am trying to do is include an anchor tag inside the html of a partial that links to an external site. Were this standard html, the code would simply be:
google
As simple as this is, I cannot seem to find a working solution for getting past angular intercepting the route (or perhaps replacing my anchor with the https://docs.angularjs.org/api/ng/directive/a directive unintentionally?).
I have scoured SO and the rest of the web and seen a myriad of solutions for dealing with: links within the same domain, routing within the SPA, routing within a page (ala $anchorScroll) but none of these are my issue exactly.
I suspect it may having something to do with using $sce but I am an Angular n00b and not really sure how to properly use that service. I tried the following in my view controller:
$scope.trustUrl = function(url) {
return $sce.trustAsResourceUrl(url);
}
with the corresponding:
<a ng-href="{{ trustUrl(item) }}">Click me!</a>
(as described here: Binding external URL in angularjs template)
but that did not seem to do the trick (I ended up with just href="{{" in the rendered page).
Using a plain vanilla anchor link like this:
google
also failed to do the trick (even though some online advised that standard href would cause a complete page reload in angular: AngularJS - How can I do a redirect with a full page load?).
I also tried adding the target=_self" attribute but that seemed to have no effect either.
Do I need to write a custom directive as described here?
Conditionally add target="_blank" to links with Angular JS
This all seems way too complicated for such a simple action and I feel like I am missing something obvious in my n00bishness, at least I hope so because this process is feeling very onerous just to link to another url.
Thanks in advance for any solutions, advice, refs or direction.
It turns out that I did in fact have all anchor links in the page bound to an event listener and being overridden. Since that code was fundamental to the way the page worked I did not want to mess with it. Instead I bypassed it by using ng-click to call the new url as follows:
HTML:
<a class="navLinkHcp" href="{{hcpurl}}" title="Habitat Conservation Plan" target="_blank" ng-click="linkModelFunc(hcpurl)">Habitat Conservation Plan</a>
Controller:
$scope.hcpurl = 'http://eahcp.org/index.php/about_eahcp/covered_species';
$scope.linkModelFunc = function (url){
console.log('link model function');
$window.open(url);
}
And voila! Good to go.
Thanks again to KevinB for cluing me in that this was probably the issue.

Resources