Skip to main content
Version: 0.8.0

Feature Modal

The FeatureManagementModal component provides a ready-to-use modal for managing features of tenants and other entities.

New in v0.8.0

This component was introduced in ABP React v0.8.0.

Basic Usage

import { FeatureManagementModal } from '@abpjs/feature-management';
import { useState } from 'react';

function TenantFeatures({ tenantId }: { tenantId: string }) {
const [visible, setVisible] = useState(false);

return (
<>
<button onClick={() => setVisible(true)}>
Manage Features
</button>

<FeatureManagementModal
providerName="T"
providerKey={tenantId}
visible={visible}
onVisibleChange={setVisible}
/>
</>
);
}

Props

PropTypeRequiredDescription
providerNamestringYesProvider name (e.g., "T" for Tenant)
providerKeystringYesProvider key (e.g., tenant ID)
visiblebooleanYesWhether the modal is visible
onVisibleChange(visible: boolean) => voidNoCallback when visibility changes
onSave() => voidNoCallback fired when features are saved

Provider Names

ProviderNameKeyDescription
TenantTTenant IDManage features for a specific tenant

With Save Callback

import { FeatureManagementModal } from '@abpjs/feature-management';
import { useToast } from '@chakra-ui/react';

function TenantFeatures({ tenantId }) {
const [visible, setVisible] = useState(false);
const toast = useToast();

const handleSave = () => {
toast({
title: 'Features saved',
description: 'Tenant features have been updated successfully.',
status: 'success',
});
};

return (
<>
<button onClick={() => setVisible(true)}>
Manage Features
</button>

<FeatureManagementModal
providerName="T"
providerKey={tenantId}
visible={visible}
onVisibleChange={setVisible}
onSave={handleSave}
/>
</>
);
}

Using the Hook Directly

For more control, use the useFeatureManagement hook directly:

import { useFeatureManagement } from '@abpjs/feature-management';
import { useEffect } from 'react';

function CustomFeatureManager({ tenantId }) {
const {
features,
isLoading,
error,
fetchFeatures,
saveFeatures,
updateFeatureValue,
getFeatureValue,
isFeatureEnabled,
reset,
} = useFeatureManagement();

useEffect(() => {
fetchFeatures(tenantId, 'T');
}, [tenantId]);

const handleToggle = (featureName: string) => {
const current = isFeatureEnabled(featureName);
updateFeatureValue(featureName, current ? 'false' : 'true');
};

const handleSave = async () => {
const result = await saveFeatures(tenantId, 'T');
if (result.success) {
console.log('Saved!');
}
};

if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;

return (
<div>
{features.map((feature) => (
<div key={feature.name}>
<label>
<input
type="checkbox"
checked={isFeatureEnabled(feature.name)}
onChange={() => handleToggle(feature.name)}
/>
{feature.name}
</label>
</div>
))}
<button onClick={handleSave}>Save</button>
</div>
);
}

Hook API Reference

useFeatureManagement Returns

PropertyTypeDescription
featuresFeature[]Array of features
featureValuesRecord<string, string>Current feature values
isLoadingbooleanLoading state
errorstring | nullError message if any
fetchFeatures(key, name) => PromiseFetch features from server
saveFeatures(key, name) => PromiseSave features to server
updateFeatureValue(name, value) => voidUpdate feature value locally
getFeatureValue(name) => stringGet current feature value
isFeatureEnabled(name) => booleanCheck if toggle feature is enabled
reset() => voidReset all state

Feature Value Types

The modal automatically renders the appropriate input based on the feature's value type:

Value TypeInputDescription
ToggleStringValueTypeCheckboxBoolean on/off features
FreeTextStringValueTypeText inputFree text input features
DefaultText inputAny other type

Integration Example

Here's a complete example integrating feature management into a tenant management page:

import { useState } from 'react';
import { usePermission } from '@abpjs/core';
import { FeatureManagementModal } from '@abpjs/feature-management';

interface Tenant {
id: string;
name: string;
}

function TenantTable({ tenants }: { tenants: Tenant[] }) {
const [selectedTenant, setSelectedTenant] = useState<Tenant | null>(null);
const [showFeatures, setShowFeatures] = useState(false);
const { hasPermission } = usePermission();

const canManageFeatures = hasPermission(
'AbpTenantManagement.Tenants.ManageFeatures'
);

const openFeatures = (tenant: Tenant) => {
setSelectedTenant(tenant);
setShowFeatures(true);
};

return (
<>
<table>
<thead>
<tr>
<th>Name</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{tenants.map((tenant) => (
<tr key={tenant.id}>
<td>{tenant.name}</td>
<td>
{canManageFeatures && (
<button onClick={() => openFeatures(tenant)}>
Features
</button>
)}
</td>
</tr>
))}
</tbody>
</table>

{selectedTenant && (
<FeatureManagementModal
providerName="T"
providerKey={selectedTenant.id}
visible={showFeatures}
onVisibleChange={setShowFeatures}
onSave={() => {
console.log(`Features saved for ${selectedTenant.name}`);
}}
/>
)}
</>
);
}