@stencil/angular-output-target
v1.5.0
Published
Angular output target for @stencil/core components.
Downloads
87,760
Keywords
Readme
@stencil/angular-output-target
Stencil can generate Angular component wrappers for your web components. This allows your Stencil components to be used within an Angular application. The benefits of using Stencil's component wrappers over the standard web components include:
- Angular component wrappers will be detached from change detection, preventing unnecessary repaints of your web component.
- Web component events will be converted to RxJS observables to align with Angular's @Output() and will not emit across component boundaries.
- Optionally, form control web components can be used as control value accessors with Angular's reactive forms or [ngModel].
For a detailed guide on how to add the angular output target to a project, visit: https://stenciljs.com/docs/angular.
Installation
npm install @stencil/angular-output-targetAngular Support
| @stencil/angular-output-target | Angular | |------------------------------------|-----------------| | 0.10.2 | v18.x and lower | | 1.0.0 | v19.x and above |
Usage
In your stencil.config.ts add the following configuration to the outputTargets section:
import { Config } from '@stencil/core';
import { angularOutputTarget } from '@stencil/angular-output-target';
export const config: Config = {
namespace: 'demo',
outputTargets: [
angularOutputTarget({
componentCorePackage: 'component-library',
directivesProxyFile: '../component-library-angular/src/directives/proxies.ts',
directivesArrayFile: '../component-library-angular/src/directives/index.ts',
}),
{
type: 'dist',
esmLoaderPath: '../loader',
},
],
};Config Options
| Property | Description |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| componentCorePackage | The NPM package name of your Stencil component library. This package is used as a dependency for your Angular wrappers. |
| directivesProxyFile | The output file of all the component wrappers generated by the output target. This file path should point to a location within your Angular library/project. |
| directivesArrayFile | The output file of a constant of all the generated component wrapper classes. Used for easily declaring and exporting the generated components from an NgModule. This file path should point to a location within your Angular library/project. |
| valueAccessorConfigs | The configuration object for how individual web components behave with Angular control value accessors. |
| excludeComponents | An array of tag names to exclude from generating component wrappers for. This is helpful when have a custom framework implementation of a specific component or need to extend the base component wrapper behavior. |
| outputType | Specifies the type of output to be generated. It can take one of the following values: 1. component: Generates all the component wrappers to be declared on an Angular module. This option is required for Stencil projects using the dist hydrated output. 2. scam: Generates a separate Angular module for each component. 3. standalone: Generates standalone component wrappers. Both scam and standalone options are compatible with the dist-custom-elements output. Note: Please choose the appropriate outputType based on your project's requirements and the desired output structure. Defaults to component. |
| customElementsDir | This is the directory where the custom elements are imported from when using the Custom Elements Bundle. Defaults to the components directory. Only applies for outputType: "scam" or outputType: "standalone". |
| inlineProperties | Experimental. When true, tries to inline the properties of components. This is required to enable Angular Language Service to type-check and show jsdocs when using the components in html-templates. |
| booleanAttributes | When true, boolean properties are declared with an Angular input transform so they can be set by attribute presence, e.g. <my-component disabled> instead of <my-component [disabled]="true">. Type-checking the attribute form also requires inlineProperties. Defaults to false. Refer to Boolean attributes. |
Boolean attributes
Angular resolves a bare attribute to the empty string, so a boolean property has to be bound explicitly by default:
<!-- Type 'string' is not assignable to type 'boolean' under strictTemplates -->
<my-component disabled></my-component>
<my-component [disabled]="true"></my-component>Setting booleanAttributes: true declares boolean properties with an Angular input transform,
which accepts the attribute form and coerces it:
<my-component disabled></my-component>
<my-component disabled="false"></my-component>
<my-component [disabled]="isDisabled"></my-component>The transform used is nullableBooleanAttribute rather than Angular's booleanAttribute. It
coerces strings identically, but passes null and undefined through instead of coercing them to
false. Components frequently treat those as a state distinct from false:
// `undefined` means "decide based on the mode", which is not the same as `false`
const showDetail = detail !== undefined ? detail : mode === 'ios';
// a strict comparison also behaves differently for `null` than it does for `false`
const showHandle = handle !== false;Both values reach inputs routinely, from the async pipe before its first emission and from form
control values, so coercing them would change the behavior of bindings that work today.
Type-checking requires inlineProperties
This option changes what the Angular compiler accepts, so it only has a visible effect where the
compiler type-checks the wrapper's inputs in the first place. That needs inlineProperties
enabled as well:
angularOutputTarget({
// ...
booleanAttributes: true,
inlineProperties: true,
});Without inlineProperties the generated wrappers declare no typed members for their inputs, so
Angular does not check these bindings at all and there is no TS2322 for the transform to
resolve.
The transform itself still runs either way. Angular applies it from the component definition's
input map, which does not depend on a declared class member, so enabling booleanAttributes on
its own moves boolean coercion from Stencil to the transform without the compiler checking what
you pass. The two agree on strings, booleans, null and undefined. If you bind a value outside
those, prefer enabling inlineProperties too so that ngAcceptInputType_* rejects it at compile
time rather than silently coercing it.
Note that inlineProperties is itself experimental, so enabling both is opting into that. With
booleanAttributes on its own you still get the attribute syntax at runtime, just without the
compiler checking it.
Limitations
A property is only transformed when Stencil reports its type as exactly boolean. Three kinds of
property fall outside that, and they behave differently from each other. In all three the property
receives the attribute's empty string rather than true, so bind them explicitly when you need a
boolean.
Virtual properties are not transformed and get no inlined class member either, so Angular has
nothing to check the binding against and skips it. A bare attribute compiles, and the property
receives ''. Nothing warns you.
Properties declared as any are not transformed, but they do get an inlined member typed
any, so '' is assignable. A bare attribute compiles, and the property receives ''. Nothing
warns you here either.
Properties whose type unions boolean with something else, such as boolean | 'auto', are
reported to the output target as any, so they get no transform, but their inlined member keeps
the real union type. This is the only case the compiler catches:
TS2322: Type '""' is not assignable to type 'boolean | "auto"'