The Dynamic Form Builder introspects a PostGIS table or a GeoPackage vector layer and generates a complete, validated data-entry form — labels, types, options, geometry handling, and layout — then renders it to live HTML. Pair it with the offline-capable field-collection PWA to collect, edit, and export spatial records with zero infrastructure.
No more re-keying column names into form fields by hand. The service reads the real column metadata — data type, nullable, max-length, precision, primary/foreign keys, geometry type and SRID — and turns each column into a typed, validated FormField. Exclude the noise, keep the structure.
/generate/postgis) and GPKG vector layers (/generate/gpkg); schema preview for both before you commit.Text, Number, Date/DateTime, Boolean, Select, Geometry, Json, Color, Range and more — with auto-generated labels and grouping.created_by.// GPKG layer → typed form (shared by PostGIS path) { "formName": "Building Survey", "title": "Building Survey Data Entry", "filePath": "Data/GPKG/survey_points.gpkg", "layerName": "survey_points", "geometryColumn": "geom", "primaryKey": "fid", "options": { "includeGeometry": true, "groupRelatedFields": true, "generateValidation": true, "excludedColumns": ["created_by", "updated_at"] } } → DynamicForm with N typed FormFields → render to HTML / React / Vue / Angular
Every FormField carries its own type, constraints, options, validation rules, and the original ColumnInfo it was derived from — so the form stays truthful to the underlying table even after you override individual fields.
Reads data_type, nullability, max_length, precision/scale, PK/FK, and is_geometry + geometry_type + srid straight from the layer.
autoGenerateLabels humanizes column names; groupRelatedFields clusters them into collapsible FormGroups and FormSections.
generateValidation emits Required, MinLength/MaxLength, MinValue/MaxValue, Pattern, email/url/phone rules per field.
Per-field fieldOverrides let you swap widgets, set defaults, placeholders, help text, or mark a column read-only — without touching the source table.
Geometry columns map to a Geometry field type; opt in via includeGeometry so the form can capture or edit the feature shape alongside attributes.
Three starters — basic, grouped, complete — returned from GET /api/dynamicform/templates to bootstrap a new survey fast.
| Capability | Endpoint | Notes |
|---|---|---|
| Generate (generic) | POST /api/dynamicform/generate | Single request body, picks source by DataSourceType |
| Generate from PostGIS | POST /api/dynamicform/generate/postgis | Connection string + table + schema + geom/PK columns |
| Generate from GPKG | POST /api/dynamicform/generate/gpkg | File path + layer name + geom/PK columns |
| Preview | POST /api/dynamicform/preview | Estimated field count & layout, no full generate |
| Schema | POST /api/dynamicform/schema/{postgis,gpkg} | Raw column metadata before building a form |
| Render | POST /api/dynamicform/{id}/render | Returns html + css + javascript |
| Standalone HTML | GET /api/dynamicform/{id}/html?theme= | Full <!DOCTYPE> page, ready to host |
| Manage | GET · DELETE /api/dynamicform/{id} | Fetch or remove a stored form |
| Templates | GET /api/dynamicform/templates | basic · grouped · complete presets |
In-app designer ships at /form-builder.html with PostGIS / GPKG tabs, options checkboxes, and a live Form Preview panel. Source: Controllers/DynamicFormController.cs, Services/DynamicFormService.cs, Services/FormRenderingService.cs, Models/FormModels.cs.
The FormRenderFormat enum emits to the framework you already use — so a generated survey can drop straight into an existing app, not just the in-app preview.
Standalone, themed HTML with inline CSS + JS — host it anywhere or embed it in the desktop preview.
React-renderable output for Next.js / SPA integration.
Vue-renderable output for Vue 3 apps.
Angular-renderable output for enterprise Angular shells.
Portable JSON Schema for any RJSF-compatible renderer or downstream pipeline.
Pass ?theme=default on the HTML route to swap the look without regenerating the form.
A bundled Next.js PWA (geospatial-form-builder) turns generated designs into a real data-collection app. Built on MapLibre GL JS and DuckDB-WASM, it runs fully offline with no CDN dependencies, stores records in-browser, and exports to the formats your GIS expects.
// offline PWA stack (no CDN, no internet required) { "name": "geospatial-form-builder", "dependencies": { "next": "^16.2.10", "react": "^19.2.7", "maplibre-gl": "^5.24.0", "react-hook-form": "^7.81.0", "lets-form": "^0.13.1" }, "devDependencies": { "@ducanh2912/next-pwa": "^10.2.9", "tailwindcss": "^4.3.3" } } → DuckDB-WASM via POST /api/duckdb/{id}/query → installable, air-gap-ready
The FormBuilder, FormDesigner, and specialized fields below are the building blocks the PWA composes — each driven by a JSON Schema + UI Schema pair.
Render a schema-driven form bound to a DuckDB table; onSubmit/onChange/onError hooks, readonly & disabled modes, reset button.
Visual schema editor with live preview — edit JSON Schema + UI Schema side by side and save the result.
Capture Lat/Long (DD & DMS), MGRS, USNG, GARS — with optional map click-to-select.
Drag-and-drop photos, video, and documents; preview, type/size validation, stored as blobs.
Inline add / edit / remove child records with a sortable, filterable, paginated table view.
ConditionalField shows fields on rules; ChainedSelectField loads dependent options async.
VoiceEnabledForm + VoiceFormControl fill fields by voice command (Qwen3-backed).
Inline translate between languages and read-back text-to-speech for accessibility.
Update previously collected records in place — versioned edits, not duplicate rows.
Generate validated forms from the layers you already have, render them anywhere, and collect offline — all from one desktop.