Commit 3ae2c7a9 authored by Daniel Bluhm's avatar Daniel Bluhm

Generate form by reflection

Signed-off-by: Daniel Bluhm's avatarDaniel Bluhm <bluhmdj@ornl.gov>
parent 921d74cc
/**
* Person DataElement
* Person DataElement.
* In the future, we hope to be able to generate data structures like this
* directly from DataElement Spec classes.
*/
import { DataElement } from "./data-element";
......
import {css, customElement, html, LitElement, property} from 'lit-element';
import {css, customElement, html, LitElement, property, TemplateResult} from 'lit-element';
import '@vaadin/vaadin-text-field';
import '@vaadin/vaadin-checkbox';
import { Person } from './Person';
import { DataElement } from './data-element';
/**
* Tasks:
* *This class should be templated or take a function call back in place of updateDataElement and loadData.
* Tasks:
* *This class should be templated or take a function call back in place of
* updateDataElement and loadData.
* *Add documentation as required.
* *Remove console debug statements
* *This is just an example so the rest doesn't matter much, (the rest being changing the render() function, etc.).
* *This is just an example so the rest doesn't matter much, (the rest being
* changing the render() function, etc.).
*/
@customElement("renderer-template")
class Renderer extends LitElement {
/**
* This is the default data value. It is the empty string and indicates that the JSON has not yet been received from the server.
*/
person = new Person();
person: Person = new Person();
@property({type: String})
dataElementJSON = '';
......@@ -29,63 +30,94 @@ class Renderer extends LitElement {
constructor() {
super();
console.log("Constructed");
}
updateFirstName(e: {target: HTMLInputElement}) {
// First, the event data needs to be read into the local structure
this.person.firstName = e.target.value;
// Second, dump into the JSON property
this.dataElementJSON = JSON.stringify(this.person);
// Notify the listeners of the change.
this.dispatchEvent(new CustomEvent(
'data-changed',
{bubbles: true, composed: true, detail: e.target.value}
));
loadData() {
this.person = <Person> JSON.parse(this.dataElementJSON);
}
updateLastName(e: {target: HTMLInputElement}) {
this.person.lastName = e.target.value;
this.dataElementJSON = JSON.stringify(this.person);
this.dispatchEvent(new CustomEvent(
'data-changed',
{bubbles: true, composed: true, detail: e.target.value}
));
/**
* Create an updater method for updating the objects field on form events.
* @param obj holding object of field
* @param field field for which an updater is generated
* @returns updater method
*/
fieldUpdater(obj: object, field: string):
(e: {target: HTMLInputElement}) => void
{
let that = this;
return function(e: {target: HTMLInputElement}) {
if (typeof Reflect.get(obj, field) === 'number') {
Reflect.set(obj, field, Number(e.target.value))
} else if (typeof Reflect.get(obj, field) === 'string') {
Reflect.set(obj, field, e.target.value);
} else if (typeof Reflect.get(obj, field) === 'boolean') {
Reflect.set(obj, field, e.target.checked);
}
that.dataElementJSON = JSON.stringify(that.person);
that.dispatchEvent(new CustomEvent(
'data-changed',
{bubbles: true, composed: true, detail: e.target.value}
));
};
}
loadData() {
this.person = <Person> JSON.parse(this.dataElementJSON);
console.log("dEJ-ld = ");
console.log(this.dataElementJSON);
console.log("dataElement-ld = ")
console.log(this.person);
console.log(this.person.firstName, this.person.lastName);
/**
* Create input form element for the given field.
* @param obj holding object of field
* @param field field for which input is generated
* @returns html template result
*/
fieldInput(obj: object, field: string): TemplateResult {
if (typeof Reflect.get(obj, field) === 'boolean') {
return html`
<vaadin-checkbox
value="${field}"
?checked=${Reflect.get(obj, field)}
@change=${this.fieldUpdater(obj, field)}
>${field}</vaadin-checkbox>
`;
} else {
return html`
<vaadin-text-field
label="${field}"
.value=${Reflect.get(obj, field)}
@input=${this.fieldUpdater(obj, field)}
></vaadin-text-field>
`;
}
}
render() {
// Might clean this up a bit - remove some of the <h2> statements.
/**
* Create a form for the passed DataElement.
*
* In this experiment, forms are generated by inspecting the data element.
* In the future, we hope to generate these forms directly from the DataElement
* Spec classes during Annotation Processing.
* @param element element for which a form will be generated
* @returns form html
*/
dataElementForm(element: DataElement): TemplateResult {
let form = html``;
for (let field in element) {
form = html`${form}${this.fieldInput(element, field)}`;
}
return form;
}
/**
* Render this LitElement.
*/
render() {
return html`
<script>${this.loadData()}</script>
<h1>Greetings ${this.person.firstName}!</h1>
<h1>Greetings ${this.person.age} year old ${this.person.firstName}!</h1>
<div>
<vaadin-text-field
label="First Name"
.value=${this.person.firstName}
@input=${this.updateFirstName}
></vaadin-text-field>
<vaadin-text-field
label="Last Name"
.value=${this.person.lastName}
@input=${this.updateLastName}
></vaadin-text-field>
${this.dataElementForm(this.person)}
</div>
<pre>${JSON.stringify(this.person, null, 2)}</pre>
<h2>${this.person.description}</h2>
<h2>${this.person.name}</h2>
`;
}
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment