Also removing password change component from manage-profile-tabs.provider.ts altogether, I still get the same error.
Something about the way MANAGE_PROFILE_TAB_PROVIDER is handled by the framework isn't working.
Here's password change module, unchanged from the ng generate version:
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { PasswordChangeComponent } from './password-change.component';
@NgModule({
declarations: [
PasswordChangeComponent
],
imports: [
CommonModule
]
})
export class PasswordChangeModule { }
Here's the component also unchanged:
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-password-change',
templateUrl: './password-change.component.html',
styleUrls: ['./password-change.component.scss']
})
export class PasswordChangeComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}
Removing the reference to password change from app.module.ts leaves me with the same error:
NullInjectorError: R3InjectorError(AppModule)[ApplicationModule -> ApplicationRef -> ApplicationInitStatus -> InjectionToken Application Initializer -> [object Object] -> ManageProfileTabsService -> ManageProfileTabsService -> ManageProfileTabsService]:
NullInjectorError: No provider for ManageProfileTabsService!
Something else foundational is missing from the site implementation itself but I don't know where to look for it. What normally injects the ManageProfileTabsService into the stack? It isn't explicitly called in app.module.ts so what part of what file is doing it? I search the sites code base and only my manage-profile-tabs.provider.ts file references it, so the problem is in the framework somewhere. Did a later version of 5.3 get a bug fix to rectify this that I have to reproduce?
Setting that const MANAGE_PROFILE_TAB_PROVIDER is breaking some other validation or other.
Best I can guess, Angular isn't picking up that MANAGE_PROFILE_TAB_PROVIDER is standing in for ManageProfileTabsService. What can I look at, where is that supposed to happen, what's ABP.IO doing? Give me something to poke and I'll poke it, it's not my code base.
Adding ManageProfileTabsService to providers prevents the custom component page from showing
Removing it causes the error to occur.
Sorry this is going round in circles mate.
SO I get "NullInjectorError: No provider for ManageProfileTabsService!" I add ManageProfileTabsService to app.module.ts providers and that goes away.
SO the code for MANAGE_PROFILE_TAB_PROVIDER and my PasswordChangeComponent/Module seems to be compiling. BUT the old profile screens are still there. Probably because I added ManageProfileTabsService to providers right?
I can't figure out how to solve that NullInjectorError properly.
MANAGE_PROFILE_TAB_PROVIDER
import { APP_INITIALIZER } from '@angular/core';
import { TwoFactorTabComponent } from '@volo/abp.ng.account/public';
import {
eAccountManageProfileTabNames,
ManageProfileTabsService,
} from '@volo/abp.ng.account/public/config';
import { PasswordChangeComponent } from './password-change.component';
export const MANAGE_PROFILE_TAB_PROVIDER = {
provide: APP_INITIALIZER,
useFactory: configureManageProfileTabs,
deps: [ManageProfileTabsService],
multi: true,
};
export function configureManageProfileTabs(tabs: ManageProfileTabsService) {
return () => {
tabs.add([
{
name: 'ChangePasswordNew',
order: 5,
component: PasswordChangeComponent,
},
]);
tabs.patch(eAccountManageProfileTabNames.TwoFactor, {
name: 'Two factor authentication',
component: TwoFactorTabComponent,
});
tabs.remove([eAccountManageProfileTabNames.ChangePassword]);
};
}
app.module.ts
import { LOCALE_ID, NgModule } from '@angular/core';
import { registerLocaleData } from '@angular/common';
import { OverlayModule } from '@angular/cdk/overlay';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import localeEnAu from '@angular/common/locales/en-AU';
import { CoreModule } from '@abp/ng.core';
import { registerLocale } from '@abp/ng.core/locale';
import { ThemeSharedModule } from '@abp/ng.theme.shared';
import { SettingManagementConfigModule } from '@abp/ng.setting-management/config';
import { SaasConfigModule } from '@volo/abp.ng.saas/config';
import { IdentityConfigModule } from '@volo/abp.ng.identity/config';
import { AccountAdminConfigModule } from '@volo/abp.ng.account/admin/config';
import { AuditLoggingConfigModule } from '@volo/abp.ng.audit-logging/config';
import { IdentityServerConfigModule } from '@volo/abp.ng.identity-server/config';
import { LanguageManagementConfigModule } from '@volo/abp.ng.language-management/config';
import { TextTemplateManagementConfigModule } from '@volo/abp.ng.text-template-management/config';
import { HttpErrorComponent, ThemeLeptonModule } from '@volo/abp.ng.theme.lepton';
import { CommercialUiConfigModule } from '@volo/abp.commercial.ng.ui/config';
import { NgxEchartsModule } from 'ngx-echarts';
import { NgxsModule } from '@ngxs/store';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { NgMultiSelectDropDownModule } from 'ng-multiselect-dropdown';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { APP_ROUTE_PROVIDER } from './route.provider';
import { environment} from '../environments/environment';
import { REPORTS} from "./report/core/domain/report-plugin";
import { IOReportPlugin } from './report/io/IOReportPlugin';
import { HMAReportPlugin } from './report/hma/HMAReportPlugin';
import { REPORT_TYPES} from "./report-type/core/domain/report-type-plugin";
import { IOReportTypePlugin } from './report-type/io/IOReportTypePlugin';
import { HMAReportTypePlugin } from './report-type/hma/HMAReportTypePlugin';
import { PasswordChangeModule } from './password-change/password-change.module';
import { MANAGE_PROFILE_TAB_PROVIDER } from './password-change/manage-profile-tabs.provider';
// first part of setting local to au locale rather than
// the default en-us
registerLocaleData(localeEnAu);
const REPORT_PLUGINS = [
{
provide: REPORTS,
multi: true,
useClass: IOReportPlugin,
},
{
provide: REPORTS,
multi: true,
useClass: HMAReportPlugin,
},
];
const REPORT_TYPE_PLUGINS = [
{
provide: REPORT_TYPES,
multi: true,
useClass: IOReportTypePlugin,
},
{
provide: REPORT_TYPES,
multi: true,
useClass: HMAReportTypePlugin,
},
];
@NgModule({
declarations: [AppComponent],
imports: [
AppRoutingModule,
BrowserModule,
BrowserAnimationsModule,
NgbModule,
NgMultiSelectDropDownModule.forRoot(),
NgxEchartsModule.forRoot({
echarts: () => import('echarts'),
}),
NgxsModule.forRoot([]),
OverlayModule,
CoreModule.forRoot({
environment,
registerLocaleFn: registerLocale(),
}),
ThemeSharedModule.forRoot({
httpErrorConfig: {
errorScreen: {
component: HttpErrorComponent,
forWhichErrors: [401, 403, 404, 500],
hideCloseIcon: true,
},
},
}),
ThemeLeptonModule.forRoot(),
CommercialUiConfigModule.forRoot(),
SettingManagementConfigModule.forRoot(),
AccountAdminConfigModule.forRoot(),
IdentityConfigModule.forRoot(),
LanguageManagementConfigModule.forRoot(),
SaasConfigModule.forRoot(),
AuditLoggingConfigModule.forRoot(),
IdentityServerConfigModule.forRoot(),
TextTemplateManagementConfigModule.forRoot(),
PasswordChangeModule
],
providers: [
APP_ROUTE_PROVIDER,
REPORT_PLUGINS,
REPORT_TYPE_PLUGINS,
// there has to be a better way to do this with the abp localization but
// i couldn't work it out. For the timebeing set it to en-au so date/times
// get converted correctly in the ui
{ provide: LOCALE_ID, useValue: 'en-AU' },
MANAGE_PROFILE_TAB_PROVIDER
],
bootstrap: [AppComponent],
})
export class AppModule {}
"Create new component my-awsome-tab-component with module"
the 'with module' part is missing from the instructions at https://docs.abp.io/en/commercial/5.3/ui/angular/manage-profile-page-tabs
Are there steps for that? Not having much success trying to do it manually
Adding in the MANAGE_PROFILE_TAB_PROVIDER prevents the site from loading, no idea what would be conflicting with it though.
Unfortunately, that appears to be for a different version of ABP. Some of that code simply isn't valid. But at least my approach is the same. Now only if it would work!
I was following this guide: https://docs.abp.io/en/abp/5.3/UI/Angular/Component-Replacement With this sample: https://docs.abp.io/en/abp/5.3/UI/Angular/Permission-Management-Component-Replacement
I used ng generate to make my component
yarn ng generate component password-change --inlineStyle
Added the reference to it in app.component.ts
import { Component } from '@angular/core';
import { ReplaceableComponentsService } from '@abp/ng.core';
import { eAccountComponents } from '@volo/abp.ng.account/public/enums/components';
import { OnInit } from '@angular/core';
import { PasswordChangeComponent } from './password-change/password-change.component';
@Component({
selector: 'app-root',
template: `
<abp-loader-bar></abp-loader-bar>
<abp-dynamic-layout></abp-dynamic-layout>
`,
})
export class AppComponent implements OnInit {
constructor(private replaceableComponents: ReplaceableComponentsService) {} // injected ReplaceableComponentsService
ngOnInit() {
this.replaceableComponents.add({
component: PasswordChangeComponent,
key: eAccountComponents.ChangePassword,
});
}
}
I expect to see "password-change works!" in the 'My account > Change password' tab but I still see the default Account module behaviour:
Have I gone about this the wrong way?
The ultimate goal is to display a link to Azure B2C where they can change their password but for now, I just want to make sure I'm going about customizing this properly.
Looks like this is what I was looking for. Useful for anyone else having this problem getting it to work for ABP. https://medium.com/the-new-control-plane/using-the-userinfo-endpoint-in-azure-ad-b2c-41a01c4907a2