Make et2-textbox as a WebComponent

Not all attributes are handled yet, but value cycle is working
This commit is contained in:
nathan 2021-07-22 14:54:10 -06:00
parent ad00156113
commit 5fee9fcafe
9 changed files with 127 additions and 30 deletions

View File

@ -60,8 +60,7 @@ export class Et2Button extends Et2InputWidget(Et2Widget(LionButton))
// Define a default click handler
// If a different one gets set via attribute, it will be used instead
this.onclick = (typeof this.onclick === "function") ? this.onclick : () => {
debugger;
this.getInstanceManager().submit();
return this.getInstanceManager().submit();
};
}
@ -82,6 +81,7 @@ export class Et2Button extends Et2InputWidget(Et2Widget(LionButton))
_handleClick(event: MouseEvent) : boolean
{
debugger;
// ignore click on readonly button
if (this.disabled) return false;

View File

@ -0,0 +1,50 @@
/**
* EGroupware eTemplate2 - Button widget
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
* @subpackage api
* @link https://www.egroupware.org
* @author Nathan Gray
*/
import {css,html} from "../../../node_modules/@lion/core/index.js";
import {LionInput} from "../../../node_modules/@lion/input/index.js";
import {Et2InputWidget} from "./et2_core_inputWidget";
import {Et2Widget} from "./et2_core_inheritance";
export class Et2Textbox extends Et2InputWidget(Et2Widget(LionInput))
{
static get styles() {
return [
...super.styles,
css`
/* Custom CSS */
`,
];
}
static get properties() {
return {
...super.properties,
value: {attribute: true},
onclick: {type: Function}
}
}
constructor()
{
debugger;
super();
}
connectedCallback()
{
super.connectedCallback();
}
}
customElements.define("et2-textbox",Et2Textbox);

View File

@ -260,7 +260,7 @@ export class ClassWithAttributes extends ClassWithInterfaces
*/
type Constructor<T = {}> = new (...args: any[]) => T;
export const Et2Widget = <T extends Constructor>(superClass: T) => {
export const Et2Widget = <T extends Constructor<LitElement>>(superClass: T) => {
class Et2WidgetClass extends superClass implements et2_IDOMNode {
/** et2_widget compatability **/
@ -271,6 +271,12 @@ export const Et2Widget = <T extends Constructor>(superClass: T) => {
/** WebComponent **/
static get properties() {
return {
...super.properties,
/**
* Tooltip which is shown for this element on hover
*/
statustext: {type: String},
label: {type: String},
onclick: {
type: Function,
@ -372,7 +378,16 @@ export const Et2Widget = <T extends Constructor>(superClass: T) => {
// TODO: children
}
loadingFinished()
{}
{
/**
* This is needed mostly as a bridge between non-WebComponent widgets and
* connectedCallback(). It's not really needed if the whole tree is WebComponent.
* WebComponents can be added as children immediately after createion, and they handle the
* rest themselves with their normal lifecycle (especially connectedCallback(), which is kind
* of the equivalent of doLoadingFinished()
*/
this.getParent().getDOMNode(this).append(this);
}
getWidgetById(_id)
{
if (this.id == _id) {
@ -523,5 +538,19 @@ export const Et2Widget = <T extends Constructor>(superClass: T) => {
return false;
}
};
function applyMixins(derivedCtor: any, baseCtors: any[]) {
baseCtors.forEach(baseCtor => {
Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
if (name !== 'constructor') {
derivedCtor.prototype[name] = baseCtor.prototype[name];
}
});
});
}
// Add some more stuff in
applyMixins(Et2WidgetClass, [ClassWithInterfaces]);
return Et2WidgetClass as unknown as Constructor<et2_IDOMNode> & T;
}

View File

@ -388,7 +388,7 @@ export class et2_inputWidget extends et2_valueWidget implements et2_IInput, et2_
* This mixin will allow any LitElement to become an Et2InputWidget
*
* Usage:
* export class Et2Button extends Et2InputWidget(BXButton) {...}
* export class Et2Button extends Et2InputWidget(Et2Widget(LitWidget)) {...}
*/
type Constructor<T = {}> = new (...args: any[]) => T;
@ -399,18 +399,28 @@ export const Et2InputWidget = <T extends Constructor>(superClass: T) => {
protected value: string | number | Object;
protected _oldValue: string | number | Object;
/** WebComponent **/
static get properties() {
return {
...super.properties,
value: {attribute: false}
};
}
constructor() {
super();
// Add statustext hover
}
set_value(new_value)
{
this.modelValue=new_value;
}
getValue()
{
var node = this.getInputNode();
if (node)
{
var val = jQuery(node).val();
return val;
}
return this._oldValue;
return this._inputNode.value;
}
isDirty()
@ -464,19 +474,8 @@ export const Et2InputWidget = <T extends Constructor>(superClass: T) => {
getInputNode()
{
return this.node;
}
/**
* These belongs somewhere else/higher, I'm just getting it to work
*/
loadingFinished()
{}
getWidgetById(_id)
{
if (this.id == _id) {
return this;
}
// From LionInput
return this._inputNode;
}
};
return Et2InputWidgetClass as unknown as Constructor<et2_IInput> & T;

View File

@ -25,6 +25,7 @@ import {et2_IDOMNode, et2_IInputNode} from "./et2_core_interfaces";
// fixing circular dependencies by only importing type
import type {et2_container} from "./et2_core_baseWidget";
import type {et2_inputWidget, et2_input} from "./et2_core_inputWidget";
import {Et2InputWidget} from "./et2_core_inputWidget";
/**
* The registry contains all XML tag names and the corresponding widget
@ -758,7 +759,7 @@ export class et2_widget extends ClassWithAttributes
}
widget.setParent(this);
var mgr = widget.getArrayMgr("content");
debugger;
// Apply any set attributes - widget will do its own coercion
_node.getAttributeNames().forEach(attribute => {
let attrValue = _node.getAttribute(attribute);
@ -776,6 +777,22 @@ export class et2_widget extends ClassWithAttributes
widget.setAttribute(attribute, attrValue);
});
if(widget_class.getPropertyOptions("value") && widget.set_value)
{
if (mgr != null) {
let val = mgr.getEntry(widget.id, false, true);
if (val !== null)
{
widget.setAttribute("value", val);
}
}
// Check for already inside namespace
if(this._createNamespace() && this.getArrayMgr("content").perspectiveData.owner == this)
{
widget.setAttribute("value", this.getArrayMgr("content").data);
}
}
// Children need to be loaded
//this.loadFromXML(_node);
return widget;

View File

@ -24,6 +24,7 @@ import {et2_tabbox} from "./et2_widget_tabs";
import '../jsapi/egw_json.js';
import {egwIsMobile} from "../egw_action/egw_action_common.js";
import './et2-button';
import './et2-textbox';
/* Include all widget classes here, we only care about them registering, not importing anything*/
import './et2_widget_vfs'; // Vfs must be first (before et2_widget_file) due to import cycle
import './et2_widget_template';

View File

@ -179,4 +179,4 @@ class Textbox extends Etemplate\Widget
}
}
}
Etemplate\Widget::registerWidget(__NAMESPACE__.'\\Textbox', array('textbox','text','int','integer','float','hidden','colorpicker','hidden'));
Etemplate\Widget::registerWidget(__NAMESPACE__.'\\Textbox', array('et2-textbox','textbox','text','int','integer','float','hidden','colorpicker','hidden'));

View File

@ -154,7 +154,7 @@
<rows>
<row class="dialogHeader">
<description value="Title" for="info_subject"/>
<textbox statustext="a short subject for the entry" id="info_subject" class="et2_fullWidth et2_required" maxlength="255" span="4" tabindex="1"/>
<et2-textbox statustext="a short subject for the entry" id="info_subject" class="et2_fullWidth et2_required" maxlength="255" span="4" tabindex="1"></et2-textbox>
<textbox type="integer" id="info_number" readonly="true"/>
<appicon src="infolog" for="info_number"/>
</row>

View File

@ -47,6 +47,7 @@
"dependencies": {
"@lion/button": "^0.14.1",
"@lion/core": "^0.18.1",
"@lion/input": "^0.15.3",
"carbon-components": "^10.37.0",
"carbon-web-components": "^1.14.1",
"lit-element": "^2.5.1",