@switch (feature.valueType?.name) {
diff --git a/npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.ts b/npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.ts
index 5feac210e5..0ba6880036 100644
--- a/npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.ts
+++ b/npm/ng-packs/packages/feature-management/src/lib/components/feature-management/feature-management.component.ts
@@ -1,4 +1,4 @@
-import { Component, EventEmitter, Input, Output, inject, DOCUMENT } from '@angular/core';
+import { Component, inject, DOCUMENT, input, output, signal, effect } from '@angular/core';
import { NgTemplateOutlet } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { ConfigStateService, LocalizationPipe, TrackByService } from '@abp/ng.core';
@@ -20,7 +20,6 @@ import {
import { Tabs, TabList, Tab, TabPanel, TabContent } from '@angular/aria/tabs';
import { finalize } from 'rxjs/operators';
import { FreeTextInputDirective } from '../../directives';
-import { FeatureManagement } from '../../models';
enum ValueTypes {
ToggleStringValueType = 'ToggleStringValueType',
@@ -49,11 +48,7 @@ const DEFAULT_PROVIDER_NAME = 'D';
ModalCloseDirective,
],
})
-export class FeatureManagementComponent
- implements
- FeatureManagement.FeatureManagementComponentInputs,
- FeatureManagement.FeatureManagementComponentOutputs
-{
+export class FeatureManagementComponent {
protected readonly track = inject(TrackByService);
protected readonly toasterService = inject(ToasterService);
protected readonly service = inject(FeaturesService);
@@ -61,14 +56,17 @@ export class FeatureManagementComponent
protected readonly confirmationService = inject(ConfirmationService);
private document = inject(DOCUMENT);
- @Input()
- providerKey: string;
+ // Signal inputs
+ readonly providerKey = input
(undefined);
+ readonly providerName = input(undefined);
+ readonly providerTitle = input(undefined);
+ readonly visibleInput = input(false, { alias: 'visible' });
- @Input()
- providerName: string;
+ // Output signals
+ readonly visibleChange = output();
- @Input({ required: false })
- providerTitle: string;
+ // Internal state
+ protected readonly _visible = signal(false);
selectedGroupDisplayName: string;
@@ -82,33 +80,41 @@ export class FeatureManagementComponent
defaultProviderName = DEFAULT_PROVIDER_NAME;
- protected _visible;
+ modalBusy = false;
- @Input()
+ // Getter/setter for backward compatibility
get visible(): boolean {
- return this._visible;
+ return this._visible();
}
set visible(value: boolean) {
- if (this._visible === value) {
+ if (this._visible() === value) {
return;
}
- this._visible = value;
+ this._visible.set(value);
this.visibleChange.emit(value);
if (value) {
this.openModal();
- return;
}
}
- @Output() readonly visibleChange = new EventEmitter();
-
- modalBusy = false;
+ constructor() {
+ // Sync visible input to internal signal
+ effect(() => {
+ const inputValue = this.visibleInput();
+ if (this._visible() !== inputValue) {
+ this._visible.set(inputValue);
+ if (inputValue) {
+ this.openModal();
+ }
+ }
+ });
+ }
openModal() {
- if (!this.providerName) {
+ if (!this.providerName()) {
throw new Error('providerName is required.');
}
@@ -116,7 +122,7 @@ export class FeatureManagementComponent
}
getFeatures() {
- this.service.get(this.providerName, this.providerKey).subscribe(res => {
+ this.service.get(this.providerName()!, this.providerKey()).subscribe(res => {
if (!res.groups?.length) return;
this.groups = res.groups.map(({ name, displayName }) => ({ name, displayName }));
this.selectedGroupDisplayName = this.groups[0].displayName;
@@ -149,13 +155,13 @@ export class FeatureManagementComponent
this.modalBusy = true;
this.service
- .update(this.providerName, this.providerKey, { features: changedFeatures })
+ .update(this.providerName()!, this.providerKey(), { features: changedFeatures })
.pipe(finalize(() => (this.modalBusy = false)))
.subscribe(() => {
this.visible = false;
this.toasterService.success('AbpUi::SavedSuccessfully');
- if (!this.providerKey) {
+ if (!this.providerKey()) {
// to refresh host's features
this.configState.refreshAppState().subscribe();
}
@@ -167,11 +173,11 @@ export class FeatureManagementComponent
.warn('AbpFeatureManagement::AreYouSureToResetToDefault', 'AbpFeatureManagement::AreYouSure')
.subscribe((status: Confirmation.Status) => {
if (status === Confirmation.Status.confirm) {
- this.service.delete(this.providerName, this.providerKey).subscribe(() => {
+ this.service.delete(this.providerName()!, this.providerKey()).subscribe(() => {
this.toasterService.success('AbpFeatureManagement::ResetedToDefault');
this.visible = false;
- if (!this.providerKey) {
+ if (!this.providerKey()) {
// to refresh host's features
this.configState.refreshAppState().subscribe();
}
@@ -190,17 +196,18 @@ export class FeatureManagementComponent
isParentDisabled(parentName: string, groupName: string, provider: string): boolean {
const children = this.features[groupName]?.filter(f => f.parentName === parentName);
+ const providerNameValue = this.providerName();
if (children?.length) {
return children.some(child => {
const childProvider = child.provider?.name;
return (
- (childProvider !== this.providerName && childProvider !== this.defaultProviderName) ||
- (provider !== this.providerName && provider !== this.defaultProviderName)
+ (childProvider !== providerNameValue && childProvider !== this.defaultProviderName) ||
+ (provider !== providerNameValue && provider !== this.defaultProviderName)
);
});
} else {
- return provider !== this.providerName && provider !== this.defaultProviderName;
+ return provider !== providerNameValue && provider !== this.defaultProviderName;
}
}
diff --git a/npm/ng-packs/packages/feature-management/src/lib/directives/free-text-input.directive.ts b/npm/ng-packs/packages/feature-management/src/lib/directives/free-text-input.directive.ts
index 6b6556dcfa..b341879995 100644
--- a/npm/ng-packs/packages/feature-management/src/lib/directives/free-text-input.directive.ts
+++ b/npm/ng-packs/packages/feature-management/src/lib/directives/free-text-input.directive.ts
@@ -1,4 +1,4 @@
-import { Directive, HostBinding, Input } from '@angular/core';
+import { Directive, effect, inject, input, ElementRef, Renderer2 } from '@angular/core';
// TODO: improve this type
export interface FreeTextType {
@@ -9,7 +9,7 @@ export interface FreeTextType {
};
}
-export const INPUT_TYPES = {
+export const INPUT_TYPES: Record = {
numeric: 'number',
default: 'text',
};
@@ -19,21 +19,25 @@ export const INPUT_TYPES = {
exportAs: 'inputAbpFeatureManagementFreeText',
})
export class FreeTextInputDirective {
- _feature: FreeTextType;
- // eslint-disable-next-line @angular-eslint/no-input-rename
- @Input('abpFeatureManagementFreeText') set feature(val: FreeTextType) {
- this._feature = val;
- this.setInputType();
- }
+ private readonly elRef = inject(ElementRef);
+ private readonly renderer = inject(Renderer2);
- get feature() {
- return this._feature;
- }
+ readonly feature = input(undefined, {
+ alias: 'abpFeatureManagementFreeText',
+ });
- @HostBinding('type') type: string;
+ constructor() {
+ effect(() => {
+ const feature = this.feature();
+ if (feature) {
+ this.setInputType(feature);
+ }
+ });
+ }
- private setInputType() {
- const validatorType = this.feature?.valueType?.validator?.name.toLowerCase();
- this.type = INPUT_TYPES[validatorType] ?? INPUT_TYPES.default;
+ private setInputType(feature: FreeTextType) {
+ const validatorType = feature?.valueType?.validator?.name?.toLowerCase();
+ const type = INPUT_TYPES[validatorType] ?? INPUT_TYPES['default'];
+ this.renderer.setAttribute(this.elRef.nativeElement, 'type', type);
}
}
diff --git a/npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.html b/npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.html
index 0224f3d45a..0711bb995b 100644
--- a/npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.html
+++ b/npm/ng-packs/packages/permission-management/src/lib/components/permission-management.component.html
@@ -1,9 +1,9 @@
- @if (data.entityDisplayName || entityDisplayName) {
+ @if (data.entityDisplayName || entityDisplayName()) {
{{ 'AbpPermissionManagement::Permissions' | abpLocalization }} -
- {{ entityDisplayName || data.entityDisplayName }}
+ {{ entityDisplayName() || data.entityDisplayName }}
@@ -115,7 +115,7 @@
/>