Reputation: 29
I am migrating old angular project from version 5 to version 19. I have indentified all compatible and dependent libraries and able to migrate code. However I keep getting standanlone error.
Note : I have already tried standalone:false
in the component section. It is not helping, because I'm getting same error.
The project is based on NgModule and I want to have as is, and I don't need the standalone feature as now.
ng build
√ Browser application bundle generation complete.
Error: src/app/app.module.ts:7:5 - error NG6008: Component AppComponent is standalone, and cannot be declared in an NgModule. Did you mean to import it instead?
7 AppComponent // Declare AppComponent here
To drill down the issue, I created a minimal project from actual and reproduded the issue. I added standalone:false
in the angular.json, cleared cache, removed node-modules, verified all ts files for no standalone:true
. However this has become a nightmare for me as from last two day I am not able to fix it.
angular.json
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"resource-planning": {
"projectType": "application",
"root": "src",
"sourceRoot": "src",
"prefix": "app",
"schematics": {
"@schematics/angular:component": {
"standalone": false
}
},
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/resource-planning",
"index": "src/index.html",
"main": "src/main.ts",
//"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": true,
"assets": [
"src/assets",
"src/favicon.ico"
],
"styles": [
"src/styles.css",
"node_modules/font-awesome/css/font-awesome.min.css",
"node_modules/primeng/resources/themes/omega/theme.css",
"node_modules/primeng/resources/primeng.min.css"
],
"scripts": []
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"buildTarget": "resource-planning:build"
},
"configurations": {
"production": {
"buildTarget": "resource-planning:build:production"
}
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
//"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "./karma.conf.js",
"styles": [
"src/styles.css",
"node_modules/font-awesome/css/font-awesome.min.css",
"node_modules/primeng/resources/themes/omega/theme.css",
"node_modules/primeng/resources/primeng.min.css"
],
"scripts": [],
"assets": [
"src/assets",
"src/favicon.ico"
]
}
},
"lint": {
"builder": "@angular-eslint/builder:lint",
"options": {
"lintFilePatterns": ["src/**/*.ts", "src/**/*.html"]
}
}
}
}
}
}
package.json
{
"name": "resource-planning",
"version": "0.0.0",
"license": "MIT",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build --prod",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "^19.0.5",
"@angular/common": "^19.0.5",
"@angular/compiler": "^19.0.5",
"@angular/core": "^19.0.5",
"@angular/forms": "^19.0.5",
"@angular/platform-browser": "^19.0.5",
"@angular/platform-browser-dynamic": "^19.0.5",
"@angular/router": "^19.0.5",
"@fortawesome/fontawesome-free": "^6.5.0",
"core-js": "^3.32.2",
"ngx-bootstrap": "^19.0.1",
"primeicons": "^7.0.0",
"primeng": "^19.0.1",
"rxjs": "^7.8.0",
"xlsx": "^0.18.5",
"zone.js": "~0.15.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "^19.0.6",
"@angular/cli": "^19.0.5",
"@angular/compiler-cli": "^19.0.5",
"@angular/language-service": "^19.0.5",
"@eslint/config-array": "^0.19.1",
"@eslint/object-schema": "^2.0.3",
"@types/jasmine": "^4.5.0",
"@types/jasminewd2": "^2.0.10",
"@types/node": "^20.4.0",
"angular-eslint": "19.0.2",
"cypress": "^13.0.0",
"eslint": "^9.16.0",
"glob": "^9.0.0",
"rimraf": "^4.0.0",
"ts-node": "~10.9.1",
"typescript": "~5.6.0",
"typescript-eslint": "8.18.0"
}
}
app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent // Declare AppComponent here
],
imports: [
BrowserModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'My Angular App';
}
app-routing.module.ts
import { Routes,RouterModule } from '@angular/router';
import { NgModule } from '@angular/core';
@NgModule({
imports: [
],
exports: [RouterModule]
})
export class AppRoutingModule {}
main.ts
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
/*platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.log(err));
*/
console.log('App bootstrapping...');
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.error('Error bootstrapping module:', err));
Upvotes: 2
Views: 2566
Reputation: 57986
If you are not ready to go with standalone component, all you need to do is to add standalone: false
to all your components. This can be easily achieved using vsCode
find and replace feature, since we just add an extra property:
In Angular 19, all components are by default standalone: true
. If a component is standalone, it has to have its own imports and can work individually without relying on other parts of the application. We can add them to the imports array to use them.
If you want to use standalone component, then you should have a look at the below link:
ng g @angular/core:standalone
Migration code that helps you move to standalone components.
There are two possible fixes here.
In this approach, you leave the component as standalone and the changes are made on main.ts
, where we use bootstrapApplication
to bootstrap the component (defaults to standalone), apart from this, we also use the ApplicationConfig
object to add providers:
provideHttpClient
-> required for http client to be available in dependency injection.
provideAnimations
-> required for angular animations to work.
import { bootstrapApplication } from '@angular/platform-browser';
import { enableProdMode } from '@angular/core';
import { AppComponent } from './app/app.component';
import { environment } from './environments/environment';
import { provideHttpClient } from '@angular/common/http';
import { provideAnimations } from '@angular/platform-browser/animations';
if (environment.production) {
enableProdMode();
}
bootstrapApplication(AppComponent, {
providers: [
provideHttpClient(), // <- required for http client to work
provideAnimations(), // <- required for animations to work
]
})
.catch(err => console.error('Error bootstrapping module:', err));
This approach requires less coding effort, we can simply set the AppComponent
to standalone: false
, by doing this we can bootstrap it using the appModule and it will work, but other parts of your code should try to use the standalone approach wherever needed. By manually setting the standalone
to false
, angular considers it as a non standalone component and bootstrapping using module works.
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
standalone: false,
})
export class AppComponent {
title = 'My Angular App';
}
Upvotes: 4
Reputation: 93
You can try the steps mentioned in this Medium article:
In angular.json
, under schematics, add the below lines:
"schematics": {
"@schematics/angular: component": {
"standalone": false
},
"@schematics/angular:directive": {
"standalone": false
· },
"@schematics/angular: pipe" : {
"standalone": false
},
}
Remove app.config.ts
, app.config.server.ts
and app.routes.ts
.
Add app.routing.module.ts
and copy all the Routes from app.routes.ts
to the Routes in app.routing.module.ts
.
In main.ts
, replace:
bootstrapApplication(AppComponent, appConfig).catch((err) =>console.error(err));
to:
platformBrowserDynamic().bootstrapModule(AppModule).catch(err =>console.error(err));
And in here add the required import.
Delete everything from main.server.ts
and paste the below line:
export { AppServerModule as default } from ‘./app/app.module.server’;
In app.module.ts
, under @NgModule
, inside providers array, add
the below line and import the required packages:
provideClientHydration()
Inside bootstrap array, add the below line and import the required packages:
AppComponent
Inside imports array, remove CommonModule
and RouterOutlet
then add below this line and import the required packages:
BrowserModule,AppRoutingModule
Create a new file called app.module.server.ts
with below lines:
import { NgModule } from '@angular/core';
import { ServerModule } from '@angular/platform-server';
import { AppModule } from './app.module';
import { AppComponent } from '../app.component';
@NgModule({
imports: [
AppModule,
ServerModule,
],
bootstrap: [AppComponent],
})
export class AppServerModule {}
And finally in the respective component files, change standalone to false
and
remove import array.
Once you're done, you can build your project and then run it.
I hope this answer will help you!
Please note that these steps are tailored for Angular 17, but they should be largely applicable to Angular 19. So, you may need to adjust as needed for any version-specific differences.
Upvotes: 2