formk

A powerful form library for ReactJs/ReactNative

Usage no npm install needed!

<script type="module">
  import formk from 'https://cdn.skypack.dev/formk';
</script>

README

formk

A flexible React form library

Installation

    npm i formk --save

or yarn

    yarn add formk

Basic Usages

Creating simple form

import formk from "formk";
import { useState } from "react";

const { Form, Field } = formk();

const LoginForm = () => {
  const [formValue, setFormValue] = useState({
    username: "admin",
    password: "admin",
  });

  return (
    <Form value={formValue} onChange={setFormValue}>
      <Field name="username" />
      <Field name="password" />
      <button type="submit">Submit</button>
    </Form>
  );
};

Adding validations

const LoginForm = () => {
  return (
    <Form value={formValue} onChange={handleChange}>
      <Field
        name="username"
        rules={{
          // indicate that username field is required
          required: true,
          // use custom error message
          message: "Username required",
        }}
      />
      <Field
        name="password"
        rules={{
          // no error message specified
          // default error message will be used
          required: true,
        }}
      />
      <button type="submit">Submit</button>
    </Form>
  );
};

Advanced Usages

Using formk with React Native

import React, { useState } from "react";
import { Text, View, StyleSheet, Button, TextInput } from "react-native";
import formk from "formk";

const { Form, Field } = formk({
  noExtraAttrs: true,
});

const initialValue = {
  username: "admin",
  password: "123456",
};

export default function App() {
  const [currentData, setCurrentData] = useState(initialValue);
  const [submittedData, setSubmittedData] = useState(initialValue);

  return (
    <View style={styles.container}>
      <View>
        <Form
          value={currentData}
          initialValue={initialValue}
          onChange={setCurrentData}
          onSuccess={setSubmittedData}
        >
          {({ handleSubmit }) => (
            <>
              <Field name="username" rules={{ required: true }}>
                {({ $props, val }) => (
                  <View>
                    <TextInput
                      {...$props("value", "onChangeText")}
                      style={styles.input}
                      placeholder="Username"
                    />
                    {val.error && (
                      <Text style={styles.error}>{val.error.message}</Text>
                    )}
                  </View>
                )}
              </Field>
              <Field
                name="password"
                label="Custom Field Name"
                rules={{ required: true }}
              >
                {({ $props, val }) => (
                  <View>
                    <TextInput
                      {...$props("value", "onChangeText")}
                      style={styles.input}
                      placeholder="Password"
                    />
                    {val.error && (
                      <Text style={styles.error}>{val.error.message}</Text>
                    )}
                  </View>
                )}
              </Field>
              <Button title="Submit" onPress={handleSubmit} />
            </>
          )}
        </Form>
      </View>
      <View>
        <Text>
          Current Data:{"\n"}
          {JSON.stringify(currentData, null, 2)}
          {"\n"}
          Submitted Data:{"\n"}
          {JSON.stringify(submittedData, null, 2)}
          {"\n"}
        </Text>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: 50,
    backgroundColor: "#ecf0f1",
    padding: 8,
  },
  input: {
    borderColor: "silver",
    borderWidth: 1,
    marginBottom: 5,
    padding: 5,
    borderRadius: 3,
  },
  error: {
    color: "red",
    marginBottom: 5,
  },
});

Nested form validation

import formk from "formk";
import faker from "faker";
import { useState } from "react";

const { Form, Field } = formk();

const initialValue = {
  loginInfo: {
    username: faker.internet.userName(),
    password: faker.internet.password(),
  },
  personalInfo: {
    email: faker.internet.email(),
    address: {
      zipCode: parseInt(faker.address.zipCode(), 10),
      city: faker.address.city(),
      street: faker.address.streetAddress(),
      country: faker.address.country(),
    },
  },
};

const LoginInfo = () => (
  <>
    <Field name="username" label="Username" rules={{ required: true }} />
    <Field
      name="password"
      label="Password"
      rules={{ required: true, min: 6 }}
    />
  </>
);

const AddressInfo = () => (
  <>
    <Field name="zipCode" label="ZipCode" rules={{ pattern: /^\d+$/ }} />
    <Field name="city" label="City" />
    <Field name="street" label="Street" />
    <Field name="country" label="Country" />
  </>
);

const PersonalInfo = () => (
  <>
    <Field
      name="email"
      label="Email"
      rules={{ type: "email", required: true }}
    />
    <Form name="address">
      <AddressInfo />
    </Form>
  </>
);

export default function App() {
  const [value, setValue] = useState(initialValue);
  const [submittedValue, setSubmittedValue] = useState(initialValue);

  return (
    <div className="App">
      <Form
        value={value}
        initialValue={initialValue}
        onChange={setValue}
        onSuccess={setSubmittedValue}
      >
        <Form name="loginInfo">
          <LoginInfo />
        </Form>
        <Form name="personalInfo">
          <PersonalInfo />
        </Form>
        <button>Save</button>
      </Form>
      <h2>Editing value</h2>
      <xmp>{JSON.stringify(value, null, 2)}</xmp>
      <h2>Submitted value</h2>
      <xmp>{JSON.stringify(submittedValue, null, 2)}</xmp>
    </div>
  );
}

API References