diff --git a/src/core/directives/directives.module.ts b/src/core/directives/directives.module.ts index 2767f4973..3a89d007f 100644 --- a/src/core/directives/directives.module.ts +++ b/src/core/directives/directives.module.ts @@ -33,6 +33,7 @@ import { CoreCollapsibleItemDirective } from './collapsible-item'; import { CoreCollapsibleFooterDirective } from './collapsible-footer'; import { CoreContentDirective } from './content'; import { CoreOnAppearDirective } from './on-appear'; +import { CoreUpdateNonReactiveAttributesDirective } from './update-non-reactive-attributes'; @NgModule({ declarations: [ @@ -55,6 +56,7 @@ import { CoreOnAppearDirective } from './on-appear'; CoreCollapsibleItemDirective, CoreCollapsibleFooterDirective, CoreContentDirective, + CoreUpdateNonReactiveAttributesDirective, ], exports: [ CoreAutoFocusDirective, @@ -76,6 +78,7 @@ import { CoreOnAppearDirective } from './on-appear'; CoreCollapsibleItemDirective, CoreCollapsibleFooterDirective, CoreContentDirective, + CoreUpdateNonReactiveAttributesDirective, ], }) export class CoreDirectivesModule {} diff --git a/src/core/directives/update-non-reactive-attributes.ts b/src/core/directives/update-non-reactive-attributes.ts new file mode 100644 index 000000000..1c8508c3b --- /dev/null +++ b/src/core/directives/update-non-reactive-attributes.ts @@ -0,0 +1,68 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Directive, ElementRef, OnDestroy, OnInit } from '@angular/core'; + +/** + * Directive to observe mutations on some attributes and propagate them inside. + * Current supported attributes: ion-button.aria-label + * + * This is necessary in order to update some attributes that are not reactive, for example aria-label. + * + * @see https://github.com/ionic-team/ionic-framework/issues/21534 + */ +@Directive({ + selector: 'ion-button', +}) +export class CoreUpdateNonReactiveAttributesDirective implements OnInit, OnDestroy { + + protected element: HTMLIonButtonElement; + protected mutationObserver: MutationObserver; + + constructor(element: ElementRef) { + this.element = element.nativeElement; + this.mutationObserver = new MutationObserver(() => { + const ariaLabel = this.element.getAttribute('aria-label'); + if (!ariaLabel) { + // Aria label unset by ionButton component (when first created). + return; + } + + // Propagate label to button. + const button = this.element.shadowRoot?.querySelector('button'); + button?.setAttribute('aria-label', ariaLabel); + }); + } + + /** + * @inheritdoc + */ + async ngOnInit(): Promise { + await this.element.componentOnReady(); + + if (!this.element.getAttribute('aria-label')) { + return; + } + + this.mutationObserver.observe(this.element, { attributes: true, attributeFilter: ['aria-label'] }); + } + + /** + * @inheritdoc + */ + ngOnDestroy(): void { + this.mutationObserver.disconnect(); + } + +} diff --git a/src/core/features/course/components/course-format/course-format.html b/src/core/features/course/components/course-format/course-format.html index 323216634..2d8cd3391 100644 --- a/src/core/features/course/components/course-format/course-format.html +++ b/src/core/features/course/components/course-format/course-format.html @@ -24,7 +24,7 @@ -
+
diff --git a/src/core/features/course/components/course-format/course-format.ts b/src/core/features/course/components/course-format/course-format.ts index 4e0be0612..50460392d 100644 --- a/src/core/features/course/components/course-format/course-format.ts +++ b/src/core/features/course/components/course-format/course-format.ts @@ -92,7 +92,6 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { selectedSection?: CoreCourseSection; previousSection?: CoreCourseSection; nextSection?: CoreCourseSection; - hasPreviousOrNextSections = false; allSectionsId: number = CoreCourseProvider.ALL_SECTIONS_ID; stealthModulesSectionId: number = CoreCourseProvider.STEALTH_MODULES_SECTION_ID; loaded = false; @@ -489,8 +488,6 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { this.showMoreActivities(); } - this.hasPreviousOrNextSections = !!this.previousSection || !!this.nextSection; - // Scroll to module if needed. Give more priority to the input. const moduleIdToScroll = this.moduleId && previousValue === undefined ? this.moduleId : moduleId; if (moduleIdToScroll) { @@ -507,8 +504,6 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { CoreCourse.logView(this.course.id, newSection.section, undefined, this.course.fullname), ); } - - this.invalidateSectionButtons(); } /** @@ -563,25 +558,6 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { done?.(); } - /** - * Invalidate section buttons so that they are rendered again. This is necessary in order to update - * some attributes that are not reactive, for example aria-label. - * - * @see https://github.com/ionic-team/ionic-framework/issues/21534 - */ - protected async invalidateSectionButtons(): Promise { - const previousSection = this.previousSection; - const nextSection = this.nextSection; - - this.previousSection = undefined; - this.nextSection = undefined; - - await CoreUtils.nextTick(); - - this.previousSection = previousSection; - this.nextSection = nextSection; - } - /** * Show more activities (only used when showing all the sections at the same time). *