In this page
Gui Input
Web components comme with a number of inputs to handle all GreyCat types, but they also work well with js types.
You can specify the the exact input component you want, for example:
gui-input-string
will create a input of type textgui-input-number
will create a input of type number
But you don’t have to, by passing the value internally we will infer the type and return the appropriate component
<gui-input value="[1,2,3]">
will return agui-input-array
This also works by specifying the greycat type
<gui-input type="core::time">
will return agui-input-time
Reflexivity, Shared Types Front <-> Back
One of the most annoying parts of fullstack development is having to define the same types and forms twice — once for the backend and then again on the frontend. That’s where our abi really comes in handy. It’s built to cut out that duplication and make it way easier to keep everything in sync, so you’re not constantly switching between layers fixing mismatches or re-writing the same logic.
Adding a new attribute to the gcl type requires no extra changes to any of the front end code.
The following example leverages <gui-object>
to display the result returned by the greycat server, a more in depth explanation here
const el = document.createElement('div');
el.className = 'list';
const form = document.createElement('gui-input-object');
// Add the typed structure specified in gcl, currently all field are empty but we could prefill them with default values
form.value = new gc.project.Entry('One');
// You cold also build the input from the arguments of the function in gcl
// el.value = new gc.project.updateEntry$args();
const button = document.createElement('sl-button');
button.textContent = 'Execute';
const result = document.createElement('gui-object');
result.header = true; // Will display the qualified name of the type as module::type
button.onclick = async () => {
if (form.validate()) {
try {
const res = await gc.project.updateEntry.apply(null, [form.value]);
result.value = res;
} catch (err) {
result.value = err;
}
}
};
el.append(form, button, result);
enum EntryStatus {
good;
bad;
none;
}
type Entry {
name: String;
date: time;
status: EntryStatus;
open: bool;
value: float;
}
@expose
fn updateEntry(entry: Entry) {
// Here typically you would store it in the graph
return entry;
}
String
el = document.createElement('gui-input-string');
el.value = 'Hello, GreyCat!';
Number (int/float)
const el = document.createElement('gui-input-number');
el.value = 3.1415;
Boolean
const el = document.createElement('gui-input-bool');
el.value = true;
core::time
const el = document.createElement('gui-input-time');
el.value = gc.core.time.fromMs(Date.now());
core::duration
const el = document.createElement('gui-input-duration');
el.value = gc.core.duration.from_days(1);
Arrays
el = document.createElement('gui-input-array');
el.value = [1, 2, 3, 4, 5];
Js Map
const el = document.createElement('gui-input-map');
el.value = new Map([
['name', 'Bob'],
['age', 42],
]);
Enums
const el = document.createElement('gui-input-enum');
el.value = gc.core.TimeZone['Europe/Luxembourg'];
Objects
const el = document.createElement('gui-input-object');
el.value = new gc.project.Sensor(40, 2);
type Sensor {
valA: int;
valB: int;
}
Functions
const el = document.createElement('div');
el.className = 'list';
const fn = document.createElement('gui-input-fn');
fn.value = new gc.project.addTwoNumbers$args(40, 2);
const btn = document.createElement('sl-button');
btn.textContent = 'Execute';
btn.onclick = async () => {
try {
const res = await gc.project.addTwoNumbers.apply(null, fn.args);
result.textContent = `Result: ${res}`;
} catch (err) {
result.textContent = `${err}`;
}
};
const result = document.createElement('div');
el.append(fn, btn, result);
// in project.gcl
@expose
fn addTwoNumbers(a: int, b: int) {
return a + b;
}