Activities of "dcsimoes"

The issues provided from @AI-Bot are not related to the current ticket.

After upgrading our Angular front-end to Angular 20 (using ABP Commercial 9.3.1), we started seeing a layout issue with abp-extensible-table. In Firefox everything renders correctly. In Chromium browsers (Chrome/Edge), the table headers do not align/adjust on initial render. They only fix themselves after interacting with the table (e.g. focusing, resizing, or triggering a redraw).

Steps to Reproduce Create a clean Angular 20 + ABP project. Add a simple abp-extensible-table with a few columns. Run in Chrome/Edge.

Observed Behavior On first load the header widths are misaligned or do not adjust to fit. After clicking inside the table or triggering focus, headers snap into place.

Expected Behavior Table headers and body columns should align correctly on first render in Chromium, same as in Firefox.

Current Workaround We currently use our own extended implementation of abp-extensible-table in some modules. As a temporary fix, we replaced it and forced ngx-datatable-column.canAutoResize = false. Our implementation is very similar to the ABP one, with just a few additions.

Description When using the Organization Units management UI from @volo/abp.ng.identity, the edit modal template throws an error if opened without first selecting a unit from the tree.

Error

java
Copiar
Editar
core.mjs:6720 ERROR TypeError: Cannot read properties of undefined (reading 'displayName')
    at OrganizationUnitsComponent_ng_template_6_Conditional_1_Template (volo-abp.ng.identity.mjs:94:103)
    at executeTemplate (core.mjs:12429:9)
    at refreshView (core.mjs:14114:13)
    at detectChangesInView (core.mjs:14334:9)
    at detectChangesInViewIfAttached (core.mjs:14294:5)
    at detectChangesInEmbeddedViews (core.mjs:14251:13)
    at refreshView (core.mjs:14143:9)
    at detectChangesInView (core.mjs:14334:9)
    at detectChangesInViewIfAttached (core.mjs:14294:5)
    at detectChangesInEmbeddedViews (core.mjs:14251:13)
The error keeps appearing in a loop during change detection.

Steps to Reproduce Create an ABP Angular application with the Identity Management module enabled.

Navigate to Identity > Organization Units.

Without selecting any node, right-click an organization unit in the tree and choose Edit.

Check the browser console.

Expected Behavior The edit modal should open without errors, even if no unit was pre-selected.

Additional Details This issue does not occur if you first select a node in the tree and then open the edit modal.

Hello ABP Team,

I am working with ABP extensible forms, and I’m using a custom template/component to override the rendering of certain fields via the [templates] property on <abp-extensible-form>. My custom component injects the field config and record data using:

constructor(
  @Inject(EXTENSIONS_FORM_PROP) public prop: FormProp,
  @Inject(EXTENSIONS_FORM_PROP_DATA) public propData: any
) {}

My issue/question:

  • When using the default ABP rendering, the options function for typeahead and other extensible fields receives a rich PropData object (with record and sometimes helpers like getInjected).
  • However, in my custom template component, propData is just the record (row/entity) and does not include any extra context or helper functions.
  • This means that my field’s options function has less information than it does in the default scenario.

Questions:

  1. Is there a supported way to access the full PropData (with helpers and full context) inside a custom template/component (e.g., for use in options or validators)?
  2. Is it possible to have EXTENSIONS_FORM_PROP_DATA provide the full context instead of only the record when using template overrides?
  3. If not, is there a recommended pattern to pass additional context to custom field templates, so options/validators can use other injected services or helpers as in the default renderer?
  4. Are there plans to support this use-case in a future version?

Any best practices, workarounds, or guidance would be greatly appreciated.

Thank you!


@Component({
  selector: 'custom-typeahead-field',
  template: ` ... `
})
export class CustomTypeaheadFieldComponent {
  constructor(
    @Inject(EXTENSIONS_FORM_PROP) public prop: FormProp,
    @Inject(EXTENSIONS_FORM_PROP_DATA) public propData: any
  ) {}
  // ...
  
    search = (params: PagedAndSortedResultRequestDto): Observable<PagedResultDto<any>> => {
        if (this.prop?.options) {
          return this.prop.options(this.propData, params).pipe(
            switchMap((result: any) => {
              if (Array.isArray(result)) {
                return of({ items: result, totalCount: result.length });
              }
              return of(result);
            })
          );
        }
        return of({ items: [], totalCount: 0 });
      };
}
  {
    type: ePropType.Typeahead,
    name: 'propId',
    displayName: 'propName',
    validators: () => [],
    options: (data$, params) => {
      const manufacturerService = data$.getInjected(MyService);
      return myService
        .getList({
          filter: params ?? '',
          maxResultCount: params?.maxResultCount,
          skipCount: params?.skipCount,
        })
        .pipe(
          map(result => {
            //add empty value
            return result.items.map(item => ({ value: item.id, key: item.name }));
          })
        );
    },
    template: MyWrapperComponent,
  },

**ERROR TypeError: data$.getInjected is not a function**


Thank you, David Simões


We have analyzed the source code for ExtensibleTableComponent (specifically the ngOnChanges method where the injector for *ngComponentOutlet is created). We found that the injector provided to the custom component only includes a provider for the PROP_DATA_STREAM token. This token provides anObservable<string> representing the formatted display value of the cell, not the raw record object for the row.

(Reference: ExtensibleTableComponent.ts -> ngOnChanges -> Injector.create({...}) block

// Snippet from ExtensibleTableComponent.ts showing the limited injector creation
if (prop.value.component) {
  record[propKey].injector = Injector.create({
    providers: [
      {
        provide: PROP_DATA_STREAM, // Only provides formatted value stream
        useValue: value,           // 'value' is Observable<string> from getContent
      },
      // PROBLEM: Missing provider for the 'record' object or a context token
    ],
    parent: this.#injector,
  });
  record[propKey].component = prop.value.component;
}

Impact: Because the record data is not injected, custom components rendered via the component property cannot access the row-specific data they need to function correctly. This prevents the creation of interactive cell components that depend on row context.

Enhancement Request:

Could the ExtensibleTableComponent be enhanced to provide the row record object (or a context object containing it) to custom components via the injector? The standard approach would be to use a documented InjectionToken (e.g., ROW_RECORD, COMPONENT_CONTEXT, or similar) for this purpose.

// Example of desired injector enhancement
Injector.create({
  providers: [
    { provide: PROP_DATA_STREAM, useValue: value },
    { provide: ROW_RECORD, useValue: record } // <-- Requesting this
  ],
  parent: this.#injector,
});

This would allow developers to build stateful, interactive components that integrate properly with the table row data, significantly enhancing the extensibility of the table.

I've created an issue on ABP repository regarding this situation: https://github.com/abpframework/abp/issues/22555

We also observed some difficulty in reliably setting very narrow fixed column widths (e.g., 10-30px) using columnWidth when a custom component is rendered, although wider widths seem to apply correctly. This might be a separate minor issue related to CSS or internal calculations.

What if I need the checkbox to appear before the actions column?

Sorry for insisting on this matter, but I still couldn't understand how to achieve that.

Can you give an example for CustomMultiSelectComponent?

I'm working with the abp-extensible-table component and have a requirement to allow users to select multiple lines from it within a specific column. Currently, it seems like it doesn't support it.

Could you please provide guidance or suggest a way to implement a multi-select within a column of the abp-extensible-table? Any examples or best practices for achieving this would be greatly appreciated.

Hello, thank you for reporting this issue.
However, I am unable to see your HTML code properly. Could you please resend it?

Hi. I updated the question with the HTML code.

Showing 11 to 20 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 17, 2025, 07:08
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.