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?
The Http Client needs to provided on application level. In your case, in the providers of createApplication()
:
createApplication({
providers: [provideHttpClient()],
})