<abp-page [title]="'AbpIdentity::Roles' | abpLocalization" [toolbar]="data.items"> <div id="identity-roles-wrapper" class="card"> <div class="card-body"> <abp-extensible-table [data]="data.items" [recordsTotal]="data.totalCount" [list]="list" ></abp-extensible-table> </div> </div>
<abp-modal [(visible)]="isModalVisible" [busy]="modalBusy"> <ng-template #abpHeader> <h3>{{ (selected?.id ? 'AbpIdentity::Edit' : 'AbpIdentity::NewRole') | abpLocalization }}</h3> </ng-template>
<ng-template #abpBody>
<form [formGroup]="form" (ngSubmit)="save()" [validateOnSubmit]="true">
<abp-extensible-form [selectedRecord]="selected"></abp-extensible-form>
</form>
</ng-template>
<ng-template #abpFooter>
<button type="button" class="btn btn-outline-primary" abpClose>
{{ 'AbpIdentity::Cancel' | abpLocalization }}
</button>
<abp-button iconClass="fa fa-check" [disabled]="form?.invalid" (click)="save()">{{
'AbpIdentity::Save' | abpLocalization
}}</abp-button>
</ng-template>
</abp-modal>
<abp-permission-management #abpPermissionManagement="abpPermissionManagement" *abpReplaceableTemplate=" { inputs: { providerName: { value: 'R' }, providerKey: { value: providerKey }, visible: { value: visiblePermissions, twoWay: true }, hideBadges: { value: true } }, outputs: { visibleChange: onVisiblePermissionChange }, componentKey: permissionManagementKey }; let init = initTemplate " (abpInit)="init(abpPermissionManagement)" > </abp-permission-management> </abp-page>
Can't bind to 'abpReplaceableTemplate' since it isn't a known property of 'abp-permission-management' (used in the 'RolesManagementComponent' component template).
- If 'abp-permission-management' is an Angular component and it has the 'abpReplaceableTemplate' input, then verify that it is included in the '@Component.imports' of this component.
- If 'abp-permission-management' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@Component.schemas' of this component to suppress this message.
- To allow any property add 'NO_ERRORS_SCHEMA' to the '@Component.schemas' of this component.
5 Answer(s)
-
0
- Solution
- Open-source ABP Angular components (e.g., abp-modal, page toolbar, extensible table, advanced filters) live in the ABP Framework repo under the Angular packages. You can browse, copy, or extend them:
- Repository path:
- npm/ng-packs/packages/theme-shared → shared UI components (e.g., abp-modal, buttons, page toolbars)
- Other Angular packages are under npm/ng-packs/packages as well
- Repository path:
- Steps to obtain and customize:
- Browse the source
- Go to the ABP repo’s Angular packages and locate the component folder (for example, modal.component.* under theme-shared).
- Copy into your app
- Create your own Angular component in your app, copy the template/ts/scss as a starting point, and adjust as needed.
- Replace (if using theme components)
- If the component is used via the theme and supports replacement, register your custom component with the app’s replaceable/override mechanism where applicable (for LeptonX, use ReplaceableComponentsService with the correct key).
- Build and import
- Make sure to import any dependent modules/services used by the original component (e.g., NgbModal, ABP services).
- Browse the source
- Commercial-only Angular components
- If the component belongs to the commercial UI packages, you can fetch the source via:
- ABP Suite → Download LeptonX source if you need to customize LeptonX theme components.
- Or install the commercial Angular UI package with source code: abp add-package @volo/abp.commercial.ng.ui --with-source-code
- If the component belongs to the commercial UI packages, you can fetch the source via:
- Using ABP Angular UI docs to identify components and usage
- Check the Angular UI overview and component sections to identify component names and packages, then locate them in the repo path above.
- Sources
- Validated links only:
- ABP Framework GitHub (Angular packages root): https://github.com/abpframework/abp/tree/dev/npm/ng-packs/packages
- ABP Framework GitHub (repo root): https://github.com/abpframework/abp
- ABP Commercial portal (Suite/source access info): https://commercial.abp.io
This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.
-
0
Hello,
Normally, you should be able to replace the components by following the documentation here: https://abp.io/docs/latest/framework/ui/angular/component-replacement
Could you please provide the steps to reproduce the issue, along with the ABP version you are using?
Thank you for your cooperation.
-
0
[sumeyye.kurtulus] said: Hello,
Normally, you should be able to replace the components by following the documentation here: https://abp.io/docs/latest/framework/ui/angular/component-replacement
Could you please provide the steps to reproduce the issue, along with the ABP version you are using?
Thank you for your cooperation.
abp 9.3.1
replace rolescomponent and permissionmanagementcomponent then error
click then error -
0
Hello,
Thank you for providing extra details about your problem. I have checked these replacements and the flow needs to be working fine. However, it depends on how you have replaced these components. Could you clarify whether you have connected the source code?
-
0
I copy code from source code
RolesComponent
import { InitDirective, ListService, LocalizationPipe, PagedAndSortedResultRequestDto, PagedResultDto, ReplaceableTemplateDirective } from '@abp/ng.core'; import { IdentityRoleDto, IdentityRoleService } from '@abp/ng.identity/proxy'; import { ePermissionManagementComponents, PermissionManagementComponent, } from '@abp/ng.permission-management'; import { ButtonComponent, Confirmation, ConfirmationService, ModalCloseDirective, ModalComponent, ToasterService, } from '@abp/ng.theme.shared'; import { ExtensibleFormComponent, ExtensibleTableComponent, EXTENSIONS_IDENTIFIER, FormPropData, generateFormFromProps, } from '@abp/ng.components/extensible'; import { Component, inject, Injector, OnInit } from '@angular/core'; import { ReactiveFormsModule, UntypedFormGroup } from '@angular/forms'; import { finalize } from 'rxjs/operators'; import { eIdentityComponents, RolesComponent } from '@abp/ng.identity'; import { PageComponent } from '@abp/ng.components/page'; import { NgxValidateCoreModule } from '@ngx-validate/core';
@Component({ selector: 'app-rolescomponent', templateUrl: './roles-management.component.html', providers: [ ListService, { provide: EXTENSIONS_IDENTIFIER, useValue: eIdentityComponents.Roles, }, { provide: RolesComponent, useExisting: RolesManagementComponent, }, ], imports: [ ReactiveFormsModule, LocalizationPipe, ExtensibleTableComponent, ModalComponent, ButtonComponent, PageComponent, ExtensibleFormComponent, ModalCloseDirective, PermissionManagementComponent, ReplaceableTemplateDirective, NgxValidateCoreModule, InitDirective, ], }) export class RolesManagementComponent implements OnInit { protected readonly list = inject(ListService<PagedAndSortedResultRequestDto>); protected readonly confirmationService = inject(ConfirmationService); protected readonly toasterService = inject(ToasterService); private readonly injector = inject(Injector); protected readonly service = inject(IdentityRoleService);
data: PagedResultDto<IdentityRoleDto> = { items: [], totalCount: 0 }; form!: UntypedFormGroup; selected?: IdentityRoleDto; isModalVisible!: boolean; visiblePermissions = false; providerKey?: string; modalBusy = false; permissionManagementKey = ePermissionManagementComponents.PermissionManagement;
onVisiblePermissionChange = (event: boolean) => { this.visiblePermissions = event; };
ngOnInit() { this.hookToQuery(); }
buildForm() { const data = new FormPropData(this.injector, this.selected); this.form = generateFormFromProps(data); }
openModal() { this.buildForm(); this.isModalVisible = true; }
add() { this.selected = {} as IdentityRoleDto; this.openModal(); }
edit(id: string) { this.service.get(id).subscribe(res => { this.selected = res; this.openModal(); }); }
save() { if (!this.form.valid) return; this.modalBusy = true;
const { id } = this.selected || {}; (id ? this.service.update(id, { ...this.selected, ...this.form.value }) : this.service.create(this.form.value) ) .pipe(finalize(() => (this.modalBusy = false))) .subscribe(() => { this.isModalVisible = false; this.toasterService.success('AbpUi::SavedSuccessfully'); this.list.get(); });}
delete(id: string, name: string) { this.confirmationService .warn('AbpIdentity::RoleDeletionConfirmationMessage', 'AbpIdentity::AreYouSure', { messageLocalizationParams: [name], }) .subscribe((status: Confirmation.Status) => { if (status === Confirmation.Status.confirm) { this.toasterService.success('AbpUi::DeletedSuccessfully'); this.service.delete(id).subscribe(() => this.list.get()); } }); }
private hookToQuery() { this.list .hookToQuery(query => this.service.getList(query)) .subscribe(res => { this.data = res; }); }
openPermissionsModal(providerKey: string) { this.providerKey = providerKey; setTimeout(() => { this.visiblePermissions = true; }, 0); }
sort(data: any) { const { prop, dir } = data.sorts[0]; this.list.sortKey = prop; this.list.sortOrder = dir; } }
