How to refresh iframe url? - angularjs

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

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.

Refresh image without changing ng-src

I have an image upload form which allows the user to upload a new profile picture. I need the image to refresh after a successful upload (with the same url in ng-src). I tried to append a random value to ng-src to force image reload using $scope.$apply but it's not working.
You don't need to use $scope.$apply, ng-src watches for changes so if you set a different value of what it was before it will change the image, check code and jsfiddle below:
https://jsfiddle.net/twizzlers/oebx8any/1/
$scope.current_src = "http://www.w3schools.com/css/trolltunga.jpg";
$scope.upload = function(){
//before upload
$scope.current_src = "test";
//after upload
$scope.current_src = "http://www.w3schools.com/css/trolltunga.jpg";
}
Hope it helps =)
I solved partially. I just added a function that delete the img dom and add it again (i know that's not the perfect solution but it works at all)

How to wait for Meteor subscription before launching angular app

I am using angular-meteor with pascalprecht.translate
the translations object have to be stored in the database in order that some users can modify the translations via a back-office
I subscribe the collection containing the translations and loads them in the .config()
it works well BUT when loading the application the page is rendered before the subscription is ready.an during a short period of time the texts are not translated.
I have to do something in order that we always see translations even during the begining
My question is the following:
Is it possible to make angular wait for the subscription to be ready before it is launched ?
Best regards
bboisvert
angular.module('test').config(['$translateProvider', function ($translateProvider) {
Meteor.subscribe('settings', function(){
test = Settings.findOne({name: "translations"});
$translateProvider.translations('fr-FR', test['fr-FR']);
$translateProvider.translations('en-EN', test['en-EN']);
});
}]);
In the Meteor.subscribe callback, you could do $rootScope.$broadcast('meteorSubscribed')
on your root-level directive/controller listen for it and set a $scope variable to say it is loaded. You could then use that variable for ng-if or ng-show
example:
$scope.$on('meteorSubscribed', function(){
$scope.meteorReady = true;
});
in template:
<div ng-app="test" ng-controller="RootController" ng-show="meteorReady">
<!-- your app here -->
</div>
You could also circumvent the whole event + controller setup and just set $rootScope.meteorReady = true; right in the Meteor.subscribe callback. Really depends on the setup of your app.

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

IndexedDB callback not updating UI in angularjs

I am using the following library to access IndexedDB in Angularjs on a new Chrome App: https://github.com/aaronpowell/db.js
When I try to update the UI on App startup by using this :
db.orders.query().all().execute().done(function(results) {
$scope.ordercount = results.length;
});
in my main.html I have used the ordercount variable as:
Orders : {{ordercount}}
However, the UI is not updating unless I do ng-click or any other ng-* events. All I need is to show number of orders when my app is loaded. I tried $scope.apply(), but it throws error saying apply() is not available.
Please help.
Since you are getting the values from out side of the angular js you need to do it like this,
$scope.$apply(function(){
$scope.ordercount = results.length;
})
It seems like you access $scope from out side of the angular world. You should get scope object first if you want to notify angular that the data had been updated.
//assume you have a controller named "dbCtrl" e.g., <div id="container" ng-controller="dbCtrl"></div>
angular.element($("#container")).scope().$apply(function(){
$scope.ordercount = result.length;
});
Hope this is helpful.

Resources