Activities of "eric_cto"

Feature Management modal (Angular): parent/child toggle cascade does nothing when the group display name differs from the group name

ABP Framework version: 10.6.0. The code is unchanged in 10.6.1 and 10.7.0-rc.5. UI type: Angular (@abp/ng.feature-management) Database provider: EF Core (PostgreSQL) Tiered (for MVC) or Auth Server separated (for Angular): no Exception message and full stack trace: none. This is a silent logic error.

Steps to reproduce

  1. Define a feature group whose localized display name differs from its name, with a toggle feature and a child toggle:

    var group = context.AddGroup("Clubs", L("Feature:Clubs")); // localized as "Clubes" in Spanish
    var parent = group.AddFeature("Clubs.Enabled", "false", valueType: new ToggleStringValueType());
    parent.CreateChild("Clubs.Members", "false", valueType: new ToggleStringValueType());
    
  2. Switch the UI language to one where the display name is translated (for example Spanish, so "Clubs" becomes "Clubes").

  3. Open Saas > Tenants > Features for any tenant and select the "Clubes" tab.

  4. Check the child Clubs.Members.

Expected

Checking the child also checks its parent, and unchecking the parent unchecks its children (checkToggleAncestors / uncheckToggleDescendants).

Actual

Only the clicked checkbox changes. A child can be saved as enabled while its parent is disabled.

With an English UI, where the display name "Clubs" equals the name, the cascade works.

Root cause

In FeatureManagementComponent, features() is keyed by the group name:

this.features.set(res.groups.reduce((acc, val) => ({
    ...acc,
    [val.name]: mapFeatures(val.features, this.document.body?.dir),
}), {}));

The template also reads it by name (features()[group.name]). But getCurrentGroup(), which findParentByType and findChildrenByType use, indexes it by the selected display name:

getCurrentGroup() {
    const selectedGroup = this.selectedGroupDisplayName();
    return selectedGroup ? this.features()[selectedGroup] ?? [] : [];
}

When the display name differs from the name, this returns [], so no parent or children are ever found. The tabs use group.displayName as their value, which is probably how the mismatch was introduced.

Suggested fix

getCurrentGroup() {
    const group = this.groups().find(g => g.displayName === this.selectedGroupDisplayName());
    return group ? this.features()[group.name] ?? [] : [];
}

A cleaner option is to use group.name as the tab value and keep the display name only for rendering. That also avoids clashes when two groups share a display name.

Showing 1 to 1 of 1 entries
Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.8.0-preview. Updated on October 06, 2026, 12:23
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.