open-wc how to use web components in a legacy application - web-component

I had a look at the open-wc generator. I can generate web component libraries and web component application but the generated README file and the documentation does not contain a description how to import a web component library into another library or into an application so that the library or application can use the dependency as a web component. Is there a sample but non trivial application build with open-wc that I can use to learn from?
My primary interest is to import several web component into a legacy application that does not use npm and rollup by itself. What would be the best way to do that?
What I have tried to do. I have created a library litelement-demo by running
npm init #open-wc
and I have created an application in the similar way. I have opted for using typescript in both cases. The README.md of libelement-demo states that it can be used in this way:
<script type="module">
import 'litelement-demo/litelement-demo.js';
</script>
<litelement-demo></litelement-demo>
I have added this snippet to the application's index.html and run
npm i --save ../litelement-demo
npm run build
but the 2nd command fails with the error message
(!) Unresolved dependencies
https://rollupjs.org/guide/en/#warning-treating-module-as-external-dependency
litelement-demo/litelement-demo.js (imported by inline-module-index-1.js)
The link in the error message does not help and neither the open webcomponent documentation nor the generated README.md files.

Typical web component is basically a class as follows:
// You can also use some external library and inherit from its base class.
// For example: LitElement
class BasicSetup extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
// Template/DOM generation
}
// One or more methods...
}
// Registration
customElements.define('basic-setup', BasicSetup);
Have a look at a registration statement. Simply add this file in your HTML scripts section and you are done. You do not have to integrate with any existing library or solution. Wherever, you have HTML, you can simply use it as
<div>
<p>My Awesome web component</p>
<basic-setup></basic-setup>
</div>
You can also initialize the element with JavaScript using customElements.get(name) method if you do not have access to BasicSetup class reference.
// Get reference to basic-setup class assuming it is already registred.
const ClassRef = customElements.get('basic-setup');
// Initialize using constructor
const myCustomElm = new ClassRef();
// or use document.createElement
const myCustomElm = document.createElement('basic-setup');
document.body.appendChild(myCustomElm);

Since your legacy application doesn't use npm, you don't need to do anything with it an npm.
Just add in the head
<script type="module">
import 'litelement-demo/litelement-demo.js';
</script>
and then use
<litelement-demo></litelement-demo>
somewhere in your html. Nothing else needed to start working

Related

Using Lit with Javascript and no build tools

I am building a desktop app that monitors some things and generates data about what it is monitoring. When the user wants to interact with the data the app starts a very simple web server. The server serves static pages and has a basic http API to serve the data. I use html as a universal UI, the user uses their browser to view and interact with the data.
I would like to rewrite my html/css/js into a component based web app using Google's Lit 2. I like the idea of plain web components but I noticed that Lit offers some great additional features. Not surprisingly, most of the Lit docs are geared toward a more traditional web environment with a build step. I want to see if I can keep my server as simple as possible and avoid traditional backend tools (typescript compilation, minification, etc). I would like to replace my current static html/css/js with Lit components in a series of simple js files.
Currently, my server serves my pages from a 'public' directory and has a minimal http API:
- public/
-- js/
-- css/
-- index.html
How should I use Lit in a system without a build step? What is the minimum set of Lit files I would need to serve along with my own javascript classes that inherit from LitElement?
2022 update: Starting with version 2.2.0, lit is also available as a pre-built bundle, see https://lit.dev/docs/getting-started/#use-bundles
<simple-greeting name="World"></simple-greeting>
<script type="module">
import {html, css, LitElement} from 'https://cdn.jsdelivr.net/gh/lit/dist#2.4.0/core/lit-core.min.js';
export class SimpleGreeting extends LitElement {
static get styles() {
return css`p { color: blue }`;
}
static get properties() {
return {
name: {type: String}
}
}
constructor() {
super();
this.name = 'Somebody';
}
render() {
return html`<p>Hello, ${this.name}!</p>`;
}
}
customElements.define('simple-greeting', SimpleGreeting);
</script>
Original answer:
The Lit team doesn't provide a pre-built bundle as of 2021-08-01, you have to build yourself (to resolve the bare module specifiers, such as import .. from 'lit-html', which are not supported by browsers yet)
If you're fine with relying on a third-party CDN and supporting modern browsers only, skypack is very useful, as you can simply import lit from 'https://cdn.skypack.dev/lit'; in a web page.
(If you open https://cdn.skypack.dev/lit and then the pinned URL specified in comments, you can see there are only 5 JS modules involved, so extracting them from lit's source by hand to host as part of your application shouldn't be very hard either.)

Deno - Importing TypeScript into a JS file

In Deno, to import a TypeScript module, does your own code file have to be TypeScript? Or does Deno auto convert TypeScript to javascript before the module gets imported?
I want all my code files to be EcmaScript modules (js or mjs, but not ts).
Unlike everyone else these days, I want to avoid using TypeScript in my own code. I dislike the rigidity of static types and Typescript is not part of the EcmaScript standard. EcmaScript alone has all I need to manage big projects. To me, TypeScript is an antiquated technology that has not been necessary since the advent of ES6 modules. The types of problems TypeScript addresses are problems I do not have.
You can write your own code with JavaScript.
Suppose you have or are using a TypeScript file/module numbers.ts:
export function isEven(n: number): boolean {
if (n % 2 != 0) {
return false
}
return true;
}
You can import and run it with an app.js JavaScript script:
import { isEven } from "./module.ts";
const one = isEven(1)
const two = isEven(2)
console.log(one)
console.log(two)
Deno does the TypeScript convertion to JavaScript internally. The process is the same when using standard or 3rd party libraries. The folks at the Deno project went even further by adding it as a goal:
https://deno.land/manual/introduction
Browser compatible: The subset of Deno programs which are written
completely in JavaScript and do not use the global Deno namespace (or
feature test for it), ought to also be able to be run in a modern web
browser without change.
Name resolution must be fully qualified. There's a whole lot more about referencing type definitions in this dedicated page for using TypeScript:
https://deno.land/manual/getting_started/typescript
Deno supports both JavaScript and TypeScript as first class languages
at runtime. This means it requires fully qualified module names,
including the extension (or a server providing the correct media type)
Example:
import { config } from "https://deno.land/x/dotenv/mod.ts";
Following my example above you can use the bundle command to generate a single JavaScript file with all the dependencies. Bundling it will take my app.js and module.ts files and create a new file app.bundle.js which is JavaScript.
https://deno.land/manual/tools/bundler
$ deno bundle app.js app.bundle.js
Bundling file:///home/pomatti/projects/deno-sandbox/app.js
Emitting bundle to "app.bundle.js"
3111 bytes emmited.
$ deno run app.bundle.js
false
true
It can even be loaded in the browser:
Bundles can also be loaded in the web browser. The bundle is a
self-contained ES module, and so the attribute of type must be set to
"module". For example:
<script type="module" src="website.bundle.js"></script>
As for ECMAScript modules I would like to point out that TypeScript implements it as well.
https://github.com/microsoft/TypeScript/issues/2242
https://www.staging-typescript.org/docs/handbook/modules.html
Starting with ECMAScript 2015, JavaScript has a concept of modules.
TypeScript shares this concept.
Now, the "static type" discussion falls out of scope of this forum so I won't touch it here, but I believe I covered everything else.

How do I consume a polymer lit-element?

I have a litElement that I will need to consume from another domain. My browser is Chrome, I am using 'polymer serve' and navigating directly to the es5-bundle.
The lit-element is very simple. Just some static text.
When I use 'polymer build' my entry HTML page gets compiled (or transformed). I see a reference to 'custom-elements-es5-adapter.js' is added, as well as other custom JavaScript. When I navigate to this entry page (in the build folder) everything works. However, if I replace that compiled version with the original uncompiled version I get an error in the chrome console 'define is not defined'.
Eventually I will be calling this from another domain and will not be building the HTML it with polymer.(I have already tried it cross-domain and it's not working)
What do I need to include in the client to consume the polymer lit-element?
Here is what I have:
<body>
<my-element></my-element>
<script src="../node_modules/#webcomponents/webcomponentsjs/webcomponents-loader.js"></script>
<script type="module" src="./components/my-element.js" crossorigin=""?</script>
</body>
lit-element requires a transform step. The files the browser consumes must be transformed. If you want to deploy your original source files, the web server to which you deploy them needs to perform the transform step itself (as polymer serve does).
Source: lit-element README:
LitElement is published on npm using JavaScript Modules. This means it
can take advantage of the standard native JavaScript module loader
available in all current major browsers.
However, since LitElement uses npm convention to reference
dependencies by name, a light transform to rewrite specifiers to URLs
is required to get it to run in the browser. The polymer-cli's
development server polymer serve automatically handles this transform.
Tools like WebPack and Rollup can also be used to serve and/or bundle
LitElement.
The lit-element README has an example that will run in a browser with no transform steps. The example loads the lit-element library as modules from unpkg like this:
<script type="module">
import {LitElement, html} from 'https://unpkg.com/#polymer/lit-element#latest/lit-element.js?module';
class MyElement extends LitElement {
...
</script>
<my-element></my-element>
That method is useful if you want to try out lit-element with less messing about, but the Polymer team doesn't recommend doing this in production; AFAIK unpkg has no guarantees about uptime or performance.

Using Bootstrap-Slider in Vue with Typescript

I'm trying to create a boostrap-slider on my page using a vue backend built with TypeScript and ASP net core. I'm using the standard template for Vue.js with TypeScript in ASP.NET Core.
I've imported the boostrap-slider types with
npm install --save #types/bootstrap-slider
and when I try to
import { Slider } from 'bootstrap-slider';
I get the error
ERROR in [at-loader] ./ClientApp/components/mycomponent/mycomponent.ts:3:24
TS2306: File '~~redacted~~/node_modules/#types/bootstrap-slider/index.d.ts' is not a module.
To achieve your goal you can refer to this MSDN post.
This sample demonstration will help you to setup Vue.js with TypeScript in ASP.NET Core.
Complete Description
setup Vue.js with TypeScript in ASP.NET Core.
Sample Source Code:
Vue.js with TypeScript in ASP.NET Core
To achieve Boorstrap-Slider you can use vue-bootstrap-slider
for further details see link: vue-bootstrap-slider
The error occurs because the type definitions don't export a module, so you can't import it. They do this because you can call the slider functions through jquery:
var someSlider = $("input.slider").slider();
var value = someSlider.slider('getValue');
These functions are properly typed because the typings are found even without any imports.

ExtensionContext error while creating Native Extension in Flex 3.6 SDK

I'm creating native extension with Flex 3.6. Coded native side then created Flex Library Project and then create .ane file. Finally imported .ane file to myFlex Project. Here is the problem I had. While I'm debugging app, "1046: Type was not found or was not a compile-time constant: ExtensionContext" error occurs. Attached the Library project .as class .
Thanks in Advance
package com.extension.samples
{
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;
import flash.external.ExtensionContext;
public class NetworkConnectionANE extends EventDispatcher
{
public var _extContext : ExtensionContext;
public function NetworkConnectionANE(target:IEventDispatcher=null)
{
_extContext = ExtensionContext.createExtensionContext("com.extension.samples.NetworkConnectionANE", null);
super(target);
}
public function Connect(path:String):int
{
return _extContext.call("nativeFunc", path);
}
public function dispose():void
{
_extContext.dispose();
}
}
}
Edit:
I tried to use .swc file that created from library project in another Flex Desktop app, but the same error
Also tried with _extContext = ExtensionContext.createExtensionContext("com.extension.samples.NetworkConnectionANE","");
Edit: The problem about Flex SDK,no problem in SDK 4.6. Now the question is, How to use Extension in lib project in Flex 3.6 SDK ?
Right click on the project in flash builder goto properties of project and add air libraries in the flex library compiler.
I had the same problem but it was resolved in the following way:
File > New > Flex Library Project
Check the "Include Adobe AIR Libraries" option
As I know ExtensionContext.createExtensionContext() can be null in these cases:
The call is not in an .ane file. You cannot call this from a .swc or a .swf file. In other words it needs to be compiled to an .ane file before calling it.
You try to use the extension in a platform, that is not supported by the extension. For example you try to use an iOS extension on PC.
The ID for the extension does not exists. The extension ID must be the same, as the one you specify in the extension.xml like:
<extension xmlns="http://ns.adobe.com/air/extension/3.5">
<id>com.extension.samples.NetworkConnectionANE</id>
<versionNumber>0.0.1</versionNumber>
....
btw you dont need to set the second parameter of the ExtensionContext.createExtensionContext call, unless you want to specify OS-specific APIs (I havent even seen apps, that do this)

Resources