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

View File

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