Fixes to JsonForm and json
* Update model when JsonForm.editable set false * Bugfixes in jsonPatch
This commit is contained in:
@@ -30,14 +30,14 @@
|
|||||||
--jsl-dialog-bgcolor: #ffd;
|
--jsl-dialog-bgcolor: #ffd;
|
||||||
--jsl-dialog-bordercolor: #835f10;
|
--jsl-dialog-bordercolor: #835f10;
|
||||||
.-title::before {
|
.-title::before {
|
||||||
content: '✔ ';
|
content: '⁉️ ';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.-style-error {
|
&.-style-error {
|
||||||
--jsl-dialog-bgcolor: #fcc;
|
--jsl-dialog-bgcolor: #fcc;
|
||||||
--jsl-dialog-bordercolor: #bb3434;
|
--jsl-dialog-bordercolor: #bb3434;
|
||||||
.-title::before {
|
.-title::before {
|
||||||
content: '⚠️ ';
|
content: '⛔ ';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.-style-warning {
|
&.-style-warning {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<script type="module">
|
<script type="module">
|
||||||
import { el } from './dom.js';
|
import { el } from './dom.js';
|
||||||
import { dialog } from './dialog.js';
|
import { dialog } from './dialog.js';
|
||||||
import { JsonForm, TextField, SelectField } from './jsonform.js';
|
import { JsonForm, TextField, NumericField } from './jsonform.js';
|
||||||
import { jsonQuery, jsonPatch, tokenizePath } from './json.js';
|
import { jsonQuery, jsonPatch, tokenizePath } from './json.js';
|
||||||
import { date } from './date.js';
|
import { date } from './date.js';
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ document.body.appendChild(root);
|
|||||||
const userForm = new JsonForm();
|
const userForm = new JsonForm();
|
||||||
userForm.layout.addRow()
|
userForm.layout.addRow()
|
||||||
.append(new TextField({ label:"Username", width:70, path:".username" }))
|
.append(new TextField({ label:"Username", width:70, path:".username" }))
|
||||||
.append(new TextField({ label:"ID", path:".id", locked:true }));
|
.append(new NumericField({ label:"ID", path:".id", locked:true }));
|
||||||
userForm.layout.addRow()
|
userForm.layout.addRow()
|
||||||
.append(new TextField({ label:"Created", width:50, path:".meta.created", locked:true }))
|
.append(new TextField({ label:"Created", width:50, path:".meta.created", locked:true }))
|
||||||
.append(new TextField({ label:"Updated", width:50, path:".meta.updated", locked:true }));
|
.append(new TextField({ label:"Updated", width:50, path:".meta.updated", locked:true }));
|
||||||
@@ -62,6 +62,9 @@ userForm.model = {
|
|||||||
|
|
||||||
btn3.addEventListener('click', () => {
|
btn3.addEventListener('click', () => {
|
||||||
userForm.editable = !userForm.editable;
|
userForm.editable = !userForm.editable;
|
||||||
|
if (!userForm.editable) {
|
||||||
|
console.log(userForm.model);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// console.log(tokenizePath(".foo.bar[1].title"));
|
// console.log(tokenizePath(".foo.bar[1].title"));
|
||||||
|
|||||||
2
json.js
2
json.js
@@ -90,7 +90,7 @@ function jsonPatch(json, path, value) {
|
|||||||
if (search === 'key') {
|
if (search === 'key') {
|
||||||
// find key tok in ptr
|
// find key tok in ptr
|
||||||
if (typeof ptr[tok] === 'undefined') {
|
if (typeof ptr[tok] === 'undefined') {
|
||||||
return defaultValue;
|
return json;
|
||||||
} else {
|
} else {
|
||||||
if (toks.length === 0) {
|
if (toks.length === 0) {
|
||||||
ptr[tok] = value;
|
ptr[tok] = value;
|
||||||
|
|||||||
@@ -56,6 +56,9 @@
|
|||||||
border: solid 1px var(--jsl-form-focused-outline);
|
border: solid 1px var(--jsl-form-focused-outline);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
&.-number-field {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
55
jsonform.js
55
jsonform.js
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
import { dom, el } from './dom.js';
|
import { dom, el } from './dom.js';
|
||||||
import { jsonQuery } from './json.js';
|
import { jsonQuery, jsonPatch } from './json.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This form encapsulates a form with a model and a layout.
|
* This form encapsulates a form with a model and a layout.
|
||||||
@@ -50,6 +50,7 @@ class JsonForm {
|
|||||||
|
|
||||||
refreshModel() {
|
refreshModel() {
|
||||||
// TODO go over the fields and update the model with any modified data
|
// TODO go over the fields and update the model with any modified data
|
||||||
|
this.#model = this.#layout.updateModel(this.#model);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -77,6 +78,11 @@ class FormLayout {
|
|||||||
this.#rows.forEach(row => row.modelUpdated(model));
|
this.#rows.forEach(row => row.modelUpdated(model));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateModel(model) {
|
||||||
|
this.#rows.forEach(row => model = row.updateModel(model));
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
setEditable(state) {
|
setEditable(state) {
|
||||||
this.#rows.forEach(row => row.setEditable(state));
|
this.#rows.forEach(row => row.setEditable(state));
|
||||||
}
|
}
|
||||||
@@ -110,6 +116,14 @@ class FormRow {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateModel(model) {
|
||||||
|
this.#fields.forEach(field => {
|
||||||
|
if (!field.options.path) return;
|
||||||
|
model = jsonPatch(model, field.options.path, field.value);
|
||||||
|
});
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
setEditable(state) {
|
setEditable(state) {
|
||||||
this.#fields.forEach(field => {
|
this.#fields.forEach(field => {
|
||||||
if (field.options.locked === true) return;
|
if (field.options.locked === true) return;
|
||||||
@@ -163,6 +177,15 @@ class FormField {
|
|||||||
return this.#el;
|
return this.#el;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the value without triggering any effects
|
||||||
|
*
|
||||||
|
* @param {*} value The new value
|
||||||
|
*/
|
||||||
|
updateValue(value) {
|
||||||
|
this.#value = value;
|
||||||
|
}
|
||||||
|
|
||||||
buildField() {
|
buildField() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,6 +215,35 @@ class TextField extends FormField {
|
|||||||
if (state) {
|
if (state) {
|
||||||
dom.apply(this.#input, { 'contenteditable':'plaintext-only' });
|
dom.apply(this.#input, { 'contenteditable':'plaintext-only' });
|
||||||
} else {
|
} else {
|
||||||
|
this.updateValue(this.#input.innerText);
|
||||||
|
dom.apply(this.#input, { 'contenteditable':null });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NumericField extends FormField {
|
||||||
|
#input = null;
|
||||||
|
buildField() {
|
||||||
|
if (!this.#input) {
|
||||||
|
this.#input = el.div({ class: '-field -number-field' })
|
||||||
|
this.el.appendChild(this.#input);
|
||||||
|
}
|
||||||
|
this.#input.innerText = this.value;
|
||||||
|
}
|
||||||
|
valueUpdated() {
|
||||||
|
this.#input.innerText = this.value;
|
||||||
|
}
|
||||||
|
getValue() {
|
||||||
|
if (this.options.float) {
|
||||||
|
return parseFloat(this.#input.innerText);
|
||||||
|
}
|
||||||
|
return parseInt(this.#input.innerText);
|
||||||
|
}
|
||||||
|
setEditable(state) {
|
||||||
|
if (state) {
|
||||||
|
dom.apply(this.#input, { 'contenteditable':'plaintext-only' });
|
||||||
|
} else {
|
||||||
|
this.updateValue(this.#input.innerText);
|
||||||
dom.apply(this.#input, { 'contenteditable':null });
|
dom.apply(this.#input, { 'contenteditable':null });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -222,6 +274,7 @@ export {
|
|||||||
FormRow,
|
FormRow,
|
||||||
FormField,
|
FormField,
|
||||||
TextField,
|
TextField,
|
||||||
|
NumericField,
|
||||||
DateField,
|
DateField,
|
||||||
SelectField,
|
SelectField,
|
||||||
CheckField,
|
CheckField,
|
||||||
|
|||||||
Reference in New Issue
Block a user