Skip to content

Commit 22cb6f7

Browse files
committed
MOBILE-4842 chore: Migrate some Inputs and Outputs on directives
1 parent b90f24e commit 22cb6f7

File tree

11 files changed

+88
-100
lines changed

11 files changed

+88
-100
lines changed

src/addons/mod/workshop/assessment/numerrors/component/addon-mod-workshop-assessment-strategy-numerrors.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@ <h2>{{ field.dimtitle }}</h2>
4141
} @else {
4242
<ion-item class="ion-text-wrap">
4343
<ion-label>
44-
<p class="item-heading">{{ 'addon.mod_workshop_assessment_numerrors.dimensioncommentfor' | translate : {'$a': field.dimtitle
45-
} }}</p>
44+
<p class="item-heading">
45+
{{ 'addon.mod_workshop_assessment_numerrors.dimensioncommentfor' | translate : {'$a': field.dimtitle} }}
46+
</p>
4647
<p>
4748
<core-format-text [text]="selectedValues[n].peercomment" contextLevel="module" [contextInstanceId]="moduleId"
4849
[courseId]="courseId" />

src/core/directives/aria-button.ts

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
import { Directive, ElementRef, OnInit, Output, EventEmitter, OnChanges, SimpleChanges, Input, inject } from '@angular/core';
15+
import { Directive, ElementRef, OnInit, inject, input, effect, output } from '@angular/core';
1616
import { CoreDom } from '@singletons/dom';
1717
import { toBoolean } from '../transforms/boolean';
1818

@@ -22,35 +22,31 @@ import { toBoolean } from '../transforms/boolean';
2222
@Directive({
2323
selector: '[ariaButtonClick]',
2424
})
25-
export class CoreAriaButtonClickDirective implements OnInit, OnChanges {
25+
export class CoreAriaButtonClickDirective implements OnInit {
2626

27-
@Input({ transform: toBoolean }) disabled = false;
28-
@Output() ariaButtonClick = new EventEmitter();
27+
readonly disabled = input(false, { transform: toBoolean });
28+
readonly ariaButtonClick = output<MouseEvent | KeyboardEvent>();// Emit when the button is clicked.
2929

3030
protected element: HTMLElement = inject(ElementRef).nativeElement;
3131

32-
/**
33-
* @inheritdoc
34-
*/
35-
ngOnInit(): void {
36-
CoreDom.initializeClickableElementA11y(this.element, (event) => this.ariaButtonClick.emit(event));
32+
constructor() {
33+
effect(() => {
34+
const disabled = this.disabled();
35+
if (this.element.getAttribute('tabindex') === '0' && disabled) {
36+
this.element.setAttribute('tabindex', '-1');
37+
}
38+
39+
if (this.element.getAttribute('tabindex') === '-1' && !disabled) {
40+
this.element.setAttribute('tabindex', '0');
41+
}
42+
});
3743
}
3844

3945
/**
4046
* @inheritdoc
4147
*/
42-
ngOnChanges(changes: SimpleChanges): void {
43-
if (!changes.disabled) {
44-
return;
45-
}
46-
47-
if (this.element.getAttribute('tabindex') === '0' && this.disabled) {
48-
this.element.setAttribute('tabindex', '-1');
49-
}
50-
51-
if (this.element.getAttribute('tabindex') === '-1' && !this.disabled) {
52-
this.element.setAttribute('tabindex', '0');
53-
}
48+
ngOnInit(): void {
49+
CoreDom.initializeClickableElementA11y(this.element, (event) => this.ariaButtonClick.emit(event));
5450
}
5551

5652
}

src/core/directives/auto-focus.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
import { Directive, Input, ElementRef, AfterViewInit, inject } from '@angular/core';
15+
import { Directive, ElementRef, AfterViewInit, inject, input } from '@angular/core';
1616

1717
import { CoreDom } from '@singletons/dom';
1818
import { CoreWait } from '@singletons/wait';
@@ -31,7 +31,7 @@ import { toBoolean } from '../transforms/boolean';
3131
})
3232
export class CoreAutoFocusDirective implements AfterViewInit {
3333

34-
@Input({ alias: 'core-auto-focus', transform: toBoolean }) autoFocus = true;
34+
readonly autoFocus = input(true, { alias: 'core-auto-focus', transform: toBoolean });
3535

3636
protected element: HTMLIonInputElement | HTMLIonTextareaElement | HTMLIonSearchbarElement | HTMLElement
3737
= inject(ElementRef).nativeElement;
@@ -40,7 +40,7 @@ export class CoreAutoFocusDirective implements AfterViewInit {
4040
* @inheritdoc
4141
*/
4242
async ngAfterViewInit(): Promise<void> {
43-
if (!this.autoFocus) {
43+
if (!this.autoFocus()) {
4444
return;
4545
}
4646

src/core/directives/auto-rows.ts

Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
import { Directive, ElementRef, Output, EventEmitter, AfterViewInit, Input, OnChanges, inject } from '@angular/core';
15+
import { Directive, ElementRef, Output, EventEmitter, inject, input, effect, output } from '@angular/core';
1616

1717
/**
1818
* Directive to adapt a textarea rows depending on the input text. It's based on Moodle's data-auto-rows.
@@ -24,45 +24,28 @@ import { Directive, ElementRef, Output, EventEmitter, AfterViewInit, Input, OnCh
2424
@Directive({
2525
selector: 'textarea[core-auto-rows], ion-textarea[core-auto-rows]',
2626
})
27-
export class CoreAutoRowsDirective implements AfterViewInit, OnChanges {
27+
export class CoreAutoRowsDirective {
28+
29+
readonly value = input<string>(undefined, { alias: 'core-auto-rows' });
30+
readonly onResize = output<void>();// Emit when resizing the textarea.
2831

2932
protected height = 0;
3033
protected element: HTMLElement = inject(ElementRef).nativeElement;
3134

32-
@Input('core-auto-rows') value?: string;
33-
@Output() onResize: EventEmitter<void>; // Emit when resizing the textarea.
34-
3535
constructor() {
36-
this.onResize = new EventEmitter();
37-
}
36+
effect(() => {
37+
this.value();
3838

39-
/**
40-
* Resize after initialized.
41-
*/
42-
ngAfterViewInit(): void {
43-
// Wait for rendering of child views.
44-
setTimeout(() => {
39+
// Resize the textarea when the value changes.
4540
this.resize();
46-
}, 300);
47-
}
48-
49-
/**
50-
* Resize when content changes.
51-
*/
52-
ngOnChanges(): void {
53-
this.resize();
54-
55-
if (this.value === '') {
56-
// Maybe the form was resetted. In that case it takes a bit to update the height.
57-
setTimeout(() => this.resize(), 300);
58-
}
41+
});
5942
}
6043

6144
/**
6245
* Resize the textarea.
6346
*/
6447
protected resize(): void {
65-
if (this.element.tagName == 'ION-TEXTAREA') {
48+
if (this.element.tagName === 'ION-TEXTAREA') {
6649
// Search the actual textarea.
6750
const textarea = this.element.querySelector('textarea');
6851
if (!textarea) {
@@ -77,7 +60,7 @@ export class CoreAutoRowsDirective implements AfterViewInit, OnChanges {
7760
this.element.style.height = `${this.element.scrollHeight}px`;
7861

7962
// Emit event when resizing.
80-
if (this.height != this.element.scrollHeight) {
63+
if (this.height !== this.element.scrollHeight) {
8164
this.height = this.element.scrollHeight;
8265
this.onResize.emit();
8366
}

src/core/directives/collapsible-footer.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
import { Directive, ElementRef, Input, OnDestroy, OnInit, inject } from '@angular/core';
15+
import { Directive, ElementRef, OnDestroy, OnInit, inject, input } from '@angular/core';
1616
import { ScrollDetail } from '@ionic/core';
1717
import { IonContent } from '@ionic/angular';
1818
import { CoreUtils } from '@singletons/utils';
@@ -38,7 +38,7 @@ import { toBoolean } from '../transforms/boolean';
3838
})
3939
export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy {
4040

41-
@Input({ transform: toBoolean }) appearOnBottom = false; // Whether footer should re-appear when reaching the bottom.
41+
readonly appearOnBottom = input(false, { transform: toBoolean }); // Whether footer should re-appear when reaching the bottom.
4242

4343
protected id = '0';
4444
protected element: HTMLElement = inject(ElementRef).nativeElement;
@@ -218,7 +218,7 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy {
218218
protected onScroll(scrollDetail: ScrollDetail, scrollElement: HTMLElement): void {
219219
const maxScroll = scrollElement.scrollHeight - scrollElement.offsetHeight;
220220
const footerHasFocus = this.moduleNav?.contains(document.activeElement);
221-
if (scrollDetail.scrollTop <= 0 || (this.appearOnBottom && scrollDetail.scrollTop >= maxScroll) || footerHasFocus) {
221+
if (scrollDetail.scrollTop <= 0 || (this.appearOnBottom() && scrollDetail.scrollTop >= maxScroll) || footerHasFocus) {
222222
// Reset.
223223
this.setBarHeight(this.initialHeight);
224224
} else {

src/core/directives/collapsible-item.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
import { Directive, ElementRef, Input, OnDestroy, OnInit, inject } from '@angular/core';
15+
import { Directive, ElementRef, OnDestroy, OnInit, inject, input } from '@angular/core';
1616
import { CoreCancellablePromise } from '@classes/cancellable-promise';
1717
import { CoreLoadingComponent } from '@components/loading/loading';
1818
import { CoreSettingsHelper } from '@features/settings/services/settings-helper';
@@ -46,7 +46,7 @@ export class CoreCollapsibleItemDirective implements OnInit, OnDestroy {
4646
* Using this parameter will force display: block to calculate height better.
4747
* If you want to avoid this use class="inline" at the same time to use display: inline-block.
4848
*/
49-
@Input('collapsible-item') height: number | string = defaultMaxHeight;
49+
readonly height = input<number | string>(defaultMaxHeight, { alias: 'collapsible-item' });
5050

5151
protected element: HTMLElement = inject(ElementRef).nativeElement;
5252
protected toggleExpandEnabled = false;
@@ -72,16 +72,17 @@ export class CoreCollapsibleItemDirective implements OnInit, OnDestroy {
7272
* @inheritdoc
7373
*/
7474
async ngOnInit(): Promise<void> {
75-
if (this.height === null) {
75+
const height = this.height();
76+
if (height === null) {
7677
return;
7778
}
7879

79-
if (typeof this.height === 'string') {
80-
this.maxHeight = this.height === ''
80+
if (typeof height === 'string') {
81+
this.maxHeight = height === ''
8182
? defaultMaxHeight
82-
: parseInt(this.height, 10);
83+
: parseInt(height, 10);
8384
} else {
84-
this.maxHeight = this.height;
85+
this.maxHeight = height;
8586
}
8687
this.maxHeight = this.maxHeight < minMaxHeight ? defaultMaxHeight : this.maxHeight;
8788

src/core/directives/download-file.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
import { Directive, Input, OnInit, ElementRef, inject } from '@angular/core';
15+
import { Directive, OnInit, ElementRef, inject, input } from '@angular/core';
1616
import { CoreFileHelper } from '@services/file-helper';
1717
import { CoreAlerts } from '@services/overlays/alerts';
1818
import { CoreLoadings } from '@services/overlays/loadings';
@@ -28,9 +28,9 @@ import { Translate } from '@singletons';
2828
})
2929
export class CoreDownloadFileDirective implements OnInit {
3030

31-
@Input('core-download-file') file?: CoreWSFile; // The file to download.
32-
@Input() component?: string; // Component to link the file to.
33-
@Input() componentId?: string | number; // Component ID to use in conjunction with the component.
31+
readonly file = input<CoreWSFile>(undefined, { alias: 'core-download-file' }); // The file to download.
32+
readonly component = input<string>(); // Component to link the file to.
33+
readonly componentId = input<string | number>(); // Component ID to use in conjunction with the component.
3434

3535
protected element: HTMLElement = inject(ElementRef).nativeElement;
3636

@@ -39,7 +39,8 @@ export class CoreDownloadFileDirective implements OnInit {
3939
*/
4040
ngOnInit(): void {
4141
this.element.addEventListener('click', async (ev: Event) => {
42-
if (!this.file) {
42+
const file = this.file();
43+
if (!file) {
4344
return;
4445
}
4546

@@ -49,7 +50,7 @@ export class CoreDownloadFileDirective implements OnInit {
4950
const modal = await CoreLoadings.show();
5051

5152
try {
52-
await CoreFileHelper.downloadAndOpenFile(this.file, this.component, this.componentId);
53+
await CoreFileHelper.downloadAndOpenFile(file, this.component(), this.componentId());
5354
} catch (error) {
5455
CoreAlerts.showError(error, { default: Translate.instant('core.errordownloading') });
5556
} finally {

src/core/directives/supress-events.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
// Based on http://roblouie.com/article/198/using-gestures-in-the-ionic-2-beta/
1616

17-
import { Directive, ElementRef, OnInit, Input, Output, EventEmitter, inject } from '@angular/core';
17+
import { Directive, ElementRef, OnInit, Output, EventEmitter, inject, input } from '@angular/core';
1818
import { CoreLogger } from '@singletons/logger';
1919

2020
/**
@@ -41,7 +41,9 @@ import { CoreLogger } from '@singletons/logger';
4141
})
4242
export class CoreSupressEventsDirective implements OnInit {
4343

44-
@Input('core-suppress-events') suppressEvents?: string | string[];
44+
readonly suppressEvents = input<string | string[]>(undefined, { alias: 'core-suppress-events' });
45+
// Not migrable yet, observed is not supported in Angular 20.
46+
// https://github.com/angular/angular/issues/54837
4547
@Output() onClick = new EventEmitter();
4648

4749
protected element: HTMLElement = inject(ElementRef).nativeElement;
@@ -59,17 +61,18 @@ export class CoreSupressEventsDirective implements OnInit {
5961

6062
let events: string[];
6163

62-
if (this.suppressEvents == 'all' || this.suppressEvents === undefined || this.suppressEvents === null) {
64+
const suppressEvents = this.suppressEvents();
65+
if (suppressEvents == 'all' || suppressEvents === undefined || suppressEvents === null) {
6366
// Suppress all events.
6467
events = ['click', 'mousedown', 'touchdown', 'touchmove', 'touchstart'];
6568

66-
} else if (typeof this.suppressEvents == 'string') {
69+
} else if (typeof suppressEvents == 'string') {
6770
// It's a string, just suppress this event.
68-
events = [this.suppressEvents];
71+
events = [suppressEvents];
6972

70-
} else if (Array.isArray(this.suppressEvents)) {
73+
} else if (Array.isArray(suppressEvents)) {
7174
// Array supplied.
72-
events = this.suppressEvents;
75+
events = suppressEvents;
7376
} else {
7477
events = [];
7578
}

0 commit comments

Comments
 (0)