Topic: Accordion not opening firstItem after API call
Declan Ward priority asked 11 months ago
Expected behavior
First item opens
Actual behavior
Does not open after data retrieved from API call.However, if test data loaded locally, the first item does open.
I suspect a timing issue or am I missing something simple? Why would one work and not the other?
Any help appreciated.
Resources (screenshots, code snippets etc.)
ngOnInit() {
// Load data locally
this.addDocTypes();
// Load data from API
this.refreshDocuments();
}
ngAfterViewInit(){
this.firstItem.show();
// Needed this to prevent error
this.cdr.detectChanges();
}
Loading data locally:
addDocTypes(){
this.localDocTypes.push({ DocumentCount:2, Description: 'Payslip', NumberNotViewed:0,
Documents:[
{
DocCreated: '2020-02-10T10:11:27',
DocFileName: 'Payslip-Period__5.pdf',
DocId: '2864453',
DocLength: '45883',
DocTypeDescr: 'Payslip',
DocURL: 'https://someserver.com/docserver.ashx?file=00028644535',
DocViewed: '11/9/2023 7:55:47 PM'
},
{
DocCreated: '2019-07-17T10:17:35',
DocFileName: 'Payslip-Period__6.pdf',
DocId: '2516617',
DocLength: '45883',
DocTypeDescr: 'Payslip',
DocURL: 'https://someserver.com/docserver.ashx?file=00025166170',
DocViewed: '3/8/2021 5:29:52 PM'
}
]
});
this.localDocTypes.push({ DocumentCount: 2, Description: 'P60', NumberNotViewed: 0,
Documents:[
{
DocCreated: '2020-03-27T12:43:54',
DocFileName: 'P60-2016.pdf',
DocId: '2965144',
DocLength: '126317',
DocTypeDescr: 'P60',
DocURL: 'https://someserver.com/docserver.ashx?file=00029651',
DocViewed: '11/10/2023 2:58:00 PM'
},
{
DocCreated: '2019-04-05T10:06:22',
DocFileName: 'P60-2017.pdf',
DocId: '2323834',
DocLength: '126317',
DocTypeDescr: 'P60',
DocURL: 'https://someserver.com/docserver.ashx?file=00023238301',
DocViewed: '11/9/2023 3:18:46 PM'
}
]
});
}
Loading data from API
this.docGuestService.getUserDocuments()
.subscribe(
{
next: (response) => {
// Normally set docTypes directly from API
this.docTypes = response;
// Trying to build object with data from API
// Just in case something is different!
// this.docTypes = [];
// response.forEach(element => {
// // Clear list of UserDocuments first
// this.userDocuments = [];
// // Add documents
// element.Documents.forEach(doc =>{
// this.userDocuments.push({
// DocCreated: doc.DocCreated,
// DocFileName: doc.DocFileName,
// DocId: doc.DocId,
// DocLength: doc.DocLength,
// DocTypeDescr: doc.DocTypeDescr,
// DocURL: doc.DocURL,
// DocViewed: doc.DocViewed
// })
// })
// // Add complete item & documents
// this.docTypes.push({
// DocumentCount: element.DocumentCount,
// Description: element.Description,
// NumberNotViewed: element.NumberNotViewed,
// Documents: this.userDocuments
// });
// });
},
error:(e) => {
this.IsError = true;
this.alertService.error(e.error, {
autoClose: false,
keepAfterRouteChange: false
});
},
complete: () =>{
this.loading = false;
}
}
Service to get data:
getUserDocuments(): Observable<DocumentType[]> {
return this.http.get<DocumentType[]>(this._urlBase + 'DocViewer/g');
}
Interface
DocumentType interface
export interface DocumentType{
// Description of the current document type
Description: string;
// Number of documents for the document type (description)
DocumentCount: number;
// Number of documents NotViewed for the document type (description)
NumberNotViewed: number;
// User Documents for the above document Type (Description)
Documents: BaseDocument[];
}
HTML - identical for each accordion except
API data
*ngFor="let docType of docTypes"
Locally loaded data
*ngFor="let docType of localDocTypes"
Defined
// Interfaces
// From API
docTypes: DocumentType[] = [];
userDocuments: UserDocument[] = [];
// Generated locally
localDocTypes:DocumentType[] = [];
Actual HTML
<mdb-accordion
[flush]="true"
[multiple]="false">
<mdb-accordion-item
[collapsed]="true"
*ngFor="let docType of localDocTypes"
#firstItem
>
<ng-template mdbAccordionItemHeader>
<div>
<fa-icon class="icon" [icon]="faFilePdf"></fa-icon>
{{docType.Description}}
{{docType.DocumentCount}} ({{docType.NumberNotViewed}})
</div>
</ng-template>
<ng-template mdbAccordionItemBody>
<div class="datatable">
<table
class="table datatable-table "
mdbTable
#table="mdbTable"
[dataSource]="docType.Documents"
striped="true"
sm="true">
<thead class="datatable-header">
<tr>
<div class="row">
<div class="col">File Name</div>
<div class="col" style="text-align:right;">Size</div>
<div class="col" style="text-align:right;">Date</div>
</div>
</tr>
</thead>
<tbody class="datatable-body">
<tr *ngFor="let doc of table.data" scope="row" >
<td>
<a href="{{doc.DocURL}}" download >
<div class="row">
<div class="col">
<span class="viewed" *ngIf="doc.DocViewed !=''">Viewed</span>
<span class="notviewed" *ngIf="doc.DocViewed ===''">Not Viewed</span>
</div>
<div class="col" style="text-align:right;">
{{doc.DocLength}}
</div>
<div class="col" style="text-align:right;">
{{ doc.DocCreated | date:'dd MMM yyyy' }}
</div>
</div>
<div class="row">
<div class="col wraptext">{{doc.DocFileName}}</div>
</div>
</a>
</td>
</tr>
</tbody>
</table>
</div>
</ng-template>
</mdb-accordion-item>
</mdb-accordion>
Rafał Seifert free answered 11 months ago
You are rendering accordion items through *ngFor directive. At the beginning there is no data so items will not render. Therefore you will not be able to open them in ngAfterViewInit(), you should also see an error in console that items are not defined. To fix this issue I would suggest to add opening logic in callback function where you receive data from API call. It would look like this in your example. You should also wrap it in setTimeout as the items won't be rendered immediately after updating local data.
this.docGuestService.getUserDocuments()
.subscribe(
{
next: (response) => {
// Normally set docTypes directly from API
this.docTypes = response;
setTimeout(() => {
this.firstItem.show();
}, 0);
Declan Ward priority commented 11 months ago
Hi Rafal,
Yes you are correct, there was an error stating firstItem undefined.
Your solution above is perfect, thank you.
Regards, Declan
FREE CONSULTATION
Hire our experts to build a dedicated project. We'll analyze your business requirements, for free.
Resolved
- ForumUser: Priority
- Premium support: Yes
- Technology: MDB Angular
- MDB Version: MDB5 5.1.0
- Device: All
- Browser: All
- OS: Windows
- Provided sample code: No
- Provided link: No