可替换组件如何与扩展协同工作
ABP 页面中使用了额外的 UI 扩展点(实体操作扩展、数据表格列扩展、页面工具栏扩展等),用于控制页面的实体操作、表格列和页面工具栏。如果您替换了某个页面,需要进行一些配置才能使扩展组件在您的组件中正常工作。让我们通过替换角色页面来看看具体如何操作。
创建一个名为 MyRolesModule 的新模块:
yarn ng generate module my-roles --module app
创建一个名为 MyRolesComponent 的新组件:
yarn ng generate component my-roles/my-roles --flat --export
打开生成的 src/app/my-roles/my-roles.component.ts 文件,并将其内容替换为以下代码:
import { Component, Injector, inject, OnInit } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { finalize } from 'rxjs/operators';
import { ListService, PagedAndSortedResultRequestDto, PagedResultDto } from '@abp/ng.core';
import { eIdentityComponents, RolesComponent } from '@abp/ng.identity';
import { IdentityRoleDto, IdentityRoleService } from '@abp/ng.identity/proxy';
import { ePermissionManagementComponents } from '@abp/ng.permission-management';
import { Confirmation, ConfirmationService } from '@abp/ng.theme.shared';
import {
EXTENSIONS_IDENTIFIER,
FormPropData,
generateFormFromProps
} from '@abp/ng.components/extensible';
@Component({
selector: 'app-my-roles',
templateUrl: './my-roles.component.html',
providers: [
ListService,
{
provide: EXTENSIONS_IDENTIFIER,
useValue: eIdentityComponents.Roles,
},
{
provide: RolesComponent,
useExisting: MyRolesComponent,
},
],
})
export class MyRolesComponent implements OnInit {
public readonly list = inject<ListService<PagedAndSortedResultRequestDto>>(ListService);
protected readonly confirmationService = inject(ConfirmationService);
protected readonly injector = inject(Injector);
protected readonly service = inject(IdentityRoleService);
data: PagedResultDto<IdentityRoleDto> = { items: [], totalCount: 0 };
form: FormGroup;
selected: IdentityRoleDto;
isModalVisible: boolean;
visiblePermissions = false;
providerKey: string;
modalBusy = false;
permissionManagementKey = ePermissionManagementComponents.PermissionManagement;
onVisiblePermissionChange = (event) => {
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.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.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) {
const { prop, dir } = data.sorts[0];
this.list.sortKey = prop;
this.list.sortOrder = dir;
}
}
{
provide: EXTENSIONS_IDENTIFIER,
useValue: eIdentityComponents.Roles,
},
{
provide: RolesComponent,
useExisting: MyRolesComponent
}
我们在 MyRolesComponent 中定义的这两个提供者是扩展组件正确工作所必需的。
- 通过第一个提供者,我们定义了扩展标识符,以便在
MyRolesComponent中使用RolesComponent的扩展操作。 - 通过第二个提供者,我们用
MyRolesComponent替换了RolesComponent注入。RolesComponent的默认扩展操作尝试获取RolesComponent实例。然而,在定义了第二个提供者之后,这些操作可以获取MyRolesComponent实例。
打开生成的 src/app/my-role/my-role.component.html 文件,并将其内容替换为以下代码:
<div id="identity-roles-wrapper" class="card">
<div class="card-header">
<div class="row">
<div class="col col-md-6">
<h5 class="card-title">我的角色</h5>
</div>
<div class="text-end col col-md-6">
<abp-page-toolbar [record]="data.items"></abp-page-toolbar>
</div>
</div>
</div>
<div class="card-body">
<abp-extensible-table
[data]="data.items"
[recordsTotal]="data.totalCount"
[list]="list"
></abp-extensible-table>
</div>
</div>
<abp-modal size="md" [(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>
<abp-extensible-form [selectedRecord]="selected"></abp-extensible-form>
</form>
</ng-template>
<ng-template #abpFooter>
<button type="button" class="btn btn-secondary" 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-toolbar、abp-extensible-table 和 abp-extensible-form 扩展组件添加到 MyRolesComponent 的模板中。
您需要将 MyRolesComponent 所需的模块导入到 MyRolesModule 中。打开 src/my-roles/my-roles.module.ts 文件,并将其内容替换为以下代码:
import { ExtensibleModule } from '@abp/ng.components/extensible';
import { NgModule } from '@angular/core';
import { SharedModule } from '../shared/shared.module';
import { MyRolesComponent } from './my-roles.component';
import { PermissionManagementModule } from '@abp/ng.permission-management';
@NgModule({
declarations: [MyRolesComponent],
imports: [SharedModule, ExtensibleModule, PermissionManagementModule],
exports: [MyRolesComponent],
})
export class MyRolesModule {}
- 导入
ExtensionsModule以便在您的组件中使用扩展组件。 - 导入
PermissionManagementModule以便在您的组件中使用abp-permission-*management。
最后一步,需要用 MyRolesComponent 替换 RolesComponent。打开 app.component.ts 文件,并按如下所示修改其内容:
import { Component, inject } from '@angular/core';
import { ReplaceableComponentsService } from '@abp/ng.core';
import { eIdentityComponents } from '@abp/ng.identity';
import { MyRolesComponent } from './my-roles/my-roles.component';
@Component({
// 组件元数据
})
export class AppComponent {
private replaceableComponents = inject(ReplaceableComponentsService);
constructor() {
this.replaceableComponents.add({ component: MyRolesComponent, key: eIdentityComponents.Roles });
}
}
完成上述步骤后,RolesComponent 已成功被 MyRolesComponent 替换。当您导航到 /identity/roles URL 时,您将看到 MyRolesComponent 的模板,并看到扩展组件正常工作。
抠丁客




