Activities of "dcsimoes"

Use PreContribute to fill OriginalValue for VO-derived members from ABP’s scalar PropertyChanges: PreContribute is not bringing any EntityChanges on the context. More assistance required.

Description When implementing a custom IAuditLogContributor to support audit logging of ValueObjects, we discovered that the ABP Framework does not provide the correct InternalEntity on OriginalValues during the audit logging process while the NewValue is resolved correctly, the InternalEntity for original values is already overwritten by the time the contributor executes. All EF Core sources that should expose the previous state (e.g., EntityEntry.OriginalValues) already reflect the new value.

Technical Context

[AttributeUsage(AttributeTargets.Property)]
public class EntityChangeTrackedValueObjectAttribute : Attribute
{
    public string MemberName { get; }
    public bool IsMethod { get; }

    public EntityChangeTrackedValueObjectAttribute(string memberName, bool isMethod = true)
    {
        MemberName = memberName;
        IsMethod = isMethod;
    }
}

*Custom AuditLogContributor* - Implemented so newValue is fetched

public override void PostContribute(AuditLogContributionContext context)
{
     if (context?.AuditInfo?.EntityChanges == null)
     {
         base.PostContribute(context);
         return;
     }
    
     foreach (var entityChange in context.AuditInfo.EntityChanges)
     {
         if (entityChange?.PropertyChanges == null) continue;
    
         var entityTypeFullName = entityChange.EntityTypeFullName;
         var entityTypeName = entityChange.EntityTypeFullName?.Split('.').LastOrDefault()?.Trim();
    
         foreach (var propertyChange in entityChange.PropertyChanges)
         {
             if (propertyChange == null) continue;
    
             var propertyPath = propertyChange.PropertyName ?? string.Empty;
             if (string.IsNullOrWhiteSpace(propertyPath)) continue;
    
             var propertyLast = propertyPath.Split('.').Last();
    
             if (!string.IsNullOrEmpty(propertyChange.NewValue))
                 continue;
    
             if (!string.IsNullOrEmpty(entityTypeName) &&
                 VoTrackedPropertyCache.TryGet(entityTypeName, propertyLast, out var voType, out var memberName, out var isMethod, out var declaringType))
             {
                 var entryWrapper = entityChange.EntityEntry;
                 var wrapperType = entryWrapper.GetType();
    
                 object newResult = null;
                 var entityProp = wrapperType.GetProperty("Entity");
                 var currentEntity = entityProp?.GetValue(entryWrapper);
    
                 if (currentEntity != null && declaringType.IsInstanceOfType(currentEntity))
                 {
                     var voProp = declaringType.GetProperty(propertyLast);
                     var currentVoInstance = voProp?.GetValue(currentEntity);
    
                     if (currentVoInstance != null)
                     {
                         newResult = GetResultFromVo(currentVoInstance, voType, memberName, isMethod);
                     }
                 }
    
                 if (newResult != null)
                 {
                     propertyChange.NewValue = newResult.ToString();
                     propertyChange.PropertyTypeFullName = "System.String";
                 }
         }
      }
  }
}

Observed Behavior

During the PostContribute phase, we attempted to retrieve the old values from: entityChange.EntityEntry, without success beecause all InternalEntities already ahd the new values.

Expected Behavior ABP should expose the actual original value of the Value Object within the audit context, when accessing the InternalEntity of a change.

So, we want to know if there is already in the framework a way to handle value objects obtaining similar results without using our implementation, and, if not, if you can provide a solution so we can use this aproach also for OriginalValues.

Thanks in advance

Hello. I was able to achieve it this way

/// Custom Menu Filter Component
/// IS TEMPORARY - TO BE REMOVED WHEN FIXED IN FUTURE RELEASE: https://abp.io/support/questions?sort=LastActivityDate-desc&creatorUserId=3a10d34c-87a0-a3f1-8e50-72cd7b2a718f&hidepinnedQuestions=True
@Component({
  selector: 'app-custom-menu-filter',
  imports: [CommonModule, FormsModule, LocalizationPipe],
  standalone: true,
  template: `
    <div class="lpx-menu-filter">
      <i class="bi bi-funnel menu-filter-icon"></i>
      <!-- TODO: PROVIDE API -->
      <input
        class="menu-filter-input hidden-in-hover-trigger"
        type="text"
        [(ngModel)]="service.menuFilter"
        [placeholder]="menuFilterText | abpLocalization"
      />
      <span
        (click)="service.clearFilter()"
        class="menu-filter-clear hidden-in-hover-trigger"
        [class.hidden]="!service.menuFilter"
      >
        <i class="bi bi-x clear-icon"></i>
      </span>
    </div>
  `,
})
export class CustomMenuFilterComponent extends MenuFilterComponent {
  override menuFilterText = 'LeptonX::FilterMenu' as SideMenuLayoutTranslate;
}

app.config.ts:

{
      provide: CONTENT_BEFORE_ROUTES,
      useValue: [CustomMenuFilterComponent],
      multi: true,
    },
lpx-menu-filter {
  display: none !important;
  }

sincelpx-menu-filter is not an ReplaceableComponent. If you can share a better wayu to achieve this I would appreciate it. Also I'll be waiting for feedback for when this issue is solved

Thanks, David Simões

Can you exemplify?

It is on angular and is page agnostic, it's on the sidebar layout

The text already exists on localization

Hello. I'm being unable to localize the filter menu's text on Filter Menu, is this a known issue or am I missing something?

The provided solution by @AI-Bot is not suficient

When ngx-datatable is in a loading state (initial load, sort, or external paging), the built-in loading/scroll indicator () is rendered outside the . As a result: The spinner/indicator appears below/above the table instead of centered inside the rows area. In some cases the “No data to display” label is still shown while loading.

Steps to Reproduce Create a simple page using ABP Extensible Table with externalPaging/externalSorting wired to an async ListService. Trigger a page change or sort so that the table enters loading state.

Observe the DOM: is appended as a sibling to (or otherwise outside the body/viewport), not inside it. Visually, the spinner sits outside the rows area;

Also when the number of results is still being calculated it display the text "NaN" instead of 0 as in previous versions

Yes. It is. I've solved it on my current implementation using datatable.recalculateColumns(). Is there a issue open on github?

Showing 1 to 10 of 21 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.1.0-preview. Updated on December 10, 2025, 12:02
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.