Angular Library with PrimeNg throwing Error ('firstCreatePass')

283 views Asked by At

For the current project I am working on integrating an Angular application with a custom UI (Angular library), that is based on PrimeNg.

I am utilizing PrimeNg as usual like this:

// mac-login.html
<p-panel header="Login">
  <form (ngSubmit)="onSubmit()">
    <div class="p-field">
      <label for="username">Username</label>
      <input pInputText [(ngModel)]="username" id="username" name="username" required />
    </div>
    <div class="p-field">
      <label for="password">Password</label>
      <p-password [(ngModel)]="password" id="password" name="password" required />
    </div>
    <div class="p-field">
      <p-button type="submit" label="Login"></p-button>
    </div>
  </form>
</p-panel>

And here:

import { CommonModule } from '@angular/common';
import { Component, EventEmitter, Input, NgModule, Output } from '@angular/core';
import { PanelModule } from 'primeng/panel';
import { PasswordModule } from 'primeng/password';
import { InputTextModule } from 'primeng/inputtext';
import { ButtonModule } from 'primeng/button';
import { FormsModule } from '@angular/forms';

@Component({
  selector: 'mac-login',
  templateUrl: './mac-login.html',
  styleUrls: ['./mac-login.scss']
})
export class macLogin {
  @Input() username: string = '';
  @Input() password: string = '';

  @Output() submitForm: EventEmitter<{ username: string; password: string }> = new EventEmitter();

  onSubmit(): void {
    if (this.username && this.password) {
      this.submitForm.emit({ username: this.username, password: this.password });
    }
  }
}

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    PanelModule,
    InputTextModule,
    PasswordModule,
    ButtonModule
  ],
  exports: [ macLogin ],
  declarations: [ macLogin ]
})
export class macLoginModule {}

When I am trying to use the component within my main app like this:

<mac-login
    [username]="user.email"
    [password]="user.password"
    (submitForm)="signIn()"
  ></mac-login>

And here:

import { Component } from '@angular/core';
import { Router } from '@angular/router';

import { IUser, AuthService } from '../../services/auth/cognito.service';

@Component({
  selector: 'app-sign-in',
  templateUrl: './sign-in.page.html',
  styleUrls: ['./sign-in.page.scss'],
})
export class SignInPage {

  loading: boolean;
  user: IUser;

  constructor(private router: Router,
              private authService: AuthService) {
    this.loading = false;
    this.user = {
      email: '',
      password: ''
    } as IUser;
  }

  public signIn(): void {
    this.loading = true;
    this.authService.signIn(this.user)
    .then(() => {
      this.router.navigate(['/profile']);
    }).catch(() => {
      this.loading = false;
    });
  }

}

I get the following error message:

main.ts:6 ERROR Error: Uncaught (in promise): TypeError: Cannot read properties of null (reading 'firstCreatePass')
TypeError: Cannot read properties of null (reading 'firstCreatePass')
    at providersResolver (core.mjs:22359:15)
    at definition.providersResolver (core.mjs:22620:24)
    at initializeDirectives (core.mjs:11935:17)
    at resolveDirectives (core.mjs:11909:13)
    at elementStartFirstCreatePass (core.mjs:15677:5)
    at ɵɵelementStart (core.mjs:15713:9)
    at macLogin_Template (mac-login.html:1:1)
    at executeTemplate (core.mjs:11409:17)
    at renderView (core.mjs:12608:13)
    at renderComponent (core.mjs:12555:5)
    at resolvePromise (zone.js:1193:31)
    at resolvePromise (zone.js:1147:17)
    at zone.js:1260:17
    at _ZoneDelegate.invokeTask (zone.js:402:31)
    at core.mjs:27127:55
    at AsyncStackTaggingZoneSpec.onInvokeTask (core.mjs:27127:36)
    at _ZoneDelegate.invokeTask (zone.js:401:60)
    at Object.onInvokeTask (core.mjs:27437:33)
    at _ZoneDelegate.invokeTask (zone.js:401:60)
    at Zone.runTask (zone.js:171:47)

I have correctly imported the library in app.module.ts

The whole ui-libary is propagated through pnpm workspaces.

Is there any way to solve this? THanks in advance.

1

There are 1 answers

0
André Kirchner On

Okay, I have been reading in forums and through posts countless hours, just to finally find the answer, that has not been so obvious.

When working with pnpm workspaces with multiple Angular projects, there is an issue with package management, where Angular Ivy is provided in multiple instances, so that e.g. the library's Ivy does not exactly match the app's Ivy (from node_modules) - causing an Ivy madness within the app.

In order to avoid this, we need to make sure, that the app and the connected library are using @angular from node_modules only!

And it is really easy to set up. Add the following to your app's tsconfig.json:

{
  ...,
  compilerOptions: {
    ...,
    "paths": {
      "@angular/*": [
        "./node_modules/@angular/*"
      ]
    }
  }
}

And that's it. Working like a charm in Angular 16.2.0.