Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/dungntm58/swiftui-hooks-form

A SwiftUI implementation of React Hooks Form. A custom Hook inherits from React Hooks to handle input forms
https://github.com/dungntm58/swiftui-hooks-form

forms forms-builder hooks ios macos react react-hook-form swift swiftui tvos ux

Last synced: 10 days ago
JSON representation

A SwiftUI implementation of React Hooks Form. A custom Hook inherits from React Hooks to handle input forms

Awesome Lists containing this project

README

        

SwiftUI Hooks Form


A SwiftUI implementation of React Hooks Form.


Performant, flexible and extensible forms with easy-to-use validation.


📔 API Reference



test
release
Swift5
Platform
license

---

- [Introduction](#introduction)
- [Getting Started](#getting-started)
- [API](#hooks-api)
- [License](#license)

---

## Introduction

SwiftUI Hooks Form is a Swift implementation of React Hook Form

This library continues working from SwiftUI Hooks. Thank ra1028 for developing the library.

---

## Getting Started

### Requirements

| |Minimum Version|
|------:|--------------:|
|Swift |5.7 |
|Xcode |14.0 |
|iOS |13.0 |
|macOS |10.15 |
|tvOS |13.0 |

## Installation

The module name of the package is `FormHook`. Choose one of the instructions below to install and add the following import statement to your source code.

```swift
import FormHook
```

#### [Xcode Package Dependency](https://developer.apple.com/documentation/xcode/adding_package_dependencies_to_your_app)

From Xcode menu: `File` > `Swift Packages` > `Add Package Dependency`

```text
https://github.com/dungntm58/swiftui-hooks-form
```

#### [Swift Package Manager](https://www.swift.org/package-manager)

In your `Package.swift` file, first add the following to the package `dependencies`:

```swift
.package(url: "https://github.com/dungntm58/swiftui-hooks-form"),
```

And then, include "Hooks" as a dependency for your target:

```swift
.target(name: "", dependencies: [
.product(name: "FormHook", package: "swiftui-hooks-form"),
]),
```

### Documentation

- [API Reference](https://dungntm58.github.io/swiftui-hooks-form/documentation/hooks)
- [Example apps](Examples)

---

## Hooks API

👇 Click to open the description.

useForm

```swift
func useForm(
mode: Mode = .onSubmit,
reValidateMode: ReValidateMode = .onChange,
resolver: Resolver? = nil,
context: Any? = nil,
shouldUnregister: Bool = true,
criteriaMode: CriteriaMode = .all,
delayErrorInNanoseconds: UInt64 = 0
) -> FormControl where FieldName: Hashable
```

`useForm` is a custom hook for managing forms with ease. It returns a `FormControl` instance.

useController

```swift
func useController(
name: FieldName,
defaultValue: Value,
rules: any Validator,
shouldUnregister: Bool = false
) -> ControllerRenderOption where FieldName: Hashable
```

This custom hook powers `Controller`. Additionally, it shares the same props and methods as `Controller`. It's useful for creating reusable `Controlled` input.

`useController` must be called in a `Context` scope.

```swift
enum FieldName: Hashable {
case username
case password
}

@ViewBuilder
var hookBody: some View {
let form: FormControl = useForm()
Context.Provider(value: form) {
let (field, fieldState, formState) = useController(name: FieldName.username, defaultValue: "")
TextField("Username", text: field.value)
}
}

// this code achieves the same

@ViewBuilder
var body: some View {
ContextualForm(...) { form in
let (field, fieldState, formState) = useController(name: FieldName.username, defaultValue: "")
TextField("Username", text: field.value)
}
}
```

---

## SwiftUI Component
👇 Click to open the description.

ContextualForm

```swift
struct ContextualForm: View where Content: View, FieldName: Hashable {
init(mode: Mode = .onSubmit,
reValidateMode: ReValidateMode = .onChange,
resolver: Resolver? = nil,
context: Any? = nil,
shouldUnregister: Bool = true,
shouldFocusError: Bool = true,
delayErrorInNanoseconds: UInt64 = 0,
@_implicitSelfCapture onFocusField: @escaping (FieldName) -> Void,
@ViewBuilder content: @escaping (FormControl) -> Content
)

@available(macOS 12.0, iOS 15.0, tvOS 15.0, *)
init(mode: Mode = .onSubmit,
reValidateMode: ReValidateMode = .onChange,
resolver: Resolver? = nil,
context: Any? = nil,
shouldUnregister: Bool = true,
shouldFocusError: Bool = true,
delayErrorInNanoseconds: UInt64 = 0,
focusedFieldBinder: FocusState.Binding,
@ViewBuilder content: @escaping (FormControl) -> Content
)
```
It wraps a call of `useForm` inside the `hookBody` and passes the FormControl value to a `Context.Provider`

It is identical to

```swift
let form: FormControl = useForm(...)
Context.Provider(value: form) {
...
}
```

Controller

### Controller
```swift
import SwiftUI

struct Controller: View where Content: View, FieldName: Hashable {
init(
name: FieldName,
defaultValue: Value,
rules: any Validator = NoopValidator(),
@ViewBuilder render: @escaping (ControllerRenderOption) -> Content
)
}
```

### FieldOption

```swift
struct FieldOption {
let name: FieldName
let value: Binding
}
```

### ControllerRenderOption

```swift
typealias ControllerRenderOption = (field: FieldOption, fieldState: FieldState, formState: FormState) where FieldName: Hashable
```

It wraps a call of `useController` inside the `hookBody`. Like `useController`, you guarantee `Controller` must be used in a `Context` scope.

---

## Acknowledgements

- [React Hooks](https://reactjs.org/docs/hooks-intro.html)
- [React Hooks Form](https://react-hook-form.com)

---

## License

[MIT © Dung Nguyen](LICENSE)

---