Added new converter template that can be used to convert a value into something that can be rendered.

This commit is contained in:
MattMo 2023-07-25 23:21:54 -07:00
parent 841d03d2c3
commit f531a518b9

View File

@ -385,7 +385,7 @@ class IgniteTemplate {
/**
* Sets the inner html of the element to be constructed by this template.
* @param {String|IgniteProperty} value InnerHTML to set for element. If a property is passed the html will auto update.
* @param {String|IgniteProperty|IgniteProperty[]} value InnerHTML to set for element. If a property is passed the html will auto update.
* @param {Function} converter Optional function that can be used to convert the value if needed.
* @returns This ignite template so funciton calls can be chained.
*/
@ -2528,6 +2528,128 @@ class list extends IgniteTemplate {
}
}
/**
* A special ignite template that converts a value to HTML or a Template and supports
* dynamic value changes and dynamic converter changes.
*/
class converter extends IgniteTemplate {
constructor(value, converter) {
super();
if (converter instanceof IgniteProperty) {
this._callbacks.push(converter.attachOnChange((oldValue, newValue) => this.onConverterChanged(newValue)));
this.converter = converter.value;
} else if (converter instanceof Function) {
this.converter = converter;
}
if (value instanceof IgniteProperty) {
this._callbacks.push(value.attachOnChange((oldValue, newValue) => this.onValueChanged(newValue)));
this._callbacks.push(value.attachOnPush((list, items) => this.onValueChanged(list)));
this._callbacks.push(value.attachOnUnshift((list, items) => this.onValueChanged(list)));
this._callbacks.push(value.attachOnPop(list => this.onValueChanged(list)));
this._callbacks.push(value.attachOnShift(list => this.onValueChanged(list)));
this._callbacks.push(value.attachOnSplice((list, start, deleteCount, items) => this.onValueChanged(list)));
this.value = value.value;
} else if (value) {
this.value = value;
}
var child = this.value;
if (this.converter) {
child = this.converter(this.value);
}
if (child instanceof IgniteTemplate) {
this.child = child;
} else if (child) {
this.child = new html(child);
} else {
this.child = null;
}
this.tagName = "converter";
}
construct(parent, sibling) {
//Don't construct if we have no parent, no sibling and no element.
if (!parent && !sibling && !this.element) {
return;
}
if (!this.element) {
this.element = window.document.createTextNode(""); //Use a textnode as our placeholder
if (sibling) {
sibling.parentElement.insertBefore(this.element, sibling);
} else {
parent.appendChild(this.element);
}
} else {
parent = this.element.parentElement;
}
if (this.child) {
this.child.construct(parent, this.element);
}
}
onValueChanged(newValue) {
this.value = newValue;
if (this.child) {
this.child.deconstruct();
}
var child = newValue;
if (this.converter) {
child = this.converter(child);
}
if (child instanceof IgniteTemplate) {
this.child = child;
this.child.construct(null, this.element);
} else if (child) {
this.child = new html(child);
this.child.construct(null, this.element);
} else {
this.child = null;
}
}
onConverterChanged(newConverter) {
this.converter = newConverter;
if (this.child) {
this.child.deconstruct();
}
var child = this.value;
if (this.converter) {
child = this.converter(child);
}
if (child instanceof IgniteTemplate) {
this.child = child;
this.child.construct(null, this.element);
} else if (child) {
this.child = new html(child);
this.child.construct(null, this.element);
} else {
this.child = null;
}
}
}
/**
* A slot template that mimicks the functionality of a slot element in Web Components. This can
* be used to place children of a IgniteElement anywhere in the DOM. Slots don't actually construct an element,
@ -3417,6 +3539,7 @@ export {
text,
html,
list,
converter,
a,
input,
textarea,