Skip to content

Latest commit

 

History

History
64 lines (43 loc) · 2.93 KB

README.md

File metadata and controls

64 lines (43 loc) · 2.93 KB

FML: Fields, Models, Lists

A moderately opinionated library for building model-driven forms for web UIs.

WTF?

This library is intended to make building forms for web UIs stupid easy and 100% declarative. It is designed to be extensible to add additional control bindings, configurations, and validators.

It's "experimental" right now, but is stable enough to use. Feedback very welcome! Open issues and offer feedback!

Track progress towards a 1.0 release here.

Overview

FML provides a set of TypeScript declarations along with a small, extensible core to provide a means to bind declarations to the UI. Bindings can be provided to Web Components, React, Vue, Svelte, Angular, etc.

Conceptually, there are these three distinct types of form elements, each with their own purpose:

Fields

Fields are individual form controls and represent a model's primitive properties. These can represent the following types:

  • number
  • string
  • boolean
  • Date

Most often, they will be rendered as an <input /> of some type, but this is not a strict rule: For example, a property like description: string could be rendered to a more complex form control like a WYSIWYG editor. As long as the control holds a string value, it is a legitimate option to bind to a string property in your model.

Models

Models are objects: an aggregation of properties represented by Fields, nested Models, and Lists.

Lists

Lists are a collection of Fields, Models, or even nested Lists (e.g., a List of Workflows, where a Workflow is a List of WorkflowSteps).

Example

In the example below, the model Contact has one primitive properties (which would be rendered as a Field), another that is a nested Model, and one that is an array of string (which would be rendered as a List):

interface Contact {
  website: string; // <-- Field
  fullName: { // <-- Model
    first: string // <-- Field
    middle: string // <-- Field
    last: string // <-- Field
  };
  emailAddresses: string[]; // <-- List
}

Contributing

DO IT! 🚀

Start by looking for and/or opening issues for tracking. I don't have much for contribution guidelines right now, but please follow a few best practices:

  • TypeScript
    • Prefer interface over type aliases wherever possible. This is what allows extension of core types.
    • Prefer const over let, and don't use var in code. When compiling, var will be emitted to avoid TDZ management performance hit, but code should adhere to stricter variable declaration.
  • React
    • Function components with hooks only, please
    • Prefer a single, default export for components in a PascalCasedFile.tsx, named exports for everything else in a camelCasedFile.ts
    • Write stories and tests for what you build/fix/whatever