Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

armstrong-react

Package Overview
Dependencies
Maintainers
7
Versions
339
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

armstrong-react

Rocketmakers Armstrong library of React components

  • 4.0.0-pre34
  • latest
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
345
increased by6800%
Maintainers
7
Weekly downloads
 
Created
Source

Form Component

An extended HTML form React component to enable binding data objects to html forms.

Form Context

Form components are nestable - only the root Form will render as an html form, child Form components will be rendered as an html div. This function is provided by putting a form (IFormContext) property onto the React components context. This Form Context contains the current IDataBinder and the parent Form Context (if one exists).

Getting Started

You construct the Form in the same way you would a standard HTML form, the main differences are the additional data binding attributes required on both the Form and the bound Form Element's (that are described below the example)

Example

import * as React from "react";
import {Form,TextInput, SelectInput, Button} from "armstrong-react";
import {IDataBinder} from "armstrong-react/dist/components/form/formCore";

export interface IPerson{
  id: string
  name: string
  reputation?: number
  divisionId?: number
}

export interface IPersonForm{
  person: IPerson
}

export class PersonForm extends React.Component<IPersonForm,{binder: IDataBinder<IPerson>}>{
  constructor(props: IPersonForm){
    super(props)
    this.state = {binder: Form.jsonDataBinder(props.person)}
  }
  componentWillReceiveProps(nextProps: IPersonForm){
    if (nextProps.person !== this.props.person) {
      this.setState({binder: Form.jsonDataBinder(nextProps.person)})
    }
  }
  render(){
    return (
      <Form dataBinder={this.state.binder} onDataBinderChange={binder => this.setState({binder})}>
        <div>
          <TextInput {...Form.Bind.text("id")} />
        </div>
        <div>
          <TextInput {...Form.Bind.textNumeric("reputation")} />
          <TextInput {...Form.Bind.text("name")} />
          <SelectInput {...Form.Bind.select("divisionId")} options={[{id:1, name:"D1"},{id:2, name:"D2"},{id:3, name:"D3"}]} />
        </div>
        <Button onClick={e => alert(JSON.stringify(this.state.binder.toJson()))}>Save</Button>
      </Form>
    )
  }
}

Data Binding

IDataBinder

A data binder (IDataBinder) provides a formal read/write data model.

By default the Form provides a function to create a simple JSON dataBinder instance. This dataBinder provides a dot notation convention to access properties of the JSON object.

e.g.

// Create a Data Binder
const binder = Form.jsonDataBinder(dataObject)

// Sample dot notation
const name = binder.getValue("name") // name
const title = binder.getValue("addresses.0.title") // First address title
const mobile = binder.getValue("contact.mobile") // Mobile contact number

Form

The Form is a stateless component

attributes

(required) dataBinder: a data binder that contains the data you want to bind to the Form

(optional) onDataBinderChange(dataBinder: IDataBinder) => void: Notification with dataBinder, Called when bound Form data changes: NOTE, this is called on every key stroke/interaction on any of the bound fields

(optional) onDataChanged(data: any) => void: Notification with changed JSON data, Called when bound Form data changes: NOTE, this is called on every key stroke/interaction on any of the bound fields

<Form dataBinder={Form.jsonDataBinder(this.props.jsonObject)}>
</Form>

As Form is stateless, you should handle either onDataBinderChange or onDataChanged to trigger a refresh of your component. If your keypresses and interactions are not reflected in the UI (feels like a locked or frozen form), its likely because you are not handling these events correctly.

It is recommended that you put your dataBinder in component state, and use onDataBinderChange to setState(...)

Form Elements

A Form generally contains input html elements to handle user interaction. The Form provides a binding framework to allow simple assignment of core html element values to data (and vice versa).

The Form also permits custom (3rd party) input elements to be bound (you need to author simple custom binders to permit this - see custom binder below)

These Form Elements need a Binding Injector to participate within the Form lifecycle

IFormBinderInjector

To bind data to a Form Element you just spread a binding object (IFormBinderInjector) onto the element, you should supply the dot notation data path of the property you want to bind to.

<input {...Form.Bind.text("name")} />
<input {...Form.Bind.text("contact.mobile")} />
<input {...Form.Bind.checkbox("accept")} />

The Form comes with a default set of Form Binder Injectors catering for input and select elements (accessed via Form.Bind.*)

These Injectors effectively add a data-form-binder property onto the Form Element with the value being a IFormBinder instance.

IFormBinder

At runtime, the Form component processes all its contained Form Element - effectively inspecting each child until it finds a data-form-binder property.

The Form then uses the contained IFormBinder to bind the Form Element to the data property specified (typically using value and onChange), along with any other attributes and event handlers that are needed

Form Binders

Hidden

Bind a string property name to a hidden TextInput (or html input)

hidden(dataPath: string)
<TextInput {...Form.Bind.hidden("name")} />
<input {...Form.Bind.hidden("name")} />

Text

Bind a string property name to a TextInput (or html input)

text(dataPath: string)
<TextInput {...Form.Bind.text("name")} />
<input {...Form.Bind.text("name")} />

Password

Bind a 'secure' string property password to a TextInput (or html input)

password(dataPath: string)
<TextInput {...Form.Bind.password("password")} />
<input {...Form.Bind.password("password")} />

Number

Bind a number property reputation to a TextInput (or html input)

textNumeric(dataPath: string)
<TextInput {...Form.Bind.textNumeric("reputation")} />
<input {...Form.Bind.textNumeric("reputation")} />

Checkbox

Bind a boolean property accepts to a CheckboxInput (or html input)

checkbox(dataPath: string)
<CheckboxInput labelContent="accepts" {...Form.Bind.checkbox("accepts")} />
<input {...Form.Bind.checkbox("accepts")} />

Radio

Bind a string property userType to a RadioInput (or html input)

radio(dataPath: string, radioValue: string)
<RadioInput labelContent="One" radioGroup="main" {...Form.Bind.radio("userType", "1")}/>
<RadioInput labelContent="Two" radioGroup="main" {...Form.Bind.radio("userType", "2")}/>
<RadioInput labelContent="Three" radioGroup="main" {...Form.Bind.radio("userType", "3")}/>

<input radioGroup="main" {...Form.Bind.radio("userType", "1")}/>
<input radioGroup="main" {...Form.Bind.radio("userType", "2")}/>
<input radioGroup="main" {...Form.Bind.radio("userType", "3")}/>

Bind a number property userTypeNumeric to a RadioInput (or html input)

radioNumeric(dataPath: string, radioValue: number)
<RadioInput labelContent="One" radioGroup="main" {...Form.Bind.radioNumeric("userTypeNumeric", 1)}/>
<RadioInput labelContent="Two" radioGroup="main" {...Form.Bind.radioNumeric("userTypeNumeric", 2)}/>
<RadioInput labelContent="Three" radioGroup="main" {...Form.Bind.radioNumeric("userTypeNumeric", 3)}/>

<input radioGroup="main" {...Form.Bind.radioNumeric("userTypeNumeric", 1)}/>
<input radioGroup="main" {...Form.Bind.radioNumeric("userTypeNumeric", 2)}/>
<input radioGroup="main" {...Form.Bind.radioNumeric("userTypeNumeric", 3)}/>

Custom

You can author simple Form Binders to allow 3rd party controls to be directly bound within your application

custom(formBinder: IFormBinder)
class SelectInputFormBinder implements IFormBinder<ISelectInputProps, any> {
  constructor(private dataPath: string){}
  // set the value property of the `SelectInput`
  setElementProperty(props: ISelectInputProps, dataBinder: IDataBinder<any>): void{
    props.value = dataBinder.getValue(this.dataPath)
  }
  // handle the change property of the `SelectInput` - setting the dataBinder value and notifying on change
  handleValueChanged(props: ISelectInputProps, dataBinder: IDataBinder<any>, notifyChanged: () => void): void{
    props.change = c => {
      dataBinder.setValue(this.dataPath, c.id)
      notifyChanged()
    }
  }
}

And apply them via the custom method

<SelectInput {...Form.Bind.custom(new SelectInputFormBinder("divisionId"))} options={[{id:1, name:"D1"},{id:2, name:"D2"},{id:3, name:"D3"}]} />

Keywords

FAQs

Package last updated on 01 Oct 2019

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc