1

I am loading some mat-tabs dynamically via a promise, but the mat-tab does not show the arrows to move when necessary.

enter image description here

but when clicking on a tap if they already show correctly

enter image description here

My code looks like this

import { CsmEmployerEntity } from '@addons/casemanager/main/graphql/interfaces/generalcase.interfaces';
import {
    ChangeDetectionStrategy,
    ChangeDetectorRef,
    Component,
    Input,
    OnInit,
    ViewEncapsulation,
} from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { MatTabChangeEvent } from '@angular/material/tabs';
import { CaseManagerService } from '../../casemanager.service';
import { CsmCaseContact } from '../../graphql/interfaces';
import { ContactService } from '../../services/contact.service';
import { EmployerService } from '../../services/employer.service';
import { AddContactModalComponent } from './modal/add-contact-modal.component';
    
@Component({
    selector: 'contacts',
    templateUrl: './contacts.component.html',
    encapsulation: ViewEncapsulation.None,
    changeDetection: ChangeDetectionStrategy.OnPush,
})

export class ContactsComponent implements OnInit {
    @Input()
    caseId: string;
    // Contains the data of the Contacts
    contacts: CsmCaseContact[] = [];
    employers: CsmEmployerEntity[] = [];
    selectedIndex = 0;
    
    constructor(
        public dialog: MatDialog,
        private _contactService: ContactService,
        private _changeDetectorRef: ChangeDetectorRef,
        private _caseManagerService: CaseManagerService,
        private _employerService: EmployerService
    ) {}
    
    ngOnInit(): void{
        this.loadContacts();
        this.loadEmployers();
        this.loadStates();
        console.log('contacts', this.contacts.length);
    }
    
    openSelectContactsModal(): void {
        const dialogRef = this.dialog.open(AddContactModalComponent, {
            width: '550px',
            autoFocus: false,
            data: {
                currentContacts: this.contacts.map(
                    contact => contact.csm_contact.id
                ),
                caseId: this.caseId,
            },
        });

        dialogRef.afterClosed().subscribe((result) => {
            if (result) {
                this.refreshData('move-last');
            }
        });
    }
    
    removeContact(contactId: string): void {
        if (confirm('This action will unbind this contact from the selected current case') === true) {
            this._contactService
                .removeContactRelatedToCase(contactId, this.caseId)
                .then(() => {
                    this.contacts = this.contacts.filter(
                        contact => contact.csm_contact.id !== contactId
                    );
                })
                .catch(() => {
                    alert('can\'t remove this contact');
                });
        }
    }
    
    refreshData(action: string): void {
        this.loadContacts();
        if(action === 'move-first'){
            this.selectedIndex = 0;
            this._changeDetectorRef.markForCheck();
        }
    }
    
    loadContacts(): void {
         this._contactService
            .getContactsByCase(this.caseId)
            .then((contacts: CsmCaseContact[]) => {
                this.contacts = this.contacts.length ? [] : this.contacts;
                this.contacts = contacts;
                this._changeDetectorRef.markForCheck();
            })
            .catch(() => {
                alert('Error while retriving contacts');
            });
    }
    
    loadEmployers(): void {
        this._employerService
            .getEmployersByCaseID(this.caseId)
            .then(() => {
                this._changeDetectorRef.markForCheck();
             })
            .catch(() => {
                alert('Error while retriving Employers');
            });
    }
    
    loadStates(): void {
        this._caseManagerService.getCsmStatesCatalog(
            0,
            null,
            'name',
            'desc',
            ''
        );
    }
    
    onTabChanged(data: MatTabChangeEvent): void {
        this.selectedIndex = data.index;
    }
}

The loadContacts method is the one that brings the information that I use to render the data and I call it in the ngOninit

but in the console.log I see that this value is 0, I suppose that possibly that is the problem.

My component HTML

<section>
    <ng-container *ngIf="contacts.length && contacts.length > 0">
        <mat-tab-group [selectedIndex]="selectedIndex" (selectedTabChange)="onTabChanged($event)" class="businesstabs bg-white">
            <mat-tab *ngFor="let contact of contacts ; let i = index">
                <ng-template mat-tab-label>
                    <button mat-icon-button (click)="removeContact(contact.csm_contact.id)">
                        <mat-icon class="hover:text-red-600">cancel</mat-icon>
                    </button>
                    <span> {{ contact.csm_contact.name }}</span>
                </ng-template>
                <contact-form [contact]="contact" [caseId]="caseId" (refreshEvent)="refreshData($event)"></contact-form>
            </mat-tab>
        </mat-tab-group>
    </ng-container>
    
    <ng-container *ngIf="!contacts.length">
        <div class="bg-indigo-100 border-l-4 border-indigo-500 text-indigo-700 p-4 mt-3" role="alert">
            <p class="font-bold">Not contact yet</p>
            <p>you can add contacts using the button above.</p>
        </div>
    </ng-container>
</section>

and the service method:

getContactsByCase(
    id: string,
    policy: WatchQueryFetchPolicy = 'network-only'
): Promise<CsmCaseContact[]> {
    return new Promise((resolve, reject) => {
        const optionalContext = null;
        const query = GetContactByCaseId;
        const vars = {
            case_id: id,
        };
            
        this._queryHostService
            .getQueryResults(query, vars, optionalContext, policy)
            .then((response) => {
                const csmContacts: CsmCaseContact[] = response.csm_case_contact;
                console.log('evento disparado');
                this._contacts.next(csmContacts);
                resolve(csmContacts);
            })
            .catch((error) => {
                const gError = {
                    origin: 'getContactsByCase',
                    error,
                };
                this.onGraphQLError(gError);
                reject(error);
            });
    });
}
Jose Lora
  • 1,392
  • 4
  • 12
  • 18
  • I forgot to mention that I have the encapsulation setting: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, – Gerardo Guevara Dec 30 '21 at 15:20
  • I'm not sure, but it think as you click on the tab, the change detection is triggered again, this is why after the click the arrow is displayed. It might be kind of a timing issue, the change detection might needed to be triggered later than `contacts` update. To try this idea, please try to add a `setTimeout` with a `markForCheck` when the `loadContacts` Promise is resolved. (This is of course about getting an idea about the problem, the `setTimeout` is not the right solution.) – Milan Tenk Jan 08 '22 at 09:57

0 Answers0