MOBILE-3814 chore: Update non reactive attributes using a directive
parent
9b7988f26d
commit
b1461680a8
|
@ -33,6 +33,7 @@ import { CoreCollapsibleItemDirective } from './collapsible-item';
|
||||||
import { CoreCollapsibleFooterDirective } from './collapsible-footer';
|
import { CoreCollapsibleFooterDirective } from './collapsible-footer';
|
||||||
import { CoreContentDirective } from './content';
|
import { CoreContentDirective } from './content';
|
||||||
import { CoreOnAppearDirective } from './on-appear';
|
import { CoreOnAppearDirective } from './on-appear';
|
||||||
|
import { CoreUpdateNonReactiveAttributesDirective } from './update-non-reactive-attributes';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
|
@ -55,6 +56,7 @@ import { CoreOnAppearDirective } from './on-appear';
|
||||||
CoreCollapsibleItemDirective,
|
CoreCollapsibleItemDirective,
|
||||||
CoreCollapsibleFooterDirective,
|
CoreCollapsibleFooterDirective,
|
||||||
CoreContentDirective,
|
CoreContentDirective,
|
||||||
|
CoreUpdateNonReactiveAttributesDirective,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
CoreAutoFocusDirective,
|
CoreAutoFocusDirective,
|
||||||
|
@ -76,6 +78,7 @@ import { CoreOnAppearDirective } from './on-appear';
|
||||||
CoreCollapsibleItemDirective,
|
CoreCollapsibleItemDirective,
|
||||||
CoreCollapsibleFooterDirective,
|
CoreCollapsibleFooterDirective,
|
||||||
CoreContentDirective,
|
CoreContentDirective,
|
||||||
|
CoreUpdateNonReactiveAttributesDirective,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class CoreDirectivesModule {}
|
export class CoreDirectivesModule {}
|
||||||
|
|
|
@ -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<HTMLIonButtonElement>) {
|
||||||
|
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<void> {
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
<core-infinite-loading [enabled]="canLoadMore" (action)="showMoreActivities($event)"></core-infinite-loading>
|
<core-infinite-loading [enabled]="canLoadMore" (action)="showMoreActivities($event)"></core-infinite-loading>
|
||||||
</div>
|
</div>
|
||||||
<div collapsible-footer appearOnBottom *ngIf="displayCourseIndex && hasPreviousOrNextSections" slot="fixed">
|
<div collapsible-footer appearOnBottom *ngIf="displayCourseIndex && (previousSection || nextSection)" slot="fixed">
|
||||||
<div class="core-course-section-nav-buttons safe-area-padding-horizontal list-item-limited-width">
|
<div class="core-course-section-nav-buttons safe-area-padding-horizontal list-item-limited-width">
|
||||||
<ion-button *ngIf="previousSection" (click)="sectionChanged(previousSection)" expand="block"
|
<ion-button *ngIf="previousSection" (click)="sectionChanged(previousSection)" expand="block"
|
||||||
[attr.aria-label]="('core.previous' | translate) + ': ' + previousSection.name">
|
[attr.aria-label]="('core.previous' | translate) + ': ' + previousSection.name">
|
||||||
|
|
|
@ -92,7 +92,6 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
selectedSection?: CoreCourseSection;
|
selectedSection?: CoreCourseSection;
|
||||||
previousSection?: CoreCourseSection;
|
previousSection?: CoreCourseSection;
|
||||||
nextSection?: CoreCourseSection;
|
nextSection?: CoreCourseSection;
|
||||||
hasPreviousOrNextSections = false;
|
|
||||||
allSectionsId: number = CoreCourseProvider.ALL_SECTIONS_ID;
|
allSectionsId: number = CoreCourseProvider.ALL_SECTIONS_ID;
|
||||||
stealthModulesSectionId: number = CoreCourseProvider.STEALTH_MODULES_SECTION_ID;
|
stealthModulesSectionId: number = CoreCourseProvider.STEALTH_MODULES_SECTION_ID;
|
||||||
loaded = false;
|
loaded = false;
|
||||||
|
@ -489,8 +488,6 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
this.showMoreActivities();
|
this.showMoreActivities();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.hasPreviousOrNextSections = !!this.previousSection || !!this.nextSection;
|
|
||||||
|
|
||||||
// Scroll to module if needed. Give more priority to the input.
|
// Scroll to module if needed. Give more priority to the input.
|
||||||
const moduleIdToScroll = this.moduleId && previousValue === undefined ? this.moduleId : moduleId;
|
const moduleIdToScroll = this.moduleId && previousValue === undefined ? this.moduleId : moduleId;
|
||||||
if (moduleIdToScroll) {
|
if (moduleIdToScroll) {
|
||||||
|
@ -507,8 +504,6 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
CoreCourse.logView(this.course.id, newSection.section, undefined, this.course.fullname),
|
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?.();
|
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<void> {
|
|
||||||
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).
|
* Show more activities (only used when showing all the sections at the same time).
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue