Reputation: 103
I have a problem. I need to write a common function (class) that can both accept HTMLElements and give them using typescript
An example of attempts
class Create {
protected element: HTMLElement;
constructor(parent: ParentNode, tag: string, classNames: string, value?: string, attr?: Record<string, unknown>) {
this.element = document.createElement(tag);
this.element.classList.add(...classNames.split(' '));
if (typeof value === 'string') {
this.element.innerHTML = value;
}
if ('appendChild' in parent) {
parent.appendChild(this.element);
}
if (attr) {
for (const key in attr) {
this.element.setAttribute(key, <string>attr[key]);
}
}
}
append(element: ElementNode) {
this.element.append(element);
}
}
This function will be auxiliary to create elements on the page
example of available elements
const wrapper = new Create(this.container, 'div', styles.wrapper);
const headerWrapper = document.createElement('div') as HTMLDivElement;
const headerNav = document.createElement('nav');
const headerList = document.createElement('ul');
const headerLogo = document.createElement('div');
const headerLogoLink = document.createElement('a');
const headerLogoTitle = document.createElement('h2');
headerLogo.classList.add(styles.headerWrapperLogo);
headerLogoLink.classList.add(styles.headerWrapperLogoLink);
headerLogoLink.href = '/';
headerLogoTitle.classList.add(styles.headerWrapperLogoTitle);
headerLogoTitle.innerHTML = 'Manga Store';
headerLogo.append(headerLogoLink);
headerLogoLink.append(headerLogoTitle);
headerWrapper.append(headerLogo);
headerWrapper.classList.add(styles.headerWrapper);
headerNav.classList.add(styles.headerWrapperNav);
headerList.classList.add(styles.headerWrapperNavList);
btnHeader.forEach((btns) => {
const headerListItem = document.createElement('li');
const headerListItemLink = document.createElement('a') as HTMLAnchorElement;
headerListItem.classList.add(styles.headerWrapperNavListItem);
headerListItemLink.classList.add(styles.headerWrapperNavListItemLink);
headerListItemLink.href = `#${btns.id}`;
headerListItemLink.innerText = btns.content;
wrapper.append(headerWrapper);
headerWrapper.append(headerNav);
headerNav.append(headerList);
headerList.append(headerListItem);
headerListItem.append(headerListItemLink);
Or tell me if it is possible to rewrite the "Abstract" class (see example) to get the desired result
abstract class Template {
protected container: HTMLElement;
static content = {};
protected constructor(id: string, classNames?: string) {
this.container = document.createElement('main');
if (typeof classNames === 'string') {
this.container.classList.add(classNames);
}
this.container.id = id;
}
protected header(content: string) {
const title = document.createElement('h1');
title.innerText = content;
return title;
}
render() {
return this.container;
}
}
When I tried this code:
const wrapper = new Create(document.body, 'div', '1')
const subWrap = new Create(wrapper, 'div', '2') // ???
I got this error:
Upvotes: 0
Views: 741
Reputation: 103
export type Values = string | null | unknown;
export type ParentElem = ParentNode | Create | null;
class Create {
element: Element;
constructor(tag: string, classNames: string, parent?: ParentElem, value?: Values, attr?: Record<string, unknown>) {
this.element = document.createElement(tag);
this.element.classList.add(...classNames.split(' '));
if (typeof value === 'string') {
this.element.innerHTML = value;
}
parent ? (!(parent instanceof Create) ? parent.appendChild(this.element) : null) : undefined;
if (attr) {
for (const key in attr) {
this.element.setAttribute(key, <string>attr[key]);
}
}
}
append(element: Create | Node | string) {
return element ? (!(element instanceof Create) ? this.element.append(element) : null) : undefined;
}
remove(element = this.element) {
return element ? (!(element instanceof Create) ? this.element.remove() : null) : undefined;
}
}
ternary operators helped me, and a few checks, to protect against surprises in the form of undefind and null, I also created two additional methods for adding and removing elements, maybe it will come in handy for someone)
Upvotes: 0
Reputation: 187034
If you want Create
's append
method to support being passed a ParentNode
or an instance of Create
, then you just need to type that argument with a union.
For example:
constructor(
parent: ParentNode | Create, // changed this type
tag: string,
classNames: string,
value?: string,
attr?: Record<string, unknown>
) {
//...
}
Upvotes: 1