如何在另一Angular应用中调用已定义的自定义HTML元素
Hey Mohan, let's figure out why those custom-button, custom-checkbox, and custom-table elements aren't working when you just drop the JS file into your second app's index.html. The core issue is that Angular components need to be explicitly converted into Web Components (custom elements) before they can be used across apps, and your target app needs a small configuration to accept them. Here's how to fix this:
第一步:将源Angular项目的组件打包为可复用的Web Components
First, your original app needs to properly export these components as standard custom elements using Angular's @angular/elements package:
Install the required package in your source project:
npm install @angular/elements --saveModify your source app's
AppModuleto convert components into custom elements. If you're using standalone components, you can adjust this logic accordingly:import { NgModule, Injector } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { createCustomElement } from '@angular/elements'; // Import your custom components import { CustomButtonComponent } from './custom-button/custom-button.component'; import { CustomCheckboxComponent } from './custom-checkbox/custom-checkbox.component'; import { CustomTableComponent } from './custom-table/custom-table.component'; @NgModule({ declarations: [ CustomButtonComponent, CustomCheckboxComponent, CustomTableComponent ], imports: [BrowserModule], // For older Angular versions, include components here (not needed for v14+) entryComponents: [ CustomButtonComponent, CustomCheckboxComponent, CustomTableComponent ] }) export class AppModule { constructor(private injector: Injector) { // Register each component as a custom element const buttonElement = createCustomElement(CustomButtonComponent, { injector }); customElements.define('custom-button', buttonElement); const checkboxElement = createCustomElement(CustomCheckboxComponent, { injector }); customElements.define('custom-checkbox', checkboxElement); const tableElement = createCustomElement(CustomTableComponent, { injector }); customElements.define('custom-table', tableElement); } // Skip Angular's default bootstrap since we're only exporting custom elements ngDoBootstrap() {} }Build the source project into a standalone bundle. Update your
angular.jsonto output a single JS file (simpler for reuse):"architect": { "build": { "builder": "@angular-devkit/build-angular:browser", "options": { "outputPath": "dist/custom-elements", "singleBundle": true, // Outputs one combined JS file (Angular 15+) "tsConfig": "tsconfig.app.json", // Keep other existing configs } } }Run
ng buildto generate the bundle indist/custom-elements.
第二步:在目标Angular应用中配置并使用自定义元素
Now, set up your target app to load and recognize these custom elements:
Copy the bundled JS file from your source project's
distfolder into your target app'sassetsdirectory (e.g.,assets/custom-elements/).Load the JS file in your target app's
index.html. Use thedeferattribute to ensure it loads before Angular initializes:<script src="assets/custom-elements/main.js" defer></script>Critical: Tell Angular to allow unknown custom elements. Add
CUSTOM_ELEMENTS_SCHEMAto your target app'sAppModule:import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from './app.component'; @NgModule({ declarations: [AppComponent], imports: [BrowserModule], providers: [], bootstrap: [AppComponent], schemas: [CUSTOM_ELEMENTS_SCHEMA] // Allows usage of custom HTML elements }) export class AppModule { }Now you can use the custom elements in your target app's templates just like regular HTML elements:
<!-- Example usage in app.component.html --> <custom-button label="Submit Form"></custom-button> <custom-checkbox checked="true" label="Remember Me"></custom-checkbox> <custom-table [data]="userData"></custom-table>Note: Use Angular's binding syntax (
[]for properties,()for events) just like you would with regular Angular components.
常见问题排查
If things still aren't working, check these common pitfalls:
- Verify the bundled JS file from your source project includes
customElements.definecalls (open the file in a text editor to confirm). - Check your target app's Network tab in dev tools to ensure the JS file is loading correctly (no 404 errors).
- Ensure your source and target Angular versions are compatible (major version mismatches can cause issues).
- If your custom elements depend on Angular modules (like
FormsModule), make sure those dependencies are either bundled with the custom element or imported in your target app's module.
内容的提问来源于stack exchange,提问作者Mohan

