Extracting a View Class - ldco2016/microurb_web_framework GitHub Wiki
import { User } from "../models/User";
export abstract class View {
constructor(public parent: Element, public model: User) {
this.bindModel();
}
bindModel(): void {
this.model.on("change", () => {
this.render();
});
}
bindEvents(fragment: DocumentFragment): void {
const eventsMap = this.eventsMap();
for (let eventKey in eventsMap) {
const [eventName, selector] = eventKey.split(":");
fragment.querySelectorAll(selector).forEach((element) => {
element.addEventListener(eventName, eventsMap[eventKey]);
});
}
}
render(): void {
this.parent.innerHTML = "";
const templateElement = document.createElement("template");
templateElement.innerHTML = this.template();
this.bindEvents(templateElement.content);
this.parent.append(templateElement.content);
}
}
In this refactor, I imported the User
model for now just to eliminate the error, but now I get another error around eventsMap()
and template()
that says that these properties do not exist on abstract class View
. That's because they are not defined by abstract class View
and my expectation is that they will always be defined by a child class. So I need to add them to my View
class as abstract
methods and thats me telling TypeScript, don't worry about it, these methods will eventually exist like so:
import { User } from "../models/User";
export abstract class View {
constructor(public parent: Element, public model: User) {
this.bindModel();
}
abstract eventsMap(): { [key: string]: () => void };
abstract template(): string;
bindModel(): void {
this.model.on("change", () => {
this.render();
});
}
bindEvents(fragment: DocumentFragment): void {
const eventsMap = this.eventsMap();
for (let eventKey in eventsMap) {
const [eventName, selector] = eventKey.split(":");
fragment.querySelectorAll(selector).forEach((element) => {
element.addEventListener(eventName, eventsMap[eventKey]);
});
}
}
render(): void {
this.parent.innerHTML = "";
const templateElement = document.createElement("template");
templateElement.innerHTML = this.template();
this.bindEvents(templateElement.content);
this.parent.append(templateElement.content);
}
}