Add input validation
This commit is contained in:
parent
ef593654f4
commit
1488caf362
8 changed files with 66 additions and 17 deletions
|
@ -8,6 +8,7 @@ import {ImageCarouselWithUploadConstructor} from "../../UI/Image/ImageCarouselWi
|
|||
import BikeStationOperator from "../Questions/bike/StationOperator";
|
||||
import Translations from "../../UI/i18n/Translations";
|
||||
import ParkingOperator from "../Questions/bike/ParkingOperator";
|
||||
import {TagRenderingOptions} from "../TagRendering";
|
||||
|
||||
|
||||
export default class BikeParkings extends LayerDefinition {
|
||||
|
@ -27,7 +28,15 @@ export default class BikeParkings extends LayerDefinition {
|
|||
this.elementsToShow = [
|
||||
new ImageCarouselWithUploadConstructor(),
|
||||
//new ParkingOperator(),
|
||||
new ParkingType()
|
||||
new ParkingType(),
|
||||
new TagRenderingOptions({
|
||||
question: "How many bicycles fit in this bicycle parking?",
|
||||
freeform: {
|
||||
key: "capacity",
|
||||
renderTemplate: "Place for {capacity} bikes",
|
||||
template: "$nat$ bikes fit in here"
|
||||
}
|
||||
})
|
||||
];
|
||||
this.wayHandling = LayerDefinition.WAYHANDLING_CENTER_AND_WAY;
|
||||
|
||||
|
|
|
@ -15,9 +15,19 @@ import {FixedInputElement} from "../UI/Input/FixedInputElement";
|
|||
import {RadioButton} from "../UI/Input/RadioButton";
|
||||
import Translations from "../UI/i18n/Translations";
|
||||
import Locale from "../UI/i18n/Locale";
|
||||
import {FloatField, IntField, StringField} from "../UI/Input/PhoneField";
|
||||
|
||||
export class TagRenderingOptions implements TagDependantUIElementConstructor {
|
||||
|
||||
|
||||
public static inputValidation = {
|
||||
"$": (str) => true,
|
||||
"string": (str) => true,
|
||||
"int": (str) => str.indexOf(".") < 0 && !isNaN(Number(str)),
|
||||
"nat": (str) => str.indexOf(".") < 0 && !isNaN(Number(str)) && Number(str) > 0,
|
||||
"float": (str) => !isNaN(Number(str)),
|
||||
}
|
||||
|
||||
/**
|
||||
* Notes: by not giving a 'question', one disables the question form alltogether
|
||||
*/
|
||||
|
@ -334,13 +344,20 @@ class TagRendering extends UIElement implements TagDependantUIElement {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
const prepost = Translations.W(freeform.template).InnerRender().split("$");
|
||||
const type = prepost[1];
|
||||
const isValid = TagRenderingOptions.inputValidation[type];
|
||||
|
||||
const pickString =
|
||||
(string) => {
|
||||
(string: any) => {
|
||||
if (string === "" || string === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
if (!isValid(string)) {
|
||||
return undefined;
|
||||
}
|
||||
const tag = new Tag(freeform.key, string);
|
||||
|
||||
if (freeform.extraTags === undefined) {
|
||||
return tag;
|
||||
}
|
||||
|
@ -369,8 +386,7 @@ class TagRendering extends UIElement implements TagDependantUIElement {
|
|||
toString: toString
|
||||
});
|
||||
|
||||
const prepost = Translations.W(freeform.template).InnerRender().split("$$$");
|
||||
return new InputElementWrapper(prepost[0], textField, prepost[1]);
|
||||
return new InputElementWrapper(prepost[0], textField, prepost[2]);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -5,11 +5,12 @@ import {UIEventSource} from "../UI/UIEventSource";
|
|||
|
||||
export class QueryParameters {
|
||||
|
||||
private static order: string [] = ["layout","test","zoom","lat","lon"];
|
||||
private static order: string [] = ["layout","test","z","lat","lon"];
|
||||
private static knownSources = QueryParameters.init();
|
||||
|
||||
private static addOrder(key){
|
||||
if(this.order.indexOf(key) < 0){
|
||||
console.log("Adding order", key)
|
||||
this.order.push(key)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,4 +8,5 @@ export abstract class InputElement<T> extends UIElement{
|
|||
|
||||
abstract IsValid(t: T) : boolean;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import {UIElement} from "../UIElement";
|
||||
import {UIEventSource} from "../UIEventSource";
|
||||
import {InputElement} from "./InputElement";
|
||||
import {FixedUiElement} from "../Base/FixedUiElement";
|
||||
import Translations from "../i18n/Translations";
|
||||
|
||||
|
||||
|
@ -17,9 +16,23 @@ export class TextField<T> extends InputElement<T> {
|
|||
private _fromString?: (string: string) => T;
|
||||
private _toString: (t: T) => string;
|
||||
|
||||
|
||||
constructor(options: {
|
||||
/**
|
||||
* Shown as placeholder
|
||||
*/
|
||||
placeholder?: string | UIElement,
|
||||
|
||||
/**
|
||||
* Converts the T to a (canonical) string
|
||||
* @param t
|
||||
*/
|
||||
toString: (t: T) => string,
|
||||
/**
|
||||
* Converts the string to a T
|
||||
* Returns undefined if invalid
|
||||
* @param string
|
||||
*/
|
||||
fromString: (string: string) => T,
|
||||
value?: UIEventSource<T>
|
||||
}) {
|
||||
|
@ -66,9 +79,9 @@ export class TextField<T> extends InputElement<T> {
|
|||
}
|
||||
|
||||
InnerRender(): string {
|
||||
return "<form onSubmit='return false' class='form-text-field'>" +
|
||||
"<input type='text' placeholder='" + this._placeholder.InnerRender() + "' id='text-" + this.id + "'>" +
|
||||
"</form>";
|
||||
return `<form onSubmit='return false' class='form-text-field'>` +
|
||||
`<input type='text' placeholder='${this._placeholder.InnerRender()}' id='text-${this.id}'>` +
|
||||
`</form>`;
|
||||
}
|
||||
|
||||
InnerUpdate() {
|
||||
|
@ -76,6 +89,11 @@ export class TextField<T> extends InputElement<T> {
|
|||
if (field === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.mappedValue.addCallback((data) => {
|
||||
field.className = this.mappedValue.data !== undefined ? "valid" : "invalid";
|
||||
});
|
||||
|
||||
const self = this;
|
||||
field.oninput = () => {
|
||||
// @ts-ignore
|
||||
|
|
|
@ -386,6 +386,10 @@ export default class Translations {
|
|||
skippedQuestions: new T({
|
||||
en: "Some questions are skipped",
|
||||
nl: "Sommige vragen zijn overgeslaan"
|
||||
}),
|
||||
number: new T({
|
||||
en: "number",
|
||||
nl: "getal"
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,10 @@ form {
|
|||
display: inline;
|
||||
}
|
||||
|
||||
.invalid {
|
||||
box-shadow: 0 0 10px #ff5353;
|
||||
}
|
||||
|
||||
#leafletDiv {
|
||||
height: 100%;
|
||||
}
|
||||
|
|
10
test.ts
10
test.ts
|
@ -1,9 +1,5 @@
|
|||
import {QueryParameters} from "./Logic/QueryParameters";
|
||||
import {IntField} from "./UI/Input/PhoneField";
|
||||
|
||||
console.log("Hi");
|
||||
|
||||
const layout = QueryParameters.GetQueryParameter("layout").addCallback(console.log)
|
||||
|
||||
console.log("Layout is", layout.data)
|
||||
|
||||
window.setTimeout(() => {layout.setData("XXX"), 2000})
|
||||
const f = new IntField().AttachTo("maindiv")
|
||||
f.GetValue().addCallback(console.log)
|
Loading…
Reference in a new issue