Encapsulating an Angular app inside a web component - javascript

I have a simple angular-cli app consisting of only one component (app.component). I have created one custom build-script.js which I use to merge all the files (.js and .css) created using ng build --prod. So I get only two files in my dist folder (Index.html and ng-app.js).
I have another static website with just two files index.html and script.js. Now I want to load my compiled Angular app as a widget inside this static app. I am trying to encapsulate the Angular app inside web component (shadow dom) so that it will not mess with the parent static app and can be loaded as a widget.
static app index.html:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Widget App</title>
</head>
<body>
<!-- custom web component Widget holding angular app -->
<ng-widget></ng-widget>
<script type="text/javascript" src="./script.js"></script>
</body>
</html>
script.js:
window.customElements.define('ng-widget', class extends HTMLElement {
constructor() {
super();
var shadowRoot = this.attachShadow({
mode: 'open'
});
shadowRoot.innerHTML =
`
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>NgWidget</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<app-root></app-root>
<!-- The ng-app.js is not getting download since it is inside shadow dom -->
<script type="text/javascript" src="./ng-app.js"></script>
</body>
</html>
` } });
Now since the link to ng-app.js is inside shadow dom, it is not getting downloaded and my Angular app is not bootstraping.
What is the best way to render a Angular app as a widget inside a static website?

Related

ASP Net Core 7.0 SPA Configuration - does not load static files on sub URL paths

I am trying to configure Asp Net Core 7.0 to host Vanilla JS SPA APP. It seams to work when navigating to single paths, but on sub paths, it does not load the static files folder containing the Views and the main.js which is the client side routing for the JS SPA APP. It loads only index.html without the main.js and the Views, thus the app can't route to the Home view because the main.js file and the "Home.js" view are missing, actually the whole folder with the static files is not loaded.
I think that it is something to do with the Program.cs file and the configuration.
So what I am trying to do is to load the Home View when there is wrong path.
Ex. On single path as http://localhost:5109/Login works
Program.cs
using Microsoft.Extensions.FileProviders;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
else
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
// SPA
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseRouting();
app.MapFallbackToFile("index.html");
app.Run();
Thanks in advance.
The problem was the missing "/" efore the static
Before:
<script type="module" src="static/js/main.js"></script>
Now:
<script type="module" src="/static/js/main.js"></script>
The whole index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div>
<a href="/Register" class="barItem" data-link>Register</a>
<a href="/Login" class="barItem" data-link>Log In</a>
<a href="/" class="barItem" data-link>Home</a>
</div>
<!----Center - app - Content ------------------------>
<div id="app"></div>
<script type="module" src="/static/js/main.js"></script>
</body>
</html>
It works now on sub paths.

vuejs without build production code warning

I am using vuejs to make a simple page. Although I can make similar page without any framework, I wanted to try vuejs and now it it almost production ready.
Thing is it is simply single js and html file and it throws following warning.
You are running a development build of Vue.
Make sure to use the production build (*.prod.js) when deploying for production.
Let's say I want to keep things this way, how do I remove this warning and get single page html and js file?
// main.js
const { createApp } = Vue
createApp({
data() {
return {
message: 'Hello Vue!'
}
}
}).mount('#app')
<!-- index.html -->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="styles.css" rel="stylesheet">
</head>
<body>
<div id="app">
<h1>{{ message }}</h1>
</div>
<script src="https://unpkg.com/vue#3"></script>
<script src="main.js"></script>
</body>
</html>
- index.html
- assets
-- js
--- main.js
-- css
--- styles.css
As suggested by #IVO GELOV, and mentioned in guide here, it is working for me now.
Use below url for production use and to remove the warning.
https://unpkg.com/vue#3/dist/vue.global.prod.js

ES6 modules imported more than once?

I am struggeling to understand how exactly browsers are handling ES6 modules. I thought, that modules will only be executed the first time they are imported([modules: javascript.info][1].
Let's say i have following project structure:
js
admin.js
customers.js
index.js
customers.html
index.html
Both index.js and customers.js import the same module admin.js. When i import index.js in index.html the name of admin is changed from "John" to "Pete" and logged as expected.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Modules</title>
</head>
<body>
<nav>Customers</nav>
<h1>Homepage</h1>
<script type="module" src="js/index.js"></script>
</body>
</html>
In customers.html i expected the admin's name to be "Pete" as well:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Customers</title>
</head>
<body>
<nav>Home</nav>
<h1>Customers</h1>
<script type="module" src="js/customers.js"></script>
</body>
</html>
But instead of "Pete", "John" is logged again.
Modules i used:
// admin.js
export let admin = {
name: "John",
};
//index.js
import { admin } from "./admin.js";
admin.name = "Pete";
console.log(admin.name); // Pete
// customers.js
import { admin } from "./admin.js";
console.log(admin.name); // Pete
[1]: https://javascript.info/modules-intro#a-module-code-is-evaluated-only-the-first-time-when-imported)
As Felix said above, each page render/rerender would then reload all assets. This is the difference between a Single Page Application and a Multi Page Application. You're working with an MPA, so you would need some form of data persistence between pages, such as databasing the data server side and requesting it on each page load, or placing the necessary persisted data in something like localStorage or sessionStorage for access between pages.

How to connect CSS and JS to HTML which is sent by Dart HttpServer?

I have created a Dart HttpServer which shows "HTML" code on the browser but I also want to connect "CSS" & "JS" to this HTML,
How should I do that? please help
HttpServer _server;
_server = await HttpServer.bind(InternetAddress.anyIPv4, port);
_server.listen((request) async {
request.response
..headers.contentType = ContentType.html
//HTML Code
..write('''
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<! -- <link rel="stylesheet" href="styles.css"> -->
<title>Hello World</title>
</head>
<body>
<p>Hello WOrld</p>
</body>
<! -- <script src="app.js"></script> -->
</html>
''');
await request.response.close();
}
PS 1: One Solution is to add CSS and JS codes in the HTML code which would work but is less efficient.
PS 2: I am using this dart code in a flutter project.
Just use html tag.
Don't neglect every source imported by html tag is a http request. you should handle these requests. Dart HttpServer doesn't handle these.

Can a libgdx web application work along with web components technology?

I'm working with libgdx 1.9.2 and gwt 2.6.1.
After the GWT-compilation of my java app, I get a JS script (html.nocache.js) that I can include in my html page, and visualisate in a web browser (inside a div, here it's "embed-html"). That part is working nicely.
Here's the code:
<!doctype html>
<html>
<head>
<title>my-gdx-game</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link href="styles.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="html/html.nocache.js"></script>
</head>
<body>
<div id="embed-html"></div>
</body>
</html>
My next goal is to use web components, and more precisely custom elements, to have a simple tag <my-app></my-app> in any web page to get my application.
my index.html:
<!doctype html>
<html>
<head>
<title>my-gdx-game</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script src="webcomponents.js/webcomponents.js"></script>
<link rel="import" href="component.html">
</head>
<body>
<my-app></my-app>
</body>
</html>
my component.html:
<template id="template">
<div id="embed-html"></div>
<link href="styles.css" rel="stylesheet" type="text/css">
</template>
<script>
var helloDoc = document._currentScript.ownerDocument;
var myApp = document.registerElement('my-app', {
prototype: Object.create(HTMLElement.prototype, {
createdCallback: {
value: function() {
var root = this.createShadowRoot();
var template = helloDoc.querySelector('#template');
var clone = document.importNode(template.content, true);
root.appendChild(clone);
}
}
})
});
</script>
<script type="text/javascript" src="html/html.nocache.js"></script>
But the JS script generated by GWT-compilation has some document.write(...) inside; so all that is included is my empty div, my style sheet correctly loaded, and warnings: "Warning: A call to document.write() from an asynchronously-loaded external script was ignored". Since it is generated, I don't think I can avoid using these document.write().
If I put the <script type="text/javascript" src="html/html.nocache.js"></script> in the head of index.html (where it was before I tried using webcomponents), the app is not added inside the div, as it should, but under (the div and style sheet are included as expected).
And if I put the script inside the template, nothing happens.
So I am wondering if there is a way to have a GWT application working with web components, or if I should search for another way to easily include my application into external websites.
(If you wonder the reasons why I want to do so, it's because I want clients to be able to add my app easily on their own website, with only an import and a tag, the same way I could import a YouTube video or a Google map.)

Categories