Writing a component¶
Copy of
sumaris-app/.agents/rules/component.md(rule written for AI coding agents, when creating new UI component). Do not edit here: runnpm run site:sync-rulesto update it.
-
For each Angular component:
- Use a separate file for the HTML template;
- Use the Ionic framework, and (if necessary) Angular Material;
- Ionic is used with its standalone build (
provideIonicAngular()), never the lazyIonicModule:- Import Ionic components through
AppIonicModule(@app/shared/ionic.module) - already exported byAppSharedModule; - Any new
<ion-*>tag MUST be added toAPP_IONIC_COMPONENTS(src/app/shared/ionic.module.ts), otherwise the element stays inert (not detected at compile time); - Import controllers and types (
ModalController,AlertController,IonContent...) from@ionic/angular/standalone, never from@ionic/angular; - An
<ion-icon>with a static name must be registered inAPP_ICONS(src/app/app.icons.ts);
- Import Ionic components through
- Use the
Momentclass for dates; - Use RxState with providers:
[RxState]in the@Componentdeclaration; - Right above each component class, declare an interface MyComponentState:
- Replace "MyComponent" with the name of the component;
- Add the component's dynamic attributes to this interface;
- Within the constructor:
- Limit the parameters facilitate inheritance: by using
inject()function (on each attribute declaration) or by using theinjector: Injectorin the constructor; - Define all parameters with
protectedvisibility; - Add a parameter state:
RxState<MyComponentState>.
- Limit the parameters facilitate inheritance: by using
- For each dynamic attribute of the component:
- Define the attribute with its basic type in the MyComponentState class;
- In the component, define a getter and a setter with `@Input; that uses state:
- Use the decorator
@RxStateProperty() attribute: anyType- will generate a state's property getter/setter :get attribute(): anyType { return this.state.get('attribute'); } @Input() set attribute(value: anyType) { this.state.set('attribute', () => value); } - Is to observed a state's property, use the decorator
@RxStateSelect() attribute$: Observable<anyType>- that is similar to:attribute$ = this.state.select('attribute');
- Use the decorator
- For modals (if needed):
- Use IonicModal.
- Do not define the modal in the HTML template (inline) but in a separate component.
- Manage the modal from the calling component via ModalController.
-
For any generated code (by GPT or otherwise):
- Add a comment line at the beginning of the class indicating that the code is under a free license (GPL version 3), but do not write out the full license.
-
Use the
ngx-translatelibrary for labels:- Import the standalone
TranslatePipefrom@ngx-translate/core(in the component's ownimportsarray, or the declaring NgModule'simports) —TranslateModule/TranslateModule.forChild()is no longer used in this codebase. - Add an i18n key prefix "MY_COMPONENT." before each i18n key.
- In the template, translate each label by indicating the i18n key followed by the
translatepipe. - Define the translation for each key in a
en.jsontranslation file.
- Import the standalone