{"id":22903134,"url":"https://github.com/dungntm58/swiftui-hooks-form","last_synced_at":"2025-05-08T16:55:19.110Z","repository":{"id":63834642,"uuid":"562369300","full_name":"dungntm58/swiftui-hooks-form","owner":"dungntm58","description":"A SwiftUI implementation of React Hooks Form. A custom Hook inherits from React Hooks to handle input forms","archived":false,"fork":false,"pushed_at":"2024-01-06T14:48:48.000Z","size":853,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-31T17:44:25.431Z","etag":null,"topics":["forms","forms-builder","hooks","ios","macos","react","react-hook-form","swift","swiftui","tvos","ux"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dungntm58.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-11-06T05:52:11.000Z","updated_at":"2025-03-18T16:45:51.000Z","dependencies_parsed_at":"2023-02-15T12:16:23.443Z","dependency_job_id":null,"html_url":"https://github.com/dungntm58/swiftui-hooks-form","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dungntm58%2Fswiftui-hooks-form","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dungntm58%2Fswiftui-hooks-form/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dungntm58%2Fswiftui-hooks-form/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dungntm58%2Fswiftui-hooks-form/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dungntm58","download_url":"https://codeload.github.com/dungntm58/swiftui-hooks-form/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253112078,"owners_count":21856070,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["forms","forms-builder","hooks","ios","macos","react","react-hook-form","swift","swiftui","tvos","ux"],"created_at":"2024-12-14T02:34:07.380Z","updated_at":"2025-05-08T16:55:19.068Z","avatar_url":"https://github.com/dungntm58.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003eSwiftUI Hooks Form\u003c/h1\u003e\n\u003cp align=\"center\"\u003eA SwiftUI implementation of \u003ca href=\"https://react-hook-form.com/get-started\"\u003eReact Hooks Form\u003c/a\u003e.\u003c/p\u003e\n\u003cp align=\"center\"\u003ePerformant, flexible and extensible forms with easy-to-use validation.\u003c/p\u003e\n\u003cp align=\"center\"\u003e\u003ca href=\"https://dungntm58.github.io/swiftui-hooks-form/documentation/formhook\"\u003e📔 API Reference\u003c/a\u003e\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/dungntm58/swiftui-hooks-form/actions\"\u003e\u003cimg alt=\"test\" src=\"https://github.com/dungntm58/swiftui-hooks-form/workflows/test/badge.svg\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/dungntm58/swiftui-hooks-form/releases/latest\"\u003e\u003cimg alt=\"release\" src=\"https://img.shields.io/github/v/release/dungntm58/swiftui-hooks-form.svg\"/\u003e\u003c/a\u003e\n  \u003ca href=\"https://developer.apple.com/swift\"\u003e\u003cimg alt=\"Swift5\" src=\"https://img.shields.io/badge/language-Swift5-orange.svg\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://developer.apple.com\"\u003e\u003cimg alt=\"Platform\" src=\"https://img.shields.io/badge/platform-iOS%20%7C%20macOS%20%7C%20tvOS-green.svg\"\u003e\u003c/a\u003e\n  \u003ca href=\"LICENSE\"\u003e\u003cimg alt=\"license\" src=\"https://img.shields.io/badge/license-MIT-black.svg\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n- [Introduction](#introduction)\n- [Getting Started](#getting-started)\n- [API](#hooks-api)\n- [License](#license)\n\n---\n\n## Introduction\n\nSwiftUI Hooks Form is a Swift implementation of React Hook Form\n\nThis library continues working from \u003ca href=\"https://github.com/ra1028/swiftui-hooks\"\u003eSwiftUI Hooks\u003c/a\u003e. Thank ra1028 for developing the library.\n\n---\n\n## Getting Started\n\n### Requirements\n\n|       |Minimum Version|\n|------:|--------------:|\n|Swift  |5.7            |\n|Xcode  |14.0           |\n|iOS    |13.0           |\n|macOS  |10.15          |\n|tvOS   |13.0           |\n\n## Installation\n\nThe 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.\n\n```swift\nimport FormHook\n```\n\n#### [Xcode Package Dependency](https://developer.apple.com/documentation/xcode/adding_package_dependencies_to_your_app)\n\nFrom Xcode menu: `File` \u003e `Swift Packages` \u003e `Add Package Dependency`\n\n```text\nhttps://github.com/dungntm58/swiftui-hooks-form\n```\n\n#### [Swift Package Manager](https://www.swift.org/package-manager)\n\nIn your `Package.swift` file, first add the following to the package `dependencies`:\n\n```swift\n.package(url: \"https://github.com/dungntm58/swiftui-hooks-form\"),\n```\n\nAnd then, include \"Hooks\" as a dependency for your target:\n\n```swift\n.target(name: \"\u003ctarget\u003e\", dependencies: [\n    .product(name: \"FormHook\", package: \"swiftui-hooks-form\"),\n]),\n```\n\n### Documentation\n\n- [API Reference](https://dungntm58.github.io/swiftui-hooks-form/documentation/hooks)\n- [Example apps](Examples)\n\n---\n\n## Hooks API\n\n👇 Click to open the description.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cCODE\u003euseForm\u003c/CODE\u003e\u003c/summary\u003e\n\n```swift\nfunc useForm\u003cFieldName\u003e(\n    mode: Mode = .onSubmit,\n    reValidateMode: ReValidateMode = .onChange,\n    resolver: Resolver\u003cFieldName\u003e? = nil,\n    context: Any? = nil,\n    shouldUnregister: Bool = true,\n    criteriaMode: CriteriaMode = .all,\n    delayErrorInNanoseconds: UInt64 = 0\n) -\u003e FormControl\u003cFieldName\u003e where FieldName: Hashable\n```\n\n`useForm` is a custom hook for managing forms with ease. It returns a `FormControl` instance.\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cCODE\u003euseController\u003c/CODE\u003e\u003c/summary\u003e\n\n```swift\nfunc useController\u003cFieldName, Value\u003e(\n    name: FieldName,\n    defaultValue: Value,\n    rules: any Validator\u003cValue\u003e,\n    shouldUnregister: Bool = false\n) -\u003e ControllerRenderOption\u003cFieldName, Value\u003e where FieldName: Hashable\n```\n\nThis custom hook powers `Controller`. Additionally, it shares the same props and methods as `Controller`. It's useful for creating reusable `Controlled` input.\n\n`useController` must be called in a `Context` scope.\n\n```swift\nenum FieldName: Hashable {\n    case username\n    case password\n}\n\n@ViewBuilder\nvar hookBody: some View {\n    let form: FormControl\u003cFieldName\u003e = useForm()\n    Context.Provider(value: form) {\n        let (field, fieldState, formState) = useController(name: FieldName.username, defaultValue: \"\")\n        TextField(\"Username\", text: field.value)\n    }\n}\n\n// this code achieves the same\n\n@ViewBuilder\nvar body: some View {\n    ContextualForm(...) { form in\n        let (field, fieldState, formState) = useController(name: FieldName.username, defaultValue: \"\")\n        TextField(\"Username\", text: field.value)\n    }\n}\n```\n\n\u003c/details\u003e\n\n---\n\n## SwiftUI Component\n👇 Click to open the description.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cCODE\u003eContextualForm\u003c/CODE\u003e\u003c/summary\u003e\n\n```swift\nstruct ContextualForm\u003cContent, FieldName\u003e: View where Content: View, FieldName: Hashable {\n    init(mode: Mode = .onSubmit,\n        reValidateMode: ReValidateMode = .onChange,\n        resolver: Resolver\u003cFieldName\u003e? = nil,\n        context: Any? = nil,\n        shouldUnregister: Bool = true,\n        shouldFocusError: Bool = true,\n        delayErrorInNanoseconds: UInt64 = 0,\n        @_implicitSelfCapture onFocusField: @escaping (FieldName) -\u003e Void,\n        @ViewBuilder content: @escaping (FormControl\u003cFieldName\u003e) -\u003e Content\n    )\n\n    @available(macOS 12.0, iOS 15.0, tvOS 15.0, *)\n    init(mode: Mode = .onSubmit,\n        reValidateMode: ReValidateMode = .onChange,\n        resolver: Resolver\u003cFieldName\u003e? = nil,\n        context: Any? = nil,\n        shouldUnregister: Bool = true,\n        shouldFocusError: Bool = true,\n        delayErrorInNanoseconds: UInt64 = 0,\n        focusedFieldBinder: FocusState\u003cFieldName?\u003e.Binding,\n        @ViewBuilder content: @escaping (FormControl\u003cFieldName\u003e) -\u003e Content\n    )\n```\nIt wraps a call of `useForm` inside the `hookBody` and passes the FormControl value to a `Context.Provider\u003cForm\u003e`\n\nIt is identical to\n\n```swift\nlet form: FormControl\u003cFieldName\u003e = useForm(...)\nContext.Provider(value: form) {\n    ...\n}\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cCODE\u003eController\u003c/CODE\u003e\u003c/summary\u003e\n\n### Controller\n```swift\nimport SwiftUI\n\nstruct Controller\u003cContent, FieldName, Value\u003e: View where Content: View, FieldName: Hashable {\n    init(\n        name: FieldName,\n        defaultValue: Value,\n        rules: any Validator\u003cValue\u003e = NoopValidator(),\n        @ViewBuilder render: @escaping (ControllerRenderOption\u003cFieldName, Value\u003e) -\u003e Content\n    )\n}\n```\n\n### FieldOption\n\n```swift\nstruct FieldOption\u003cFieldName, Value\u003e {\n    let name: FieldName\n    let value: Binding\u003cValue\u003e\n}\n```\n\n### ControllerRenderOption\n\n```swift\ntypealias ControllerRenderOption\u003cFieldName, Value\u003e = (field: FieldOption\u003cFieldName, Value\u003e, fieldState: FieldState, formState: FormState\u003cFieldName\u003e) where FieldName: Hashable\n```\n\nIt wraps a call of `useController` inside the `hookBody`. Like `useController`, you guarantee `Controller` must be used in a `Context` scope.\n\n\u003c/details\u003e\n\n---\n\n## Acknowledgements\n\n- [React Hooks](https://reactjs.org/docs/hooks-intro.html)\n- [React Hooks Form](https://react-hook-form.com)\n\n---\n\n## License\n\n[MIT © Dung Nguyen](LICENSE)\n\n---\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdungntm58%2Fswiftui-hooks-form","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdungntm58%2Fswiftui-hooks-form","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdungntm58%2Fswiftui-hooks-form/lists"}