MOBILE-4616 feedback: Fix tab selection after submit form

main
Pau Ferrer Ocaña 2024-10-15 14:54:05 +02:00
parent ce7243b1ae
commit 95756b5c13
9 changed files with 130 additions and 88 deletions

View File

@ -20,20 +20,13 @@
[courseId]="courseId" [hasDataToSync]="hasOffline" (completionChanged)="onCompletionChange()" />
<core-tabs [hideUntil]="tabsReady" [selectedIndex]="firstSelectedTab">
<core-tab [title]="'addon.mod_feedback.overview' | translate" id="overview" (ionSelect)="tabChanged('overview')">
<core-tab [title]="tabs.overview.label | translate" [id]="tabs.overview.name" (ionSelect)="tabChanged(tabs.overview.name)">
<ng-template>
<ng-container *ngTemplateOutlet="tabOverview" />
</ng-template>
</core-tab>
<core-tab *ngIf="showAnalysis && access && access.canviewreports" id="analysis" [title]="'addon.mod_feedback.analysis' | translate"
(ionSelect)="tabChanged('analysis')">
<ng-template>
<ng-container *ngTemplateOutlet="tabAnalysis" />
</ng-template>
</core-tab>
<core-tab *ngIf="showAnalysis && access && !access.canviewreports" id="analysis"
[title]="'addon.mod_feedback.completed_feedbacks' | translate" (ionSelect)="tabChanged('analysis')">
<core-tab *ngIf="showAnalysis && access" [id]="tabs.analysis.name" [title]="tabs.analysis.label | translate"
(ionSelect)="tabChanged(tabs.analysis.name)">
<ng-template>
<ng-container *ngTemplateOutlet="tabAnalysis" />
</ng-template>
@ -101,7 +94,7 @@
<!-- Template to render the overview. -->
<ng-template #tabOverview>
<core-loading [hideUntil]="tabsLoaded.overview">
<core-loading [hideUntil]="tabs.overview.loaded">
<ng-container *ngTemplateOutlet="basicInfo" />
<ion-card class="core-info-card" *ngIf="access && access.cancomplete && !access.isopen">
@ -153,7 +146,7 @@
<!-- Template to render the analysis. -->
<ng-template #tabAnalysis>
<core-loading [hideUntil]="tabsLoaded.analysis">
<core-loading [hideUntil]="tabs.analysis.loaded">
<ng-container *ngTemplateOutlet="basicInfo" />
<ng-container *ngIf="access && (access.canedititems || !access.isempty)">

View File

@ -38,7 +38,12 @@ import {
AddonModFeedbackSyncResult,
} from '../../services/feedback-sync';
import { AddonModFeedbackPrefetchHandler } from '../../services/handlers/prefetch';
import { ADDON_MOD_FEEDBACK_COMPONENT, ADDON_MOD_FEEDBACK_FORM_SUBMITTED, ADDON_MOD_FEEDBACK_PAGE_NAME } from '../../constants';
import {
ADDON_MOD_FEEDBACK_COMPONENT,
ADDON_MOD_FEEDBACK_FORM_SUBMITTED,
ADDON_MOD_FEEDBACK_PAGE_NAME,
AddonModFeedbackIndexTabName,
} from '../../constants';
/**
* Component that displays a feedback index page.
@ -51,7 +56,7 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity
@ViewChild(CoreTabsComponent) tabsComponent?: CoreTabsComponent;
@Input() tab = 'overview';
@Input() selectedTab: AddonModFeedbackIndexTabName = AddonModFeedbackIndexTabName.OVERVIEW;
@Input() group = 0;
component = ADDON_MOD_FEEDBACK_COMPONENT;
@ -75,9 +80,9 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity
closeTimeReadable: '',
};
tabsLoaded = {
overview: false,
analysis: false,
tabs = {
overview: { name: AddonModFeedbackIndexTabName.OVERVIEW, label: 'addon.mod_feedback.overview', loaded: false },
analysis: { name: AddonModFeedbackIndexTabName.ANALYSIS, label: 'addon.mod_feedback.analysis', loaded: false },
};
protected submitObserver: CoreEventObserver;
@ -92,12 +97,12 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity
// Listen for form submit events.
this.submitObserver = CoreEvents.on(ADDON_MOD_FEEDBACK_FORM_SUBMITTED, async (data) => {
if (!this.feedback || data.feedbackId != this.feedback.id) {
if (!this.feedback || data.feedbackId !== this.feedback.id) {
return;
}
this.tabsLoaded.analysis = false;
this.tabsLoaded.overview = false;
this.tabs.analysis.loaded = false;
this.tabs.overview.loaded = false;
this.showLoading = true;
// Prefetch data if needed.
@ -110,7 +115,7 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity
}
// Load the right tab.
if (data.tab != this.tab) {
if (data.tab !== this.selectedTab) {
this.tabChanged(data.tab);
} else {
this.loadContent(true);
@ -149,7 +154,9 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity
*/
protected callAnalyticsLogEvent(): void {
this.analyticsLogEvent('mod_feedback_view_feedback', {
url: this.tab === 'analysis' ? `/mod/feedback/analysis.php?id=${this.module.id}` : undefined,
url: this.selectedTab === AddonModFeedbackIndexTabName.ANALYSIS
? `/mod/feedback/analysis.php?id=${this.module.id}`
: undefined,
});
}
@ -168,8 +175,8 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity
promises.push(AddonModFeedback.invalidateResumePageData(this.feedback.id));
}
this.tabsLoaded.analysis = false;
this.tabsLoaded.overview = false;
this.tabs.analysis.loaded = false;
this.tabs.overview.loaded = false;
await Promise.all(promises);
}
@ -178,7 +185,7 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity
* @inheritdoc
*/
protected isRefreshSyncNeeded(syncEventData: AddonModFeedbackAutoSyncData): boolean {
if (this.feedback && syncEventData.feedbackId == this.feedback.id) {
if (syncEventData.feedbackId === this.feedback?.id) {
// Refresh the data.
this.content?.scrollToTop();
@ -207,12 +214,17 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity
this.access = await AddonModFeedback.getFeedbackAccessInformation(this.feedback.id, { cmId: this.module.id });
this.showAnalysis = (this.access.canviewreports || this.access.canviewanalysis) && !this.access.isempty;
this.tabs.analysis.label = this.access.canviewreports
? 'addon.mod_feedback.analysis'
: 'addon.mod_feedback.completed_feedbacks';
this.firstSelectedTab = 0;
if (!this.showAnalysis) {
this.tab = 'overview';
this.selectedTab = AddonModFeedbackIndexTabName.OVERVIEW;
}
if (this.tab == 'analysis') {
if (this.selectedTab === AddonModFeedbackIndexTabName.ANALYSIS) {
this.firstSelectedTab = 1;
return await this.fetchFeedbackAnalysisData();
@ -227,34 +239,36 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity
if (this.tabsReady) {
// Make sure the right tab is selected.
this.tabsComponent?.selectTab(this.tab || 'overview');
this.tabsComponent?.selectTab(this.selectedTab ?? AddonModFeedbackIndexTabName.OVERVIEW);
}
}
}
/**
* Convenience function to get feedback overview data.
*
* @returns Resolved when done.
*/
protected async fetchFeedbackOverviewData(): Promise<void> {
if (!this.access || !this.feedback) {
return;
}
const promises: Promise<void>[] = [];
if (this.access!.cancomplete && this.access!.cansubmit && this.access!.isopen) {
promises.push(AddonModFeedback.getResumePage(this.feedback!.id, { cmId: this.module.id }).then((goPage) => {
if (this.access.cancomplete && this.access.cansubmit && this.access.isopen) {
promises.push(AddonModFeedback.getResumePage(this.feedback.id, { cmId: this.module.id }).then((goPage) => {
this.goPage = goPage > 0 ? goPage : undefined;
return;
}));
}
if (this.access!.canedititems) {
this.overview.timeopen = (this.feedback!.timeopen || 0) * 1000;
if (this.access.canedititems) {
this.overview.timeopen = (this.feedback.timeopen || 0) * 1000;
this.overview.openTimeReadable = this.overview.timeopen ? CoreTimeUtils.userDate(this.overview.timeopen) : '';
this.overview.timeclose = (this.feedback!.timeclose || 0) * 1000;
this.overview.timeclose = (this.feedback.timeclose || 0) * 1000;
this.overview.closeTimeReadable = this.overview.timeclose ? CoreTimeUtils.userDate(this.overview.timeclose) : '';
}
if (this.access!.canviewanalysis) {
if (this.access.canviewanalysis) {
// Get groups (only for teachers).
promises.push(this.fetchGroupInfo(this.module.id));
}
@ -262,7 +276,7 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity
try {
await Promise.all(promises);
} finally {
this.tabsLoaded.overview = true;
this.tabs.overview.loaded = true;
}
}
@ -273,15 +287,14 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity
*/
protected async fetchFeedbackAnalysisData(): Promise<void> {
try {
if (this.access!.canviewanalysis) {
if (this.access?.canviewanalysis) {
// Get groups (only for teachers).
await this.fetchGroupInfo(this.module.id);
} else {
this.tabChanged('overview');
this.tabChanged(AddonModFeedbackIndexTabName.OVERVIEW);
}
} finally {
this.tabsLoaded.analysis = true;
this.tabs.analysis.loaded = true;
}
}
@ -419,7 +432,7 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity
* Open attempts page.
*/
openAttempts(): void {
if (!this.access!.canviewreports || this.completedCount <= 0) {
if (!this.access || !this.access.canviewreports || this.completedCount <= 0) {
return;
}
@ -438,11 +451,11 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity
*
* @param tabName New tab name.
*/
tabChanged(tabName: string): void {
const tabHasChanged = this.tab !== undefined && this.tab !== tabName;
this.tab = tabName;
tabChanged(tabName: AddonModFeedbackIndexTabName): void {
const tabHasChanged = this.selectedTab !== undefined && this.selectedTab !== tabName;
this.selectedTab = tabName;
if (!this.tabsLoaded[this.tab]) {
if (!this.tabs[this.selectedTab].loaded) {
this.loadContent(false, false, true);
}
@ -455,17 +468,20 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity
* Set group to see the analysis.
*
* @param groupId Group ID.
* @returns Resolved when done.
*/
async setGroup(groupId: number): Promise<void> {
if (!this.feedback) {
return;
}
this.group = groupId;
const analysis = await AddonModFeedback.getAnalysis(this.feedback!.id, { groupId, cmId: this.module.id });
const analysis = await AddonModFeedback.getAnalysis(this.feedback.id, { groupId, cmId: this.module.id });
this.completedCount = analysis.completedcount;
this.itemsCount = analysis.itemscount;
if (this.tab == 'analysis') {
if (this.selectedTab === AddonModFeedbackIndexTabName.ANALYSIS) {
let num = 1;
this.items = <AddonModFeedbackItem[]> analysis.itemsdata.map((itemData) => {

View File

@ -24,3 +24,11 @@ export const ADDON_MOD_FEEDBACK_MULTICHOICE_HIDENOSELECT = 'h';
export const ADDON_MOD_FEEDBACK_MULTICHOICERATED_VALUE_SEP = '####';
export const ADDON_MOD_FEEDBACK_PER_PAGE = 20;
/**
* Index Tabs.
*/
export enum AddonModFeedbackIndexTabName {
OVERVIEW = 'overview',
ANALYSIS = 'analysis',
}

View File

@ -36,8 +36,14 @@ import {
import { AddonModFeedbackFormItem, AddonModFeedbackHelper } from '../../services/feedback-helper';
import { AddonModFeedbackSync } from '../../services/feedback-sync';
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
import { ADDON_MOD_FEEDBACK_COMPONENT, ADDON_MOD_FEEDBACK_FORM_SUBMITTED, ADDON_MOD_FEEDBACK_PAGE_NAME } from '../../constants';
import {
ADDON_MOD_FEEDBACK_COMPONENT,
ADDON_MOD_FEEDBACK_FORM_SUBMITTED,
ADDON_MOD_FEEDBACK_PAGE_NAME,
AddonModFeedbackIndexTabName,
} from '../../constants';
import { CoreLoadings } from '@services/loadings';
import { CoreError } from '@classes/errors/error';
/**
* Page that displays feedback form.
@ -117,14 +123,14 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave {
return;
}
if (!this.feedback) {
if (!this.feedback || !this.module) {
return;
}
try {
await AddonModFeedback.logView(this.feedback.id, true);
CoreCourse.checkModuleCompletion(this.courseId, this.module!.completiondata);
CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata);
} catch {
// Ignore errors.
}
@ -183,7 +189,7 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave {
let page = 0;
if (!this.preview && this.access!.cansubmit && !this.access!.isempty) {
if (!this.preview && this.access?.cansubmit && !this.access?.isempty) {
page = this.currentPage ?? await this.fetchResumePage(options);
} else {
this.preview = true;
@ -203,11 +209,14 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave {
* Fetch access information.
*
* @param options Options.
* @returns Promise resolved when done.
*/
protected async fetchAccessData(options: CoreCourseCommonModWSOptions): Promise<void> {
if (!this.feedback) {
return;
}
try {
this.access = await AddonModFeedback.getFeedbackAccessInformation(this.feedback!.id, options);
this.access = await AddonModFeedback.getFeedbackAccessInformation(this.feedback.id, options);
} catch (error) {
if (this.offline || CoreUtils.isWebServiceError(error)) {
// Already offline or shouldn't go offline, fail.
@ -218,7 +227,7 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave {
this.offline = true;
options.readingStrategy = CoreSitesReadingStrategy.PREFER_CACHE;
this.access = await AddonModFeedback.getFeedbackAccessInformation(this.feedback!.id, options);
this.access = await AddonModFeedback.getFeedbackAccessInformation(this.feedback.id, options);
}
}
@ -229,8 +238,12 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave {
* @returns Promise resolved with the page to resume.
*/
protected async fetchResumePage(options: CoreCourseCommonModWSOptions): Promise<number> {
if (!this.feedback) {
throw new CoreError('Cannot fetch resume page: missing feedback');
}
try {
return await AddonModFeedback.getResumePage(this.feedback!.id, options);
return await AddonModFeedback.getResumePage(this.feedback.id, options);
} catch (error) {
if (this.offline || CoreUtils.isWebServiceError(error)) {
// Already offline or shouldn't go offline, fail.
@ -241,7 +254,7 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave {
this.offline = true;
options.readingStrategy = CoreSitesReadingStrategy.PREFER_CACHE;
return AddonModFeedback.getResumePage(this.feedback!.id, options);
return AddonModFeedback.getResumePage(this.feedback.id, options);
}
}
@ -249,7 +262,6 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave {
* Fetch page data.
*
* @param page Page to load.
* @returns Promise resolved when done.
*/
protected async fetchFeedbackPageData(page: number = 0): Promise<void> {
this.items = [];
@ -274,6 +286,10 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave {
* @returns Promise resolved with WS response.
*/
protected async fetchPageItems(page: number): Promise<AddonModFeedbackPageItems> {
if (!this.feedback) {
throw new CoreError('Cannot fetch page items: missing feedback');
}
const options = {
cmId: this.cmId,
readingStrategy: this.offline ? CoreSitesReadingStrategy.PREFER_CACHE : CoreSitesReadingStrategy.ONLY_NETWORK,
@ -281,7 +297,7 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave {
};
if (this.preview) {
const response = await AddonModFeedback.getItems(this.feedback!.id, options);
const response = await AddonModFeedback.getItems(this.feedback.id, options);
return {
items: response.items,
@ -295,7 +311,7 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave {
let response: AddonModFeedbackPageItems;
try {
response = await AddonModFeedback.getPageItemsWithValues(this.feedback!.id, page, options);
response = await AddonModFeedback.getPageItemsWithValues(this.feedback.id, page, options);
} catch (error) {
if (this.offline || CoreUtils.isWebServiceError(error)) {
// Already offline or shouldn't go offline, fail.
@ -306,7 +322,7 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave {
this.offline = true;
options.readingStrategy = CoreSitesReadingStrategy.PREFER_CACHE;
response = await AddonModFeedback.getPageItemsWithValues(this.feedback!.id, page, options);
response = await AddonModFeedback.getPageItemsWithValues(this.feedback.id, page, options);
}
this.hasPrevPage = !!response.hasprevpage;
@ -319,9 +335,12 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave {
* Function to allow page navigation through the questions form.
*
* @param goPrevious If true it will go back to the previous page, if false, it will go forward.
* @returns Resolved when done.
*/
async gotoPage(goPrevious: boolean): Promise<void> {
if (!this.feedback || this.currentPage === undefined) {
return;
}
this.content?.scrollToTop();
this.feedbackLoaded = false;
@ -330,9 +349,9 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave {
try {
// Sync other pages first.
await CoreUtils.ignoreErrors(AddonModFeedbackSync.syncFeedback(this.feedback!.id));
await CoreUtils.ignoreErrors(AddonModFeedbackSync.syncFeedback(this.feedback.id));
const response = await AddonModFeedback.processPage(this.feedback!.id, this.currentPage!, responses, {
const response = await AddonModFeedback.processPage(this.feedback.id, this.currentPage, responses, {
goPrevious,
formHasErrors,
courseId: this.courseId,
@ -351,14 +370,14 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave {
// Invalidate access information so user will see home page updated (continue form or completion messages).
await Promise.all([
AddonModFeedback.invalidateFeedbackAccessInformationData(this.feedback!.id),
AddonModFeedback.invalidateResumePageData(this.feedback!.id),
AddonModFeedback.invalidateFeedbackAccessInformationData(this.feedback.id),
AddonModFeedback.invalidateResumePageData(this.feedback.id),
]);
// If form has been submitted, the info has been already invalidated but we should update index view.
CoreEvents.trigger(ADDON_MOD_FEEDBACK_FORM_SUBMITTED, {
feedbackId: this.feedback!.id,
tab: 'overview',
feedbackId: this.feedback.id,
tab: AddonModFeedbackIndexTabName.OVERVIEW,
offline: this.completedOffline,
});
@ -371,11 +390,11 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave {
// Errors on questions, stay in page.
} else {
// Invalidate access information so user will see home page updated (continue form).
await AddonModFeedback.invalidateResumePageData(this.feedback!.id);
await AddonModFeedback.invalidateResumePageData(this.feedback.id);
CoreEvents.trigger(ADDON_MOD_FEEDBACK_FORM_SUBMITTED, {
feedbackId: this.feedback!.id,
tab: 'overview',
feedbackId: this.feedback.id,
tab: AddonModFeedbackIndexTabName.OVERVIEW,
offline: this.completedOffline,
});
@ -393,11 +412,15 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave {
* Function to link implemented features.
*/
showAnalysis(): void {
if (!this.feedback) {
return;
}
if (this.fromIndex) {
// Previous page is the index page, go back.
CoreEvents.trigger(ADDON_MOD_FEEDBACK_FORM_SUBMITTED, {
feedbackId: this.feedback!.id,
tab: 'analysis',
feedbackId: this.feedback.id,
tab: AddonModFeedbackIndexTabName.ANALYSIS,
offline: this.completedOffline,
});
@ -409,7 +432,7 @@ export class AddonModFeedbackFormPage implements OnInit, OnDestroy, CanLeave {
CoreNavigator.navigateToSitePath(ADDON_MOD_FEEDBACK_PAGE_NAME + `/${this.courseId}/${this.cmId}`, {
params: {
module: this.module,
tab: 'analysis',
tab: AddonModFeedbackIndexTabName.ANALYSIS,
},
});
}

View File

@ -16,6 +16,6 @@
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}" />
</ion-refresher>
<addon-mod-feedback-index [module]="module" [courseId]="courseId" [group]="selectedGroup" [tab]="selectedTab"
<addon-mod-feedback-index [module]="module" [courseId]="courseId" [group]="selectedGroup" [selectedTab]="selectedTab"
(dataRetrieved)="updateData($event)" />
</ion-content>

View File

@ -16,6 +16,7 @@ import { Component, OnInit, ViewChild } from '@angular/core';
import { CoreCourseModuleMainActivityPage } from '@features/course/classes/main-activity-page';
import { CoreNavigator } from '@services/navigator';
import { AddonModFeedbackIndexComponent } from '../../components/index/index';
import { AddonModFeedbackIndexTabName } from '../../constants';
/**
* Page that displays a feedback.
@ -28,7 +29,7 @@ export class AddonModFeedbackIndexPage extends CoreCourseModuleMainActivityPage<
@ViewChild(AddonModFeedbackIndexComponent) activityComponent?: AddonModFeedbackIndexComponent;
selectedTab?: string;
selectedTab?: AddonModFeedbackIndexTabName;
selectedGroup?: number;
/**

View File

@ -34,6 +34,7 @@ import {
ADDON_MOD_FEEDBACK_MULTICHOICE_TYPE_SEP,
ADDON_MOD_FEEDBACK_MULTICHOICERATED_VALUE_SEP,
ADDON_MOD_FEEDBACK_PER_PAGE,
AddonModFeedbackIndexTabName,
} from '../constants';
/**
@ -1263,7 +1264,7 @@ declare module '@singletons/events' {
*/
export type AddonModFeedbackFormSubmittedData = {
feedbackId: number;
tab: string;
tab: AddonModFeedbackIndexTabName;
offline: boolean;
};

View File

@ -19,7 +19,7 @@ import { CoreCourse } from '@features/course/services/course';
import { CoreNavigator } from '@services/navigator';
import { CoreDomUtils } from '@services/utils/dom';
import { makeSingleton } from '@singletons';
import { ADDON_MOD_FEEDBACK_PAGE_NAME } from '../../constants';
import { ADDON_MOD_FEEDBACK_PAGE_NAME, AddonModFeedbackIndexTabName } from '../../constants';
import { CoreLoadings } from '@services/loadings';
/**
@ -59,7 +59,7 @@ export class AddonModFeedbackAnalysisLinkHandlerService extends CoreContentLinks
{
params: {
module,
tab: 'analysis',
tab: AddonModFeedbackIndexTabName.ANALYSIS,
},
siteId,
},

View File

@ -221,7 +221,7 @@ export class CoreTabsBaseComponent<T extends CoreTabBase> implements AfterViewIn
this.swiper.update();
await CoreWait.nextTick();
if (!this.hasSliddenToInitial && this.selectedIndex && this.selectedIndex >= this.swiper.slidesPerViewDynamic()) {
if (!this.hasSliddenToInitial && this.selectedIndex >= this.swiper.slidesPerViewDynamic()) {
this.hasSliddenToInitial = true;
this.shouldSlideToInitial = true;
@ -233,7 +233,7 @@ export class CoreTabsBaseComponent<T extends CoreTabBase> implements AfterViewIn
}, 400);
return;
} else if (this.selectedIndex) {
} else {
this.hasSliddenToInitial = true;
}
@ -301,21 +301,21 @@ export class CoreTabsBaseComponent<T extends CoreTabBase> implements AfterViewIn
* @returns Initial tab, undefined if no valid tab found.
*/
protected calculateInitialTab(): T | undefined {
const selectedTab: T | undefined = this.tabs[this.selectedIndex || 0] || undefined;
const selectedTab: T | undefined = this.tabs[this.selectedIndex] || undefined;
if (selectedTab && selectedTab.enabled) {
if (selectedTab?.enabled) {
return selectedTab;
}
// The tab is not enabled or not shown. Get the first tab that is enabled.
return this.tabs.find((tab) => tab.enabled) || undefined;
return this.tabs.find((tab) => tab.enabled);
}
/**
* Method executed when the slides are changed.
*/
slideChanged(): void {
if (!this.swiper) {
if (!this.swiper || this.swiper.destroyed) {
return;
}
@ -340,7 +340,7 @@ export class CoreTabsBaseComponent<T extends CoreTabBase> implements AfterViewIn
* Calculate the number of slides that can fit on the screen.
*/
protected async calculateMaxSlides(): Promise<void> {
if (!this.swiper) {
if (!this.swiper || this.swiper.destroyed) {
return;
}
@ -456,7 +456,7 @@ export class CoreTabsBaseComponent<T extends CoreTabBase> implements AfterViewIn
return;
}
if (this.selected && this.swiper) {
if (this.selected && this.swiper && !this.swiper.destroyed) {
// Check if we need to slide to the tab because it's not visible.
const firstVisibleTab = this.swiper.activeIndex;
const lastVisibleTab = firstVisibleTab + this.swiper.slidesPerViewDynamic() - 1;