Hello,
After adding this registerLocale function to your module file
let localeMap = {} as { [key: string]: string };
export function registerLocale(
{
cultureNameLocaleFileMap = {},
errorHandlerFn = defaultLocalErrorHandlerFn,
} = {} as RegisterLocaleData
) {
return (locale: string): Promise<any> => {
localeMap = { ...differentLocales, ...cultureNameLocaleFileMap };
const localePath = `/locales/${localeMap[locale] || locale}`;
return new Promise((resolve, reject) => {
return import(
/* webpackMode: "lazy-once" */
/* webpackChunkName: "locales"*/
/* webpackInclude: /[/\\](ar|cs|en|en-GB|es|de|fi|fr|hi|hu|is|it|pt|tr|ru|ro|sk|sl|zh-Hans|zh-Hant)\.(mjs|js)$/ */
/* webpackExclude: /[/\\]global|extra/ */
/* @vite-ignore */
`@angular/common${localePath}`
)
.then(val => {
let module = val;
while (module.default) {
module = module.default;
}
resolve({ default: module });
})
.catch(error => {
errorHandlerFn({
resolve,
reject,
error,
locale,
});
});
});
};
}
Checking these points may be helpful:
Verify the webpack include pattern in the function
*/* webpackInclude: /[/\\](ar|cs|en|en-GB|es|de|fi|fr|hi|hu|is|it|pt|tr|ru|ro|sk|sl|zh-Hans|zh-Hant)\.(mjs|js)$/ */*
The pattern includes en but might not be matching the actual file structure.
Check if en.mjs exists in @angular/common/locales/
`ls angular/node_modules/@angular/common/locales/en*`
The core issue is that the locale files are not being found by the dynamic import, likely due to a path or webpack configuration mismatch.
This might be due to me unintentionally misleading you about importing IdentityModule for MyIdentityModule.
If removing that import doesn’t conflict with your requirements, things should work as expected.
//my-identity.module.ts
import { MyIdentityRoutingModule } from './my-identity-routing.module';
import { SharedModule } from './shared/shared.module';
import { NgModule } from '@angular/core';
@NgModule({
declarations: [],
imports: [SharedModule, MyIdentityRoutingModule],
exports: [MyIdentityRoutingModule],
})
export class MyIdentityModule {}
I see your point now. By this means, you may not even need to replace the UsersComponent Here is how you could achieve this:
//my-identity-routing.module.ts
import { RouterOutletComponent, authGuard, permissionGuard } from '@abp/ng.core';
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { identityExtensionsResolver } from '@volo/abp.ng.identity';
import { UserDetailComponent } from './user-detail/user-detail.component';
import { UserResolver } from './my-users/users.resolver';
const routes: Routes = [
{ path: '', redirectTo: 'roles', pathMatch: 'full' },
{
path: '',
component: RouterOutletComponent,
canActivate: [authGuard, permissionGuard],
resolve: [identityExtensionsResolver],
children: [
{
path: 'users/:id',
component: UserDetailComponent,
title: 'AbpIdentity::Users',
resolve: { user: UserResolver },
},
],
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class MyIdentityRoutingModule {}
//my-identity.module.ts
import { IdentityModule } from '@volo/abp.ng.identity';
import { MyIdentityRoutingModule } from './my-identity-routing.module';
import { SharedModule } from './shared/shared.module';
import { NgModule } from '@angular/core';
@NgModule({
declarations: [],
imports: [IdentityModule, SharedModule, MyIdentityRoutingModule],
exports: [MyIdentityRoutingModule],
})
export class MyIdentityModule {}
Then in your app-routing.module.ts
{
path: 'identity',
loadChildren: () => import('./my-identity.module').then(m => m.MyIdentityModule),
},
// {
// path: 'identity',
// loadChildren: () => import('@volo/abp.ng.identity').then(m => m.IdentityModule.forLazy()),
// },
Hello,
Thank you for providing such detailed information. After reviewing the section where you appended values to the FormData while modifying the proxy, I noticed that you are trying to work with an object on the backend. You can still achieve this functionality without altering the current proxy setup.
These resources might be helpful:
How to Upload and Download Files in ABP: https://abp.io/community/articles/how-to-upload-and-download-files-in-the-abp-framework-using-angular-que8cdr8#gsc.tab=0
Using append() with FormData (MDN): https://developer.mozilla.org/en-US/docs/Web/API/FormData/append
Feel free to reach out if you need further assistance.
Hello,
If your goal is simply to display a detail page based on the user ID, there’s no need to override the IdentityRoutingModule. Instead, you can create a UserResolver as shown below:
@Injectable({ providedIn: 'root' })
export class UserResolver implements Resolve<IdentityUserDto> {
private userService = inject(IdentityUserService);
resolve(route: ActivatedRouteSnapshot): Observable<IdentityUserDto> {
const id = route.paramMap.get('id');
if (!id) {
throw new Error('User ID is required');
}
return this.userService.get(id);
}
}
You can then use this resolver in your routing configuration like so:
const routes: Routes = [
{
path: 'identity',
children: [
{
path: 'users/detail/:id',
component: UserDetailComponent,
resolve: { user: UserResolver },
},
{
path: '',
loadChildren: () =>
import('@volo/abp.ng.identity').then(m => m.IdentityModule.forLazy()),
},
],
},
// Alternative approach [#1](https://abp.io/QA/Questions/1):
// {
// path: 'identity',
// loadChildren: () => import('@volo/abp.ng.identity').then(m => m.IdentityModule.forLazy()),
// },
// {
// path: 'identity/users/detail/:id',
// component: UserDetailComponent,
// resolve: { user: UserResolver },
// },
// Alternative approach [#2](https://abp.io/QA/Questions/2):
// {
// path: 'users/:id',
// component: UserDetailComponent,
// title: 'New Users',
// resolve: { user: UserResolver },
// },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
export class AppRoutingModule {}
Feel free to reach out if you need any further clarification or assistance.
Hello,
Both templates are designed to support a modular structure.
I would like to know if it's possible to generate an Angular frontend in a microservice-based ABP project. If yes, could you please guide me on how to achieve this?
Yes, it is possible to generate an Angular frontend within a microservice-based ABP project. If you're unsure which template best fits your needs, I recommend reviewing the relevant documentation below:
Solution Template Guide: https://abp.io/docs/latest/solution-templates/guide
Microservice Tutorial: https://abp.io/docs/latest/tutorials/microservice?UI=NG&DB=EF
DDD Tutorial: https://abp.io/docs/latest/tutorials/modular-crm
Please feel free to reach out if you need further assistance.
Hello again,
I assume you're using the old CLI for this task. If that's the case, I'm encountering the same issues on my end, and we'll be looking into them. In the meantime, I recommend switching to the new CLI. You can find more information about the differences between the old and new versions here: https://abp.io/docs/latest/cli/differences-between-old-and-new-cli
Additionally, if you'd like to use the Lepton theme, make sure you have the following packages installed:
"@volo/abp.ng.theme.lepton": "~9.2.2",
"@volosoft/abp.ng.theme.lepton-x": "~4.2.1",
For more information on configuring themes, check out this guide: https://abp.io/docs/latest/framework/ui/angular/theme-configurations
Hello, thank you for providing necessary and extra information regarding your problem. I checked your project, however I could not see the module.
!-- removed picture --!
Regardless of the module, I can suggest you to discard proxy paths. Here is how paths are generated within the latest version of ABP studio:
// angular/tsconfig.json
{
...
"paths": {
"@angular/*": ["node_modules/@angular/*"],
"@abp/*": ["node_modules/@abp/*"],
"@volo/*": ["node_modules/@volo/*"],
"@volosoft/*": ["node_modules/@volosoft/*"],
"@swimlane/*": ["node_modules/@swimlane/*"],
"@ngx-validate/core": ["node_modules/@ngx-validate/core"],
"@ng-bootstrap/ng-bootstrap": ["node_modules/@ng-bootstrap/ng-bootstrap"],
"@book-store": ["../modules/bookstore/angular/projects/book-store/src/public-api.ts"],
"@book-store/config": [
"../modules/bookstore/angular/projects/book-store/config/src/public-api.ts"
]
},
...
}
You can directly use the relative path as follows:
import type { BookStoreEntityOneDto } from '../../../proxy/book-store-entity-ones/models';
import { BookStoreEntityOneService } from '../../../proxy/book-store-entity-ones/book-store-entity-one.service';
export abstract class AbstractBookStoreEntityOneDetailViewService {
// ...
}
You can let me know if you need further assistance. Thank you for your cooperation.
Unfortunately, you cannot modify the specific tab in this way. However, I can suggest you two other ways to consider:
// ...
import { SettingTabsService } from '@abp/ng.setting-management/config';
@Component({
selector: 'app-root',
template: `
<abp-loader-bar></abp-loader-bar>
<abp-dynamic-layout></abp-dynamic-layout>
<abp-gdpr-cookie-consent></abp-gdpr-cookie-consent>
`,
})
export class AppComponent {
private settingTabs = inject(SettingTabsService);
constructor() {
// 1. You can consider adding a new tab
// this.settingTabs.add([
// {
// name: 'MySettings',
// order: 1,
// component: MySettings,
// },
// ]);
// 2. Or patch an existing tab
this.settingTabs.patch('AbpIdentity::Menu:IdentityManagement', {
name: 'MySettings',
order: 1,
component: MySettings,
});
}
}
Node version: 22.17.0 Yarn version: 4.9.2 Npm version 10.9.2
There is no problem regarding version incompatibility. As I mentioned, the project you sent works when you add the related import since it is used in the app module. Could there be something you customized other than the default generated template?
Why did you create the template with references?
Including references like InternetConnectionStatusComponent ensures essential functionality—such as monitoring internet connectivity—is available out of the box. It promotes reusability and improves user experience, but can be removed if not needed.