The Problem
My html files warn that my custom components/pipes 'are not a known element'. However building and running the application works as intended, and the custom components/pipes are functional. The dichotomy of the components working but showing as errors is annoying and can be difficult to work with. I know this is a small thing, but I really want to not see errors in my html files when there are no errors.
Summary
I have two distinct angular projects; an angular library which I consume with my angular application. The library exports several custom components, pipes and services which the application uses. I do not have this library published via npm, instead I use npm-link to give the application access to the library. This seems to work as any service/component defined in my applications components work and doesn't complain. Though the moment I put anything in my template file from my library, that selector is underlined and a warning appears.
The files
/*Library Module*/
@NgModule({
declarations: [
ThemeToggleComponent,
// Other custom components/pipes
],
exports: [
ThemeToggleComponent,
// Other components needed in templates files
]
})
export class MyCommonModule {}
/*
* Public API Surface of my-common library
*/
export * from './lib/my-common.module';
/*
* Many other components, services, pipes, etc etc
*/
export * from './lib/theme-toggle/theme-toggle.component';
/* Consuming Application module */
import { MyCommonModule } from 'my-common';
@NgModule({
imports: [
MyCommonModule,
],
declarations: [
MyComponent,
],
})
export class MyModule {}
/* Template of MyComponent, my.component.html */
<div>
<my-theme-toggle (darkThemeSelected)="toggleTheme($event)"></my-theme-toggle>
</div>
The file above will have all lines which reference my custom components underlined in red with the error message 'my-theme-toggle' is not a known element: ...if it is, verify it is apart of the module.
Attempts to fix
I've tried a things, but to no avail
My hunches
I think this is an issue with the paths compiler option in tsconfig.json in the consuming application. Throughout all of my research this is the one thing that pops up more than anything else. I currently do not have a path set, because everything is working. My common library looks and acts like any other node_module library, other than this issue.
My other thought is that because everything works and runs, then the issue may be with vs-code not understanding the import, or something of that nature. Though I think this is unlikely.
The background
Both angular projects are on version 9, rc7. I use ng-packagr to build my library. I use visual studio code, and at the time of writing I am on the latest release.
EDIT This problem went away upon upgrading to angular 11, I think several of the other issues might solve it, but this feels like the best option.
I've seen this question posted in slightly different ways on different sites, within and out of Stack Overflow. I can tell you its probably not an issue with Angular Language Service.
how you've exported the missing Component from the library, e.g. check if you:
export * from <your-component>
to your public-api.ts
fileexports
of the Library Module that exports ithow you're importing the Library Component, e.g. check if you:
cd /path/to/<your-library> && npm link
cd /path/to/app && npm link <your-library>
YourLibraryModule
to imports:[]
of your Applications main NgModuleYou maybe forgot to declare the parent component in your App NgModule!!
declarations
that references the missing library Component, and the language service / compiler will complain that the Library Component is missing, but not mention the App Component is incorrectly exported!Sometimes the error may change once you restart the language service (e.g. restart VSCode). For scenario 3 I mentioned above, the error becomes:
Error: Cannot determine the module for class YourAppComponent in YourApp/src/app/components/your-app-component/your-app-component.component.ts! Add YourAppComponent to the NgModule to fix it
And voila!! You see the real problem and fixing it is easy!
To fix the issue, you currently have to build with the production flag --prod
, because, in its current state, the Angular Language Server doesn't work with Ivy builds. By default the angular prod build builds without Ivy. Thus when it is built, it creates a lib.metadata.json
file. This is the file that the language server uses to make the plugin work.
ng build <lib> --prod
--watch
flag to watch for changescd dist
then npm link
package.json
in the dist
folder and created the link there since my lib has multiple modules in it. This will allow you to do
import { ModuleAComponent } from '<lib>/moduleA'
import { ModuleADirective } from '<lib>/moduleA'
package.json
otherwise it will use the root of the project since that is the closest package.json
"lib": ["./node_modules/lib", "./node_modules/lib/*"]
npm link <lib>
path
in your tsconfig.base.json
(The path might be different depending on how you created your link){
"compilerOptions": {
"paths": {
"lib/*": [
"./node_modules/lib/*"
]
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With