Persisting an iframe in Angularjs - html

So I've recently been converting an old project to Angularjs, but there's a bigger section that I can't convert right now, but still need to work inside Angular.
To solve this I used an Iframe. The problem now is when I switch to a different page, the view and by association the iFrame is getting destroyed. This means when I switch back it will reload the iFrame and will lose the user's spot and any data they didn't save on the form. Usually I solve this by storing everything inside a service, but it won't work for this since its an iFrame.
Is there anyway to create the iFrame outside of the context of the template so when I switch back to the page I can call the iFrame to display, rather than reloading it, then I can manually destroy it when I want?
Or is there a better way to go about doing this?
Thanks!

for anyone interested, what I ended up doing is putting the iFrame in a parent template inside an ng-if. When I go to the route I want the iframe in, I set the ng-if to true and leave it as true when I'm selecting different tabs and want it to persist, when I want it to switch or not persist I set the ng-if back to false and everything seems to be working as expected.

Related

How do we get iframes to allow state changes to reflect in our components?

I'm building a component that uses an <iframe> to display another component. This component connects to an NGXS state which needs to reflect changes made to the state. After a lot of failures and testing I discovered the component will always only load the default settings of the state. I created a <button> to toggle a boolean and added an *ngIf to the <iframe> so I can force it to reload manually after trying things like this.Frame.(contentDocument || contentWindow).location.reload(true); didn't make any difference.
I created a stablitz app to demonstrate this issue however I think stackblitz blocks the use of <iframe>s in their platform so you might need to copy it into a local project to tinker with it. It's a simple app that shows the state outside of the <iframe> as well as inside with a button that toggles the <iframe> on and off so you can see how only the default values load after you update the value I have available for demonstration purposes. I'm not getting any type of errors and the issue isn't a matter of something being wrong with the code so I don't know what more to show that isn't in the stackblitz.
Does anybody know why and how <iframe>s do this and if there's a way around it? The only thing I can think to try is make a NestJS app to see if putting the data outside the app and making an API request from the component inside the <iframe> will be allowed, however I don't know why this issue is occurring to in turn know if that too won't be rejected for that same reason. How this can be handled?
The document running in an iframe is isolated from its host. They do not share memory- Angular does not provide a way to synchronize state between a host and an iframe on the page out of the box. The example is actually booting two Angular apps (one inside the frame and one outside). If you are using an iframe for security and isolation purposes, you'll need to devise a way to pass state between the host and the child via postMessage (and be aware that you are running two copies of your application). If this isn't for security/isolation, simply do not use an iframe to contain the child component.

Evaluate javascript on every dynamically loaded nested iFrames using Puppeteer

Before I start describing my problem I just want to give a heads-up that all the pages, iFrames etc. are hosted locally on my PC. And that I have used page.setBypassCSP(true) to temporarily disable any origin based restrictions.
Here we go, I have a webpage which embeds an iFrame and that iFrame may embed another one (and the list can go on...). Some of the deeper iFrames may be appended to the body of it's parent via Javascript e.g. document.body.appendChild inside a setTimeout(..., 3000) which kind of simulates a dynamic iframe load. I want to know what is the best way to evaluate a script source on all of these iFrames. I tried using page.on('framenavigated', ...) but this only works for the page's immediate child frame(s).
I tried recursively iterating through all the frames in the page using page.frames() but that only works for iFrames that are available at the time when the DOMContentLoaded event is fired.
I'm looking for a way to listen to all the framenavigated events fired by all the nested iFrames even for the ones that loaded dynamically at any point of time, after the page is loaded. Any pointers would be greatly appreciated.
UPDATE:
I have tried listening to events using page.on('frameattached', ...) and page.on('framedetached', ...) but that also doesn't let me list all iFrames.

How to append the Smooch web-messenger-container element to a custom element

I want to be able to append the #web-messenger-container element to an element instead of the document.body.
I've tried using Smooch.render without setting the embedded attribute to true and it works fine on some browsers, but on others, the smooch CDN calls are cancelled. It is related with this issue: https://github.com/smooch/smooch-web/issues/666
I don't want to use embedded mode, I just want to move the Smooch button to another container. I've tried moving the iframe element with JS but it causes the iframe to reload and the Smooch window disappears.
I would say if you want to append #web-messenger-container to a different element, embedded mode is the way to do that. Without embedded mode Smooch's host JS will call render() to append the iframe on it's own so trying to call it second time will give you nothing but grief I think.
If all you want is to render your own open/close button, that's pretty straightforward. You can specify a custom button width and height of '0', and trigger Smooch.open() / Smooch.close() however you like.
For example:
https://jsfiddle.net/alavers/ve5uhjnd/

Yii2 nested pjax

I have page with tabs (which are actually links handled by parent pjax). Which loads the tab content via pjax calls.
In one of the tabs, I have a gridview which is inside a pjax container. So that makes it a nested one.
The problem is that the nested one when loaded and inserted into the page, does not include it's own javascript i.e:
jQuery(document).pjax("#history-gridview a", "#history-pjax", {"push":true,"replace":false,"timeout":5000,"scrollTo":false});
You need to call renderAjax() when requesting the tab page (or content). I do something like this:
if (Yii::$app->request->isAjax) return $this->renderAjax('myview');
else return $this->render('myview');
However, it may not fix your problem. I've found if I navigate tabs and a grid is loaded dynamically in the tab (with its own pjax container), then any interaction with grid sort and filter tries to reload from the outer (pjax tab) container even with skipOuterContainers set to true.
On a side note, the developers are thinking of dropping pjax support completely as per here as well as how asset bundles work.
The question remains:
How to create super fast performance like an SPA (single page app)
without Angular2 or similar? The grid container within a tab container
is the perfect example which, if could be achieved (catering for
back/forward buttons, initialisation scripts) would be awesome.

page break in HTML

i want to use page break in html that means the reader cannot scroll down further until he select a link for it.
<SPAN id=title><A name=BdToc_1 external=yes><h1 id="BookTitle" align="center"><font color="#B90000"><b>Choose Subject</b></font></h1>
</A>
</SPAN>
<p>
Contents....
</p>
I want a page break before and after this. Please help me
Forgive me for pointing out the obvious, but page breaks are used to separate distinct pages. Each HTML document is a distinct "page". "select[ing] a link" traditionally loads a new page. So.... why don't you just load the next page when they click on this link?
You can specify where page breaks occur using CSS properties page-break-after, page-break-before. Of course, this works only when printing the web page. As far as I know, these properties are correctly implemented in all major browsers including IE6+. Additionally, you can also state that page break should not occur inside an element using page-break-inside.
If you want paging per se, you need to have HTML for each page and interlink these pages. Or you can fetch contents of each page using AJAX dynamically, which of course involves scripting.
It's not quite possible in HTML. You could try makeing something in Javascript, but anyone can dissable javascript.
Why would you want something like this?
You can use onscroll in javascript to control the scrolling. The onscroll event can determine the current position and there is a function to scroll up if the user is too far down.
Then, when the user clicks the link, you set a flag (scrollok=1). The onscroll checks the flag and now permits scrolling.
If you want to defeat people who have deactivated javascript, just make the content invisible until they click using stylesheets: visibility=none.
Then, when they click the link, you enable scrolling via the flag, and make the content visible.
If you don't know how to do these things, just leave a comment and I can be more precise.