1

I am trying to build a simple library in Angular (version 18) that can be used in my application and Angular Elements component.

The idea is simple in both the application and element: Get the same objects and data through the library. But all it did was give me headaches.

When I create the library I just have one service and some objects. The service get's the HttpClient injected and methods retrieve information from an API.

The service is injected in the elements component and that works. THe main.ts is set-up and nothing has errors. When I run the elements I always get this error:

ncaught RuntimeError: NG0203: inject() must be called from an injection context such as a constructor, a factory function, a field initializer, or a function used with runInInjectionContext. Find more at https://angular.dev/errors/NG0203

Here is the code, starting with the library:

The service:

@Injectable({ providedIn: 'root' })
export class SurveyService  {

    constructor(private client: HttpClient) {
       
    }

    getSurvey(id: string): Observable<any> {
        throw new Error("Method not implemented.");
    }
}

Yes, it has one method that doesn't do anything. I want to figure it out without to much code.

public-api.ts

export * from './lib/survey-service.ts';

Now the application. Remember that this is Angular Elements!

main.ts

createApplication({
  providers: [
    SurveyService
  ],
})
  .then((app) => {
    const surveyComponent = createCustomElement(SurveyComponent , { injector: app.injector });
    customElements.define('survey', surveyComponent );
  })
  .catch((err) => console.error(err));

survey.component.ts

@Component({
  selector: 'app-survey',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './survey.component.html',
  styleUrl: './survey.component.scss'
})
export class SurveyComponent {

  constructor(surveyService: SurveyService  ) {
    surveyService.getSurvey("").subscribe((x: any)=>{
      console.log(x);
    })
  }
}

This gives the error I showed before. When I remove the private client: HttpClient from the SurveyService I get no errors, so I think the problem is with the HttpClient.

What I did find was a lot of HttpClientModule, but I get that it's deprecated and I should use the provideHttpClient(). In the library, I created a module, added provideHttpClient() as a provider together with the service. Then, in the main.ts of the elements application provide the module instead of the service: Same result, same error.

The module:

@NgModule({
  imports: [
    CommonModule,    
  ],
  providers: [
    provideHttpClient(),
    SurveyService, // Provide the QuestionsService
  ],
  exports: [
    // Any components or services to export
  ],
})
export class SurveyServiceModule { }

Other things just didn't work: Add the provideHttpClient() in the elements application... Where? It's nowhere accepted!

I have added the preserveSymLinks to my angular.json, as suggested, and now I see this error:

zone.js:125 Uncaught NullInjectorError: R3InjectorError[SurveyService -> SurveyService -> HttpClient -> HttpClient]: NullInjectorError: No provider for HttpClient!

I have been working front and back to fix this, but I am really stuck. What am I doing wrong?

5
  • Could you share a github repo where the issue happens, the problem is in how you are using the module and application together, you should use symLinks to link the application and library Commented Oct 3, 2024 at 18:13
  • I don't have it on GitHub, since it's a POC. I could upload it tomorrow. I will also look into symlinks Commented Oct 3, 2024 at 18:15
  • @NarenMurali I quickly tried the symLinks, see the edit of the post (at the bottom) Commented Oct 3, 2024 at 18:24
  • Have you tried providing the http client when creating the application? createApplication({ providers: [provideHttpClient()] }) Commented Oct 3, 2024 at 18:25
  • @JSONDerulo... I feel stupid... Of all the places I tried to add the provideHtpClient... I missed that one Commented Oct 3, 2024 at 18:26

2 Answers 2

3

The Http Client needs to provided on application level. In your case, in the providers of createApplication():

createApplication({
  providers: [provideHttpClient()],
})
Sign up to request clarification or add additional context in comments.

1 Comment

Hi @JSON Derulo can you please look into this stackoverflow.com/questions/79323580/…
1

The error "RuntimeError: NG0203: inject() must be called from an injection context such as a constructor, a factory function, a field initializer, or a function used with runInInjectionContext." is due to improper linking of the angular library and angular application. You should use preserveSymlinks: true to solve this problem.

Create an Angular 14 Library, use it locally when developing and publish the package to npm


You should add provideHttpClient to the providers array of createApplication.

createApplication({
  providers: [
    SurveyService,
    provideHttpClient(), // <- changed here!
  ],
})
  .then((app) => {
    const surveyComponent = createCustomElement(SurveyComponent , { injector: app.injector });
    customElements.define('survey', surveyComponent );
  })
  .catch((err) => console.error(err));

1 Comment

Hi @Naren Mural can you please look into this stackoverflow.com/questions/79323580/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.