Skip to content

Commit

Permalink
Remove Evented from ListContent (#2619)
Browse files Browse the repository at this point in the history
  • Loading branch information
RobbieTheWagner authored Jan 21, 2025
1 parent dcccb7b commit f3b2de0
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 133 deletions.
3 changes: 2 additions & 1 deletion app/components/list-content.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
class="list-content js-list-content"
style={{this.style}}
{{did-insert this.elementInserted}}
...attributes
>
<div class="list-table-container">
<table>
<colgroup>
{{#each this.columns as |column|}}
{{#each @columns as |column|}}
<col style={{build-style width=(concat column.width "px")}} />
{{/each}}
</colgroup>
Expand Down
130 changes: 0 additions & 130 deletions app/components/list-content.js

This file was deleted.

150 changes: 150 additions & 0 deletions app/components/list-content.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import { action } from '@ember/object';
import { addListener, removeListener, sendEvent } from '@ember/object/events';
import { inject as service } from '@ember/service';
import Component from '@glimmer/component';
import { htmlSafe } from '@ember/template';
import { schedule } from '@ember/runloop';
import { tracked } from '@glimmer/tracking';
import type { AnyFn } from 'ember/-private/type-utils';

import type LayoutService from '../services/layout';

interface ListContentSignature {
Element: HTMLDivElement;
Args: {
/**
* Array of objects representing the columns to render
* and their corresponding widths. This array is passed
* through the template.
*
* Each item in the array has `width` and `id` properties.
*/
columns: Array<{ id: string; width: number }>;
/**
* Number passed from `list`. Indicates the header height
* in pixels.
*/
headerHeight: number;
};
}

/**
* Base list view config
*/
export default class ListContent extends Component<ListContentSignature> {
/**
* The layout service. Used to observe the app's content height.
*/
@service('layout') declare layoutService: LayoutService;

@tracked contentHeight: number | null = null;

/**
* Hook called before destruction. Clean up events listeners.
*/
willDestroy() {
this.layoutService.off(
'content-height-update',
this,
this.updateContentHeight,
);
return super.willDestroy();
}

get height() {
// In testing list-view is created before `contentHeight` is set
// which will trigger an exception
if (!this.contentHeight) {
return 1;
}
return this.contentHeight - this.args.headerHeight;
}

get style() {
return htmlSafe(`height:${this.height}px`);
}

/**
* Hook called when content element is inserted.
*/
@action
elementInserted() {
schedule('afterRender', this, this.setupHeight);
}

/**
* Set up the content height and listen to any updates to that property.
*/
@action
setupHeight() {
this.contentHeight = this.layoutService.contentHeight;
this.layoutService.on(
'content-height-update',
this,
this.updateContentHeight,
);
}

/**
* Triggered whenever the app's content height changes. This usually happens
* when the window is resized. Once we detect a change we update this
* component's `contentHeight` property and consequently its `height` style.
*
* @param height The app's new content height
*/
@action
updateContentHeight(height: number) {
this.contentHeight = height;
}

// Manually implement Evented functionality, so we can move away from the mixin
// TODO: Do we even need any evented-like things in this component?

on(eventName: string, method: AnyFn): void;
on(eventName: string, target: unknown, method: AnyFn): void;

@action
on(eventName: string, targetOrMethod: unknown | AnyFn, method?: AnyFn): void {
if (typeof targetOrMethod === 'function') {
// If we did not pass a target, default to `this`
addListener(this, eventName, this, targetOrMethod as AnyFn);
} else {
addListener(this, eventName, targetOrMethod, method!);
}
}

one(eventName: string, method: AnyFn): void;
one(eventName: string, target: unknown, method: AnyFn): void;

@action
one(eventName: string, targetOrMethod: unknown | AnyFn, method?: AnyFn) {
if (typeof targetOrMethod === 'function') {
// If we did not pass a target, default to `this`
addListener(this, eventName, this, targetOrMethod as AnyFn, true);
} else {
addListener(this, eventName, targetOrMethod, method!, true);
}
}

off(eventName: string, method: AnyFn): void;
off(eventName: string, target: unknown, method: AnyFn): void;

@action
off(eventName: string, targetOrMethod: unknown | AnyFn, method?: AnyFn) {
try {
if (typeof targetOrMethod === 'function') {
// If we did not pass a target, default to `this`
removeListener(this, eventName, this, targetOrMethod as AnyFn);
} else {
removeListener(this, eventName, targetOrMethod, method!);
}
} catch (e) {
console.error(e);
}
}

@action
trigger(eventName: string, ...args: Array<any>) {
sendEvent(this, eventName, args);
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import Controller from '@ember/controller';
import { action } from '@ember/object';
import type RouterService from '@ember/routing/router-service';
import { inject as service } from '@ember/service';

import type PortService from '../../services/port';

export default class ContainerTypesIndexController extends Controller {
@service port;
@service router;
@service declare port: PortService;
@service declare router: RouterService;

@action
refresh() {
Expand Down
File renamed without changes.

0 comments on commit f3b2de0

Please sign in to comment.