I want to integrate my angular app in many others simple web pages, but without iframe
In the next code we see a simple and external html web page called "Shoes Store".
"Shoes Store" is a web that sells shoes. And my goal is in <div id="my-angular-app"></div> to add my entire my-angular-app in that div.
As you can see, first, we need a async petition for then instantiate in a varible the my-angular-app.
The goal is to do something like next html. See how my-angular-app is called async
<!doctype html>
<html lang="en">
<head>
<!--external web page-->
<title>Shoes Store</title>
</head>
<body>
<div id="my-angular-app"></div>
<script async src="http://localhost:4201/my-angular-app.min.js?secret=abcdfg"></script>
// see how myAngularApp is instanciated (many times as you want)
<script>
myAngularApp = new MyAngularApp(document.getElementById('my-angular-app'), {
someParams: {x: 'x', y: 'y'},
otherParams: 1
});
</script>
</body>
</html>
As you can see, I want implement the same architecture of google maps api, but with my angular app.
Imagine that you are the owner of google-maps and no are implementations yet, and the goal is implement the same way as nowsdays works, but with a angular-app.
the result will most something like this:
see this diagram
page1, page2, page3 can integrate to my-angular-app and they can instantiate all entire app, many times using javascript, instead iframe tag
Please, the next implementations are inviables:
No iframe
No angular elements
No Webpack 5 Module federation
someone have an example to integrate this ?
very much apreciated
Currently Angular is not terribly well fitted for that use case. But you can build an angular element and bundle the required other dependencies.
The "element" represents the application root element, but you can have additional compenents, even routing, down the component tree as usual. (You have a root element in every angular app, as well.)
Here is an example repository that shows how to build and embed the element: https://github.com/trion-development/corona-covid19-simulator
The interesting part is the concatenation of all dependencies in https://github.com/trion-development/corona-covid19-simulator/blob/master/package.json#L12
Related
We created a widget as an Angular app, which our customers should be able to easily load and integrate into their own website.
The most straightforward way (which works) to do this is simply to tell them to include the default HTML tags from the index.html on their website:
<base href="/">
<app-root></app-root>
<script src="https://ourdomain.com/widget/runtime.js" type="module"></script><script src="https://ourdomain.com/widget/polyfills.js" type="module"></script><script src="https://ourdomain.com/widget/main.js" type="module"></script>
However, we would like to minimize the above code and provide them a one-liner which includes a JavaScript that loads the code dynamically into the DOM, e.g. <div id="widget"></div><script src="https://ourdomain.com/widget/start.js"></script>. The script would simply consist of:
<script>
document.getElementById('widget').innerHTML = '<base href="/"><app-root></app-root>...';
</script>
The tags are loaded correctly into the DOM but the Angular app i.e. the scripts which are dynamically included into the DOM don't load.
How can this problem be solved? Is there a method in main.js which needs to be called additionally to bootstrap the Angular app?
The Angular app is deployed and hosted on our server, e.g. on https://ourdomain.com/widget. The goal is that anyone can load and plug the app into their own website using the above approach.
It turned out to work just like that:
<script>
document.write('<base href="/"><app-root></app-root>...');
</script>
Basically, I have two components page1 and page2 and I would like to draw a google Gantt chart on the second page.
However, when switching to page2 nothing is rendered.
From what I understand you must load google chart inside the <head> element of index.html file, but because the container that should render the chart inside my component page2 is hidden at the start, google chart cannot find render it.
I have tried moving the google chart script to the html file of page2 but still no result.
Making page1 the container works but as soon as I switch pages it disappears when switching back to page1.
Here is my stackblitz with the code: https://stackblitz.com/edit/angular-button-routerlink-xglnar?file=src/index.html
Is there a way to work around that? Thank you!
You can always look for some npm library that acts as a wrapper if you're unsure about how to do it properly - i.e. angular-google-charts. Note - I didn't test the library and whether / how it works.
You can also make changes yourself.
Note that you don't have place all the scripts in the head - important part is referencing the google loader:
<head>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
</head>
Then you can use the global functions / variables imported from the file anywhere in your app. But, since Angular uses TypeScript, it will warn you that the 'google' object is not defined. To work around it, you can simply declare an empty const - which will be replaced on the runtime by the script imported from the google hosting:
declare const google;
Then you can simply put the required script in the OnInit hook of your component and it should work properly. Of course replacing the document.getElementById("chart_div") by Angular way of getting the container reference is preferred (i.e. ViewChild).
Updated stackblitz with working barebone minimum example: https://stackblitz.com/edit/angular-button-routerlink-6vzuyd
I'm having a problem with scripts in Angular 4. Let me explain: I'm building an Angular app that will be included in a greater web application. So my app is only one among other apps inside this greater web application. In my app I need to include some HTML code representing common areas of this web application. They would be the head, header, menu and footer of the app. My app would be placed in the remaining space. Thus, I retrieve these HTML codes, turn them into SafeValue by bypassing sanitizing and include them by using the innerHTML property of some divs. After that I can see these HTMLs rendered with styling and all.
So this is the context. The problem is that the scripts in these HTMLs don't run. Even though they are not removed (you can examine the page's HTML and see the scripts there), they do not run. I need them to run as they are needed to perform some important tasks such as to fill the menu with links, animate menu expansion and god knows what else.
I have already tried to include these HTMLs in the index.html using the document DOM object to replace a div I've put in index.html as a placeholder, but I've had the same problem: it renders, but the scripts don't run. Something interesting is that if I put the script tag that is not running in the index.html directly (hardcoded, not dynamically) it works.
So, the scripts would have the following form:
<script type="text/javascript" src="//some_external_source"></script>
Only a remark: I have no control over these common HTMLs that I receive. I just receive them and have to use them for the sake of visual identity of the web application.
Sorry if it has already been answered. I have been looking for an answer for days now and I still didn't found one (I did found something similar for AngularJS though), so I posted.
This is not the way angular 2 intended such problems to be solved, if you want to divide your app into separate parts like: content, header, footer you should probably take a look at named router-outlets, or transcludion.
But if you want to do this your way, then do this:
#Component({.your metadata..})
export class SomeComponent{
constructor (private domSanitizer:DomSanitizer){
this.domSanitizer.bypassSecurityTrustScript(yourScript);
}
}
Am new to AngualrJS. I reference index.html as my home page and I want to map a partial link which is not at all related to the home page(index.html); example,
http://www.example.com/newpage.
Here, the newpage shouldn't have any connection with the index.html. and where to put my newpage.html in the project.
To achieve what you want, you need to have two differente apps. Every app needs a fixed route prior to the '#'.
So, in your case, index.html would have it's app, and newpage.html would have another one.
See there is no way to ignore the index.html, so keep the index.html as plain page without any design and create different master pages
See the detail here how can you do it with demo.
I am using backbone.js and building a single page application, inspired by trello.com ..
I want to know how you show many pages on top of the original page. As in how you architect it.
How do you use Backbone routers to achieve this?
For example in trello
Basepage
And then now on top of the base page you have dynamic content
like a cards detail
like a boards details
How could i architecture something like this?
I've done a couple of approaches so far in projects with 50+ pages and they both scaled well. I did not use backbone.js but the approaches are straight forward and do not require a framework to learn other than I used jQuery for selectors.
Both of them have in common creating a single overlay window that you can pull in content into the window. I wrote mine from scratch but you could easily use jQuery UI dialog. The two approaches only differ in how the content is pulled. Also, using the information on the link is all you should need to pull in the "module" or overlay content as your rule. Do not need tons of scripts loaded in to start your app. Have the modules pull in the behavior for you.
Option 1) Use the jQuery load method to pull content from stand-alone web pages by using a placeholder variable like so:
var $ph = $('<div />');
$ph.load(URL); // loads gui of remote URL + executes any script that URL has
The $ph var now contains all the GUI loaded in from the external URL so you can use selector on it to extract the particular HTML and place it into your DOM or overlay as you need.
Here is an example of the stand-alone HTML output:
<div class="module">
<a class="link">click me</a>
</div>
<script>
(function(){
// put any private vars here
$('.module .link').click(function(){
// do something
});
})();
</script>
If you remove() or destroy the dom inside the overlay through jQuery, it will automatically remove all the events directly assigned aka "bind" and "unbind" them but using "live" or "delegate" you will need to worry about "die" and "undelegate" etc. just doing die('.namespace').live('click.namespace') will ensure is cleaned.
Here is an example of this on one of my websites -> http://www.kitgui.com/docs
But the better example is within the customer section as the docs is fairly simple using hash history.
2) Using an iframe inside your overlay and assigning it a URL.
This is the easiest option but is a little slower because each page called has to have a full standalone behavior and dependencies with the iframe. Also you must worry about sizing the frame etc. unless you have a fixed overlay window.
You must have a loader overlay your iframe while its loading then have the iframe talk the parent to tell it its done loading and hide the loader.
I did this for several sites but one of them is a site in development you can see here to get the code ->
http://dev.zipstory.com (sign in and go to my zipstory and click "group" settings etc to see this, just view source to see how I did this as its all there)
The thing about iframes is you should write some code on the parent that accepts standard messages from the iframe that you agree on as a typical set of behavior such as notifying its done loading or passing messages to update something on the parent etc. This can be added on the fly and refactored as you need as long as your aim is KISS approach.
Each of the 'dynamic content' pages should be a template (underscore.js gives you _.template()) rendered by a backbone view. The main page needs to have events that initialize new views and render the templates. Look at the todos app (http://documentcloud.github.com/backbone/docs/todos.html) to get a basic idea about the flow of a backbone app.