@trimble-oss/modus-mcp-server
Version:
An MCP server providing information about Modus React form and UI components
336 lines (263 loc) • 9.11 kB
Markdown
# Angular Framework Integration with Modus Web Components 2.0
This guide will help you get started with consuming the Modus Angular Web Component library in your Angular project.
## Introduction
We highly recommend using the Modus Angular Components library for Angular-based projects.
These components are automatically generated using the Stencil Angular Framework Integration.
Follow the steps outlined below to integrate and use Modus Angular Web Components effectively.
## Setup for Angular with Modules
Modus Angular Components have a peer dependency with Modus Web Components and require the
installation of both packages.
### 1. Install Required Packages
Ensure that you specify the target version of Angular for the `modus-wc-angular` package (e.g., `ng18` for Angular 18).
<b>
Lock the installed package versions to avoid unintended breakages on future
npm installs.
</b>
```bash
npm install -oss/moduswebcomponents @trimble-oss/moduswebcomponents-angular@<latest-version>-ng<target-version>
```
### 2. Set up the Styling
Import Modus styles in your main JavaScript or CSS file:
```js
import '@trimble-oss/moduswebcomponents/modus-wc-styles.css';
```
### 3. Import the Component Library
Add the Modus Angular Web Components library to your Angular app's module:
```ts
// app.module.ts
import { ModusAngularComponentsModule } from '@trimble-oss/moduswebcomponents-angular';
({
...
imports: [ModusAngularComponentsModule],
...
})
export class AppModule {}
```
### 4. Configure Custom Elements Schema
In the `app.module.ts` file, you need to tell Angular that you are using custom element schemas
so that it does not throw errors when unknown element names are used in the markup:
```ts
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
({
...
schemas: [CUSTOM_ELEMENTS_SCHEMA]
...
})
```
### 5. Use the Components
Use Modus Angular Web Components while leveraging Angular template binding syntax:
```html
<!-- app.component.html -->
<modus-wc-button label="Click Me"></modus-wc-button>
```
## Setup for Angular with Standalone Components
### 1. Install Required Packages
Same as with modules:
```bash
npm install -oss/moduswebcomponents @trimble-oss/moduswebcomponents-angular@<latest-version>-ng<target-version>
```
### 2. Set up the Styling
```js
import '@trimble-oss/moduswebcomponents/modus-wc-styles.css';
```
### 3. Import into Standalone Component
You must distribute your components through a primary `NgModule` to use your components in a standalone component:
```ts
// app.component.ts
import { Component } from '@angular/core';
import { ModusAngularComponentsModule } from '@trimble-oss/moduswebcomponents-angular';
({
selector: 'app-root',
standalone: true,
imports: [ModusAngularComponentsModule],
templateUrl: './app.component.html',
})
export class AppComponent {}
```
### 4. Use the Components
```html
<!-- app.component.html -->
<modus-wc-button label="Click Me"></modus-wc-button>
```
## Best Practice: Wrapping Components
When using Modus Web Components directly, it is recommended to wrap it in corresponding Angular components within your application. This will abstract away from the library dependency, allowing more flexibility for you and your application in the future.
Notice Angular allows `[]` and `()` markup syntax for the web component's inputs and outputs, respectively.
### Wrapped Button Example:
```ts
import { Component, EventEmitter, Input, Output } from '@angular/core';
({
selector: 'button-component',
template: `
<modus-wc-button
[buttonStyle]="buttonStyle"
[color]="color"
[disabled]="disabled"
[size]="size"
(buttonClick)="onButtonClick.emit()"
>
<ng-content></ng-content>
</modus-wc-button>
`,
})
export class ButtonComponent {
() buttonStyle: 'borderless' | 'fill' | 'outline' = 'fill';
() color: 'danger' | 'default' | 'primary' | 'secondary' | 'warning' =
'default';
() disabled: boolean;
() size: 'small' | 'medium' | 'large' = 'medium';
() onButtonClick = new EventEmitter();
}
```
## Reactive Forms Integration
Working with web component inputs/outputs works great, but these components do not integrate with Angular's reactive forms as easily. Since web components don't know about Angular's form APIs, we must extend form-compatible components' behavior with directives.
### Component Wrapper Example
```ts
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { FormControl } from '@angular/forms';
({
selector: 'select-component',
template: `
<modus-wc-select
#select
[disabled]="disabled"
[errorText]="errorText"
[formControl]="formControl"
[helperText]="helperText"
[label]="label"
[options]="options"
[optionsDisplayProp]="optionsDisplayProp"
[required]="required"
[selectValue]="value"
[size]="size"
[validText]="validText"
(valueChange)="onSelectValueChange.emit(select.value)"
>
</modus-wc-select>
`,
})
export class SelectComponent {
() disabled: boolean;
() errorText: string;
() formControl: FormControl;
() helperText: string;
() label: string;
() options: unknown[] = [];
() optionsDisplayProp: string;
() required: boolean;
() size: 'medium' | 'large' = 'medium';
() validText: string;
() value: unknown;
() onSelectValueChange = new EventEmitter<unknown>();
}
```
### Directive Implementation
The directive makes the web component work with Angular's form controls:
```ts
import {
Directive,
forwardRef,
ElementRef,
HostListener,
Input,
OnInit,
Output,
EventEmitter,
} from '/core';
import {
ControlValueAccessor,
FormControl,
NG_VALUE_ACCESSOR,
} from '/forms';
({
selector: 'modus-wc-select',
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => ModusSelectDirective),
multi: true,
},
],
})
export class ModusSelectDirective implements ControlValueAccessor, OnInit {
() disabled: boolean;
() errorText: string;
() formControl: FormControl;
() helperText: string;
() label: string;
() options: unknown[];
() optionsDisplayProp: string;
() required: boolean;
() selectValue: unknown;
() size: 'medium' | 'large';
() validText: string;
() valueChange = new EventEmitter<string>();
onChange: any = () => {};
onTouched: any = () => {};
private _value: string;
get value() {
return this._value;
}
set value(value) {
if (value !== this._value) {
this._value = value;
this.onChange(this._value);
this.onTouched();
this.elementRef.nativeElement.value = value;
}
}
constructor(private elementRef: ElementRef) {}
ngOnInit(): void {
const modusSelect = this.elementRef.nativeElement as HTMLModusSelectElement;
modusSelect.disabled = this.disabled;
modusSelect.errorText = this.errorText;
modusSelect.helperText = this.helperText;
modusSelect.label = this.label;
modusSelect.options = this.options;
modusSelect.optionsDisplayProp = this.optionsDisplayProp;
modusSelect.required = this.required;
modusSelect.size = this.size;
modusSelect.validText = this.validText;
modusSelect.value = this.selectValue;
if (!this.formControl) {
this.formControl = new FormControl(null);
}
}
('valueChange', ['$event.detail'])
listenForValueChange(value: string): void {
this.value = value;
}
registerOnChange(fn: Function): void {
this.onChange = fn;
}
registerOnTouched(fn: Function): void {
this.onTouched = fn;
}
setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled;
}
writeValue(value: string): void {
if (value) {
this.value = value;
}
}
}
```
### Using the Form-enabled Component
```html
<select-component
[formControl]="$any(form).controls['select1']"
[label]="'Select Form Demo'"
[options]="options"
[optionsDisplayProp]="'display'">
</select-component>
```
## Key Points for Angular Integration
1. **Custom Elements Schema**: Always include `CUSTOM_ELEMENTS_SCHEMA` in your NgModule to avoid template errors
2. **Angular Syntax**: Use Angular binding syntax (`[property]` for inputs, `(event)` for outputs)
3. **Reactive Forms**: Create directives implementing `ControlValueAccessor` for form integration
4. **Component Wrapping**: Abstract library dependencies through wrapper components
5. **Event Handling**: Use Angular's `` to handle custom events from web components
## Additional Resources
For more information on using Modus Web Components with Angular, refer to:
- [Modus Web Components Documentation](https://modus-web-components.trimble.com/)
- [Stencil.js Angular Integration Documentation](https://stenciljs.com/docs/angular)