Merge pull request #3255 from alfonso-salces/MOBILE-3833

MOBILE-3833 quiz: Fix scroll to question
main
Pau Ferrer Ocaña 2022-04-19 16:24:18 +02:00 committed by GitHub
commit ff369b0e09
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 13 deletions

View File

@ -47,6 +47,7 @@ import { CanLeave } from '@guards/can-leave';
import { CoreForms } from '@singletons/form';
import { CoreDom } from '@singletons/dom';
import { CoreTime } from '@singletons/time';
import { CoreComponentsRegistry } from '@singletons/components-registry';
/**
* Page that allows attempting a quiz.
@ -264,7 +265,7 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy, CanLeave {
return;
} else if (page == this.attempt.currentpage && !this.showSummary && slot !== undefined) {
// Navigating to a question in the current page.
this.scrollToQuestion(slot);
await this.scrollToQuestion(slot);
return;
} else if ((page == this.attempt.currentpage && !this.showSummary) || (fromModal && this.isSequential && page != -1)) {
@ -320,7 +321,7 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy, CanLeave {
if (slot !== undefined) {
// Scroll to the question.
this.scrollToQuestion(slot);
await this.scrollToQuestion(slot);
}
}
}
@ -687,8 +688,10 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy, CanLeave {
*
* @param slot Slot of the question to scroll to.
*/
protected scrollToQuestion(slot: number): void {
CoreDom.scrollToElement(
protected async scrollToQuestion(slot: number): Promise<void> {
await CoreUtils.nextTick();
await CoreComponentsRegistry.waitComponentsReady(this.elementRef.nativeElement, 'core-question');
await CoreDom.scrollToElement(
this.elementRef.nativeElement,
'#addon-mod_quiz-question-' + slot,
);

View File

@ -12,7 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, Input, Output, OnInit, EventEmitter, ChangeDetectorRef, Type } from '@angular/core';
import { Component, Input, Output, OnInit, EventEmitter, ChangeDetectorRef, Type, ElementRef } from '@angular/core';
import { AsyncComponent } from '@classes/async-component';
import { CorePromisedValue } from '@classes/promised-value';
import { CoreQuestionBehaviourDelegate } from '@features/question/services/behaviour-delegate';
import { CoreQuestionDelegate } from '@features/question/services/question-delegate';
@ -20,6 +22,7 @@ import { CoreQuestionBehaviourButton, CoreQuestionHelper, CoreQuestionQuestion }
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils';
import { Translate } from '@singletons';
import { CoreComponentsRegistry } from '@singletons/components-registry';
import { CoreLogger } from '@singletons/logger';
/**
@ -30,7 +33,7 @@ import { CoreLogger } from '@singletons/logger';
templateUrl: 'core-question.html',
styleUrls: ['../../question.scss'],
})
export class CoreQuestionComponent implements OnInit {
export class CoreQuestionComponent implements OnInit, AsyncComponent {
@Input() question?: CoreQuestionQuestion; // The question to render.
@Input() component?: string; // The component the question belongs to.
@ -50,15 +53,24 @@ export class CoreQuestionComponent implements OnInit {
data: Record<string, unknown> = {}; // Data to pass to the component.
seqCheck?: { name: string; value: string }; // Sequenche check name and value (if any).
behaviourComponents?: Type<unknown>[] = []; // Components to render the question behaviour.
loaded = false;
promisedReady: CorePromisedValue<void>;
validationError?: string;
protected logger: CoreLogger;
constructor(
protected changeDetector: ChangeDetectorRef,
) {
get loaded(): boolean {
return this.promisedReady.isResolved();
}
constructor(protected changeDetector: ChangeDetectorRef, private element: ElementRef) {
this.logger = CoreLogger.getInstance('CoreQuestionComponent');
this.promisedReady = new CorePromisedValue();
CoreComponentsRegistry.register(this.element.nativeElement, this);
}
async ready(): Promise<void> {
await this.promisedReady;
}
/**
@ -69,7 +81,7 @@ export class CoreQuestionComponent implements OnInit {
if (!this.question || (this.question.type != 'random' &&
!CoreQuestionDelegate.isQuestionSupported(this.question.type))) {
this.loaded = true;
this.promisedReady.resolve();
return;
}
@ -80,7 +92,7 @@ export class CoreQuestionComponent implements OnInit {
);
if (!this.componentClass) {
this.loaded = true;
this.promisedReady.resolve();
return;
}
@ -163,7 +175,7 @@ export class CoreQuestionComponent implements OnInit {
);
} finally {
this.question.html = CoreDomUtils.removeElementFromHtml(this.question.html, '.im-controls');
this.loaded = true;
this.promisedReady.resolve();
}
}