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
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:
PropData
object (with record
and sometimes helpers like getInjected
).propData
is just the record (row/entity) and does not include any extra context or helper functions.options
function has less information than it does in the default scenario.Questions:
PropData
(with helpers and full context) inside a custom template/component (e.g., for use in options or validators)?EXTENSIONS_FORM_PROP_DATA
provide the full context instead of only the record
when using template overrides?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
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.
Created an component with the following HTML using abp-extensible-form:
<ng-template #abpBody>
<ng-template #loaderRef>
<div class="text-center"><i class="fa fa-pulse fa-spinner"></i></div>
</ng-template>
<form [formGroup]="form" (ngSubmit)="save()" [validateOnSubmit]="true">
<abp-extensible-form [selectedRecord]="selected"></abp-extensible-form>
</form>
</ng-template>
And with the following typeahead defined on defaults:
{
type: ePropType.Typeahead,
name: 'myProp',
id: 'myProp',
displayName: '::MyField',
validators: () => [Validators.required],
options: (data, params) => {
const service = data.getInjected(MyService);
return service
.getList({
filter: params ?? '',
maxResultCount: params?.maxResultCount,
skipCount: params?.skipCount,
} as MyInput)
.pipe(
map(pagedResult => {
return pagedResult.items.map(
item =>
({
key: item.displayName,
value: item.id,
})
);
})
);
},
}
When creating a new record everything works fine, but when I patch a value to the form wich contains myProp
correctly defined and with a valid value the typeahead component don't autofill that value, even when trying to force it through form. I don't have this problem with abp-lookup-typeahead
components in forms created manually through HTML.
Here's my buildform method
buildForm() { const data = new FormPropData(this.injector, this.selected); this.form = generateFormFromProps(data); }
Thanks in advance for any help provided.