Skip to content

Commit

Permalink
feat: update forms doc
Browse files Browse the repository at this point in the history
  • Loading branch information
sdo-1A committed Apr 30, 2024
1 parent bbae039 commit 33973dd
Show file tree
Hide file tree
Showing 44 changed files with 1,668 additions and 975 deletions.
1 change: 1 addition & 0 deletions apps/showcase/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const appRoutes: Routes = [
{path: 'run-app-locally', loadComponent: () => import('./run-app-locally/index').then((m) => m.RunAppLocallyComponent), title: 'Otter Showcase - Run App Locally'},
{path: 'sdk', loadComponent: () => import('./sdk/index').then((m) => m.SdkComponent), title: 'Otter Showcase - SDK'},
{path: 'placeholder', loadComponent: () => import('./placeholder/index').then((m) => m.PlaceholderComponent), title: 'Otter Showcase - Placeholder'},
{path: 'forms', loadComponent: () => import('./forms/index').then((m) => m.FormsComponent), title: 'Otter Showcase - Forms'},
{path: '**', redirectTo: '/home', pathMatch: 'full'}
];

Expand Down
3 changes: 2 additions & 1 deletion apps/showcase/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ export class AppComponent implements OnDestroy {
{ url: '/dynamic-content', label: 'Dynamic content' },
{ url: '/component-replacement', label: 'Component replacement' },
{ url: '/rules-engine', label: 'Rules engine' },
{ url: '/placeholder', label: 'Placeholder' }
{ url: '/placeholder', label: 'Placeholder' },
{ url: '/forms', label: 'Forms' }
]
},
{
Expand Down
5 changes: 5 additions & 0 deletions apps/showcase/src/app/forms/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Forms

A showcase page that demonstrates how to use the otter forms feature inside an application.

The page contains both a step by step explanation to guide the users as well as a sample component that can be used as a reference and that illustrates the capabilities of the feature.
33 changes: 33 additions & 0 deletions apps/showcase/src/app/forms/forms.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { AsyncPipe } from '@angular/common';
import { AfterViewInit, ChangeDetectionStrategy, Component, QueryList, ViewChildren, ViewEncapsulation } from '@angular/core';
import { RouterModule } from '@angular/router';
import { O3rComponent } from '@o3r/core';
import { CopyTextPresComponent, FormsPresComponent, IN_PAGE_NAV_PRES_DIRECTIVES, InPageNavLink, InPageNavLinkDirective, InPageNavPresService } from '../../components/index';

@O3rComponent({ componentType: 'Page' })
@Component({
selector: 'o3r-forms',
standalone: true,
imports: [
RouterModule,
FormsPresComponent,
CopyTextPresComponent,
IN_PAGE_NAV_PRES_DIRECTIVES,
AsyncPipe
],
templateUrl: './forms.template.html',
styleUrl: './forms.style.scss',
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class FormsComponent implements AfterViewInit {
@ViewChildren(InPageNavLinkDirective)
private readonly inPageNavLinkDirectives!: QueryList<InPageNavLink>;
public links$ = this.inPageNavPresService.links$;

constructor(private readonly inPageNavPresService: InPageNavPresService) {}

public ngAfterViewInit() {
this.inPageNavPresService.initialize(this.inPageNavLinkDirectives);
}
}
23 changes: 23 additions & 0 deletions apps/showcase/src/app/forms/forms.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { FormsComponent } from './forms.component';

describe('FormsComponent', () => {
let component: FormsComponent;
let fixture: ComponentFixture<FormsComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [FormsComponent]
})
.compileComponents();

fixture = TestBed.createComponent(FormsComponent);

Check failure on line 15 in apps/showcase/src/app/forms/forms.spec.ts

View workflow job for this annotation

GitHub Actions / checks / test (ubuntu-latest)

FormsComponent › should create

NullInjectorError: R3InjectorError(DynamicTestModule)[InjectionToken LocaleId -> LocalizationService -> LocalizationService]: NullInjectorError: No provider for LocalizationService! at NullInjector.get (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:1654:27) at R3Injector.get (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:3093:33) at R3Injector.get (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:3093:33) at injectInjectorOnly (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:1100:40) at ɵɵinject (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:1106:42) at injectArgs (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:1237:23) at Object.factory (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:3322:52) at ../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:3219:47 at runInInjectorProfilerContext (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:866:9) at R3Injector.hydrate (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:3218:21) at R3Injector.get (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:3082:33) at TestBedCompiler.finalize (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/testing.mjs:1015:54) at _TestBedImpl.get testModuleRef [as testModuleRef] (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/testing.mjs:2010:49) at _TestBedImpl.inject (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/testing.mjs:1914:29) at _TestBedImpl.createComponent (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/testing.mjs:1966:44) at Function.createComponent (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/testing.mjs:1783:37) at src/app/forms/forms.spec.ts:15:23

Check failure on line 15 in apps/showcase/src/app/forms/forms.spec.ts

View workflow job for this annotation

GitHub Actions / checks / test (windows-latest)

FormsComponent › should create

NullInjectorError: R3InjectorError(DynamicTestModule)[InjectionToken LocaleId -> LocalizationService -> LocalizationService]: NullInjectorError: No provider for LocalizationService! at NullInjector.get (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:1654:27) at R3Injector.get (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:3093:33) at R3Injector.get (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:3093:33) at injectInjectorOnly (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:1100:40) at ɵɵinject (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:1106:42) at injectArgs (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:1237:23) at Object.factory (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:3322:52) at ../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:3219:47 at runInInjectorProfilerContext (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:866:9) at R3Injector.hydrate (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:3218:21) at R3Injector.get (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:3082:33) at TestBedCompiler.finalize (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/testing.mjs:1015:54) at _TestBedImpl.get testModuleRef [as testModuleRef] (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/testing.mjs:2010:49) at _TestBedImpl.inject (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/testing.mjs:1914:29) at _TestBedImpl.createComponent (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/testing.mjs:1966:44) at Function.createComponent (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/testing.mjs:1783:37) at src/app/forms/forms.spec.ts:15:23
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
3 changes: 3 additions & 0 deletions apps/showcase/src/app/forms/forms.style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
o3r-forms {

}
51 changes: 51 additions & 0 deletions apps/showcase/src/app/forms/forms.template.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<h1>Forms</h1>
<div class="row">
<div class="right-nav order-1 order-lg-2 col-12 col-lg-2 sticky-lg-top pt-5 pt-lg-0">
<o3r-in-page-nav-pres
id="forms-nav"
[links]="links$ | async"
>
</o3r-in-page-nav-pres>
</div>
<div class="order-2 order-lg-1 col-12 col-lg-10">
<h2 id="forms-description">Description</h2>
<div>
<p>This module provides utilities to enhance the build of Angular reactive forms for specific use cases, including:</p>
<ul>
<li>A container/presenter structure for components</li>
<li>Handling form submission at page (or parent component) level</li>
<li>Displaying the error message outside the form</li>
</ul>
</div>

<h2 id="forms-example">Example</h2>
<div>
<p>
In the following example, we have a parent component with two subcomponents, each containing a form.
</p>
<p>
The first form requires the user to define their personal information (name and date of birth).
The second form requires the definition of the user's emergency contact information (name, phone number, and email address).
Both forms contain validators, such as certain fields being required or specific values having to follow a certain pattern.
</p>
<p>
The submit of both forms is triggered at parent component level.
</p>
<o3r-forms-pres></o3r-forms-pres>
<p>
Do not hesitate to run the application locally, if not installed yet, follow the <a routerLink="/run-app-locally">instructions</a>.
</p>
<a href="https://github.com/AmadeusITGroup/otter/blob/main/apps/showcase/src/components/showcase/localization" target="_blank" rel="noopener">Source code</a>
</div>
<h2 id="forms-install">How to install</h2>
<o3r-copy-text-pres [wrap]="true" language="bash" text="ng add @o3r/forms"></o3r-copy-text-pres>
<h2 id="forms-references">References</h2>
<div>
<ul>
<li>
<a href="https://github.com/AmadeusITGroup/otter/blob/main/packages/%40o3r/forms/README.md" target="_blank" rel="noopener">Documentation</a>
</li>
</ul>
</div>
</div>
</div>
2 changes: 2 additions & 0 deletions apps/showcase/src/app/forms/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './forms.component';

3 changes: 3 additions & 0 deletions apps/showcase/src/components/showcase/forms/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# FormsPres

Showcase of an Otter component with forms
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/** Model used to create Personal Info form */
export interface PersonalInfo {
/** Name */
name: string;
/** Date of birth */
dateOfBirth: string;
}

/** Model used to create Emergency Contact form */
export interface EmergencyContact {
/** Emergency contact name */
name: string;
/** Emergency contact phone number */
phone: string;
/** Emergency contact email address */
email: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './form-models';
138 changes: 138 additions & 0 deletions apps/showcase/src/components/showcase/forms/forms-pres.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import { AsyncPipe, CommonModule, formatDate } from '@angular/common';
import { ChangeDetectionStrategy, Component, Input, type OnDestroy, type OnInit, ViewEncapsulation } from '@angular/core';
import { ReactiveFormsModule, UntypedFormControl } from '@angular/forms';
import { O3rComponent } from '@o3r/core';
import { Localization } from '@o3r/localization';
import { CustomFormValidation } from '@o3r/forms';
import { Observable, Subject, Subscription } from 'rxjs';
import { FormsEmergencyContactPresComponent, FormsPersonalInfoPresComponent } from '../../utilities';
import { EmergencyContact, PersonalInfo } from './contracts';
import { FormsPresTranslation, translations } from './forms-pres.translation';
import { dateCustomValidator, formsPresValidatorGlobal } from './forms-pres.validators';

@O3rComponent({ componentType: 'Component' })
@Component({
selector: 'o3r-forms-pres',
standalone: true,
imports: [
AsyncPipe,
CommonModule,
FormsEmergencyContactPresComponent,
FormsPersonalInfoPresComponent,
ReactiveFormsModule
],
templateUrl: './forms-pres.template.html',
styleUrl: './forms-pres.style.scss',
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush
})
export class FormsPresComponent implements OnInit, OnDestroy {

/** Localization of the component */
@Input()
@Localization('./forms-pres.localization.json')
public translations: FormsPresTranslation;

/** Observable used to notify the component that a submit has been fired from the page */
public submitTrigger$: Observable<boolean>;

/** Observable to be passed to the form */
public submitForm$: Subject<boolean> = new Subject();

private readonly subscription = new Subscription();

/** The personal info form object model */
public personalInfo: PersonalInfo;
/** The emergency contact form object model */
public emergencyContact: EmergencyContact;

/** Form validators for personal info */
public personalInfoValidators: CustomFormValidation<PersonalInfo>;
/** Form validators for emergency contact */
public emergencyContactValidators: CustomFormValidation<EmergencyContact>;

/** The form control object bind to the personal info component */
public personalInfoFormControl: UntypedFormControl;
/** The form control object bind to the emergency contact component */
public emergencyContactFormControl: UntypedFormControl;

public firstSubmit = true;
private readonly forbiddenName = 'Test';

constructor() {
this.submitTrigger$ = this.submitForm$.asObservable();
this.translations = translations;
this.personalInfo = { name: '', dateOfBirth: this.formatDate(Date.now()) };
this.personalInfoFormControl = new UntypedFormControl(this.personalInfo);
this.emergencyContact = { name: '', phone: '', email: '' };
this.emergencyContactFormControl = new UntypedFormControl(this.emergencyContact);
this.personalInfoValidators = {
global: formsPresValidatorGlobal(this.forbiddenName, translations.globalForbiddenName, translations.globalForbiddenNameLong, { name: this.forbiddenName }),
fields: {
dateOfBirth: dateCustomValidator(translations.dateInThePast)
}
};
this.emergencyContactValidators = {
global: formsPresValidatorGlobal(this.forbiddenName, translations.globalForbiddenName, translations.globalForbiddenNameLong, { name: this.forbiddenName })
};
}

private formatDate(dateTime: number) {
return formatDate(dateTime, 'yyyy-MM-dd', 'en-GB');
}

public ngOnInit() {
this.subscription.add(this.submitTrigger$.subscribe((_value) => this.submitAction()));
}

public ngOnDestroy() {
this.subscription.unsubscribe();
}

public submitForm() {
this.submitForm$.next(true);
}

/** This will store the function to make the personal info form as dirty and touched */
public _markPersonalInfoInteraction: () => void = () => {};
/** This will store the function to make the emergency contact form as dirty and touched */
public _markEmergencyContactInteraction: () => void = () => {};

/**
* Register the function to be called to mark the personal info form as touched and dirty
*
* @param fn
*/
public registerPersonalInfoInteraction(fn: () => void) {
this._markPersonalInfoInteraction = fn;
}

/**
* Register the function to be called to mark the personal emergency contact form as touched and dirty
*
* @param fn
*/
public registerEmergencyContactInteraction(fn: () => void) {
this._markEmergencyContactInteraction = fn;
}

/** submit function */
public submitAction() {
if (this.submitTrigger$ && this.firstSubmit) {
this._markPersonalInfoInteraction();
this._markEmergencyContactInteraction();
this.firstSubmit = false;
}
const isValid = !this.personalInfoFormControl.errors && !this.emergencyContactFormControl.errors;
if (isValid) {
// eslint-disable-next-line no-console
console.log('FORMS COMPONENT: personal info form status', this.personalInfoFormControl.status);
// eslint-disable-next-line no-console
console.log('FORMS COMPONENT: emergency contact form status', this.emergencyContactFormControl.status);
// eslint-disable-next-line no-console
console.log('FORMS COMPONENT: submit logic here', this.personalInfoFormControl.value, this.emergencyContactFormControl.value);
}
// eslint-disable-next-line no-console
console.log('FORMS COMPONENT: submitted with value ', isValid);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"form.dateOfBirth.dateInThePast": {
"description": "Validator for date of birth",
"defaultValue": "Date of birth should be in the past"
},
"form.globalForbiddenName": {
"description": "This validator will check if the name will be the given config",
"defaultValue": "Name cannot be { name }"
},
"form.globalForbiddenName.long": {
"description": "This validator will check if the name will be the given config",
"defaultValue": "The value introduced for the name cannot be { name }"
}
}
23 changes: 23 additions & 0 deletions apps/showcase/src/components/showcase/forms/forms-pres.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { FormsPresComponent } from './forms-pres.component';

describe('FormsPresComponent', () => {
let component: FormsPresComponent;
let fixture: ComponentFixture<FormsPresComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [FormsPresComponent]
})
.compileComponents();

fixture = TestBed.createComponent(FormsPresComponent);

Check failure on line 15 in apps/showcase/src/components/showcase/forms/forms-pres.spec.ts

View workflow job for this annotation

GitHub Actions / checks / test (ubuntu-latest)

FormsPresComponent › should create

NullInjectorError: R3InjectorError(DynamicTestModule)[InjectionToken LocaleId -> LocalizationService -> LocalizationService]: NullInjectorError: No provider for LocalizationService! at NullInjector.get (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:1654:27) at R3Injector.get (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:3093:33) at R3Injector.get (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:3093:33) at injectInjectorOnly (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:1100:40) at ɵɵinject (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:1106:42) at injectArgs (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:1237:23) at Object.factory (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:3322:52) at ../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:3219:47 at runInInjectorProfilerContext (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:866:9) at R3Injector.hydrate (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:3218:21) at R3Injector.get (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:3082:33) at TestBedCompiler.finalize (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/testing.mjs:1015:54) at _TestBedImpl.get testModuleRef [as testModuleRef] (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/testing.mjs:2010:49) at _TestBedImpl.inject (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/testing.mjs:1914:29) at _TestBedImpl.createComponent (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/testing.mjs:1966:44) at Function.createComponent (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/testing.mjs:1783:37) at src/components/showcase/forms/forms-pres.spec.ts:15:23

Check failure on line 15 in apps/showcase/src/components/showcase/forms/forms-pres.spec.ts

View workflow job for this annotation

GitHub Actions / checks / test (windows-latest)

FormsPresComponent › should create

NullInjectorError: R3InjectorError(DynamicTestModule)[InjectionToken LocaleId -> LocalizationService -> LocalizationService]: NullInjectorError: No provider for LocalizationService! at NullInjector.get (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:1654:27) at R3Injector.get (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:3093:33) at R3Injector.get (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:3093:33) at injectInjectorOnly (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:1100:40) at ɵɵinject (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:1106:42) at injectArgs (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:1237:23) at Object.factory (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:3322:52) at ../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:3219:47 at runInInjectorProfilerContext (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:866:9) at R3Injector.hydrate (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:3218:21) at R3Injector.get (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/core.mjs:3082:33) at TestBedCompiler.finalize (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/testing.mjs:1015:54) at _TestBedImpl.get testModuleRef [as testModuleRef] (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/testing.mjs:2010:49) at _TestBedImpl.inject (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/testing.mjs:1914:29) at _TestBedImpl.createComponent (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/testing.mjs:1966:44) at Function.createComponent (../../.yarn/__virtual__/@angular-core-virtual-47665d5785/0/cache/@angular-core-npm-17.3.6-88f47cfe13-9479f8c0f3.zip/node_modules/@angular/core/fesm2022/testing.mjs:1783:37) at src/components/showcase/forms/forms-pres.spec.ts:15:23
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
o3r-forms-pres {
// Your component custom SCSS
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<div class="card my-3">
<div class="row g-0">
<div class="col-6 align-items-center justify-center">
<o3r-forms-personal-info-pres
[config]="{nameMaxLength: 5}"
[customValidators]="personalInfoValidators"
(registerInteraction)="registerPersonalInfoInteraction($event)"
[formControl]="personalInfoFormControl">
</o3r-forms-personal-info-pres>
</div>
<div class="col-6 align-items-center justify-center">
<o3r-forms-emergency-contact-pres
[customValidators]="emergencyContactValidators"
(registerInteraction)="registerEmergencyContactInteraction($event)"
[formControl]="emergencyContactFormControl">
</o3r-forms-emergency-contact-pres>
</div>
</div>
<div class="row m-auto pb-3">
<button type="button" class="btn btn-primary" id="btn-submit" (click)="submitForm()">Submit</button>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Translation } from '@o3r/core';

export interface FormsPresTranslation extends Translation {
dateInThePast: string;
globalForbiddenName: string;
globalForbiddenNameLong: string;
}

export const translations: FormsPresTranslation = {
dateInThePast: 'form.dateOfBirth.dateInThePast',
globalForbiddenName: 'form.globalForbiddenName',
globalForbiddenNameLong: 'form.globalForbiddenName.long'
};
Loading

0 comments on commit 33973dd

Please sign in to comment.