{"id":18103594,"url":"https://github.com/fcanas/formulary","last_synced_at":"2025-04-13T19:26:06.406Z","repository":{"id":25929031,"uuid":"29370246","full_name":"fcanas/Formulary","owner":"fcanas","description":"Declarative iOS TableView Forms in Swift (pre-SwiftUI)","archived":false,"fork":false,"pushed_at":"2018-04-01T02:55:11.000Z","size":8817,"stargazers_count":82,"open_issues_count":9,"forks_count":10,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-06T17:12:50.538Z","etag":null,"topics":["declarative-ui","form-builder","form-validation","ios","swift"],"latest_commit_sha":null,"homepage":"https://fabiancanas.com/Formulary/","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/fcanas.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2015-01-16T22:14:22.000Z","updated_at":"2024-11-07T00:11:43.000Z","dependencies_parsed_at":"2022-08-28T08:51:48.375Z","dependency_job_id":null,"html_url":"https://github.com/fcanas/Formulary","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fcanas%2FFormulary","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fcanas%2FFormulary/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fcanas%2FFormulary/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fcanas%2FFormulary/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fcanas","download_url":"https://codeload.github.com/fcanas/Formulary/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248766899,"owners_count":21158346,"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":["declarative-ui","form-builder","form-validation","ios","swift"],"created_at":"2024-10-31T22:12:39.210Z","updated_at":"2025-04-13T19:26:06.381Z","avatar_url":"https://github.com/fcanas.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Formulary [![Build Status](https://travis-ci.org/fcanas/Formulary.svg?branch=master)](https://travis-ci.org/fcanas/Formulary)\n\nFormulary is a Swift library for creating dynamic, declarative, table view forms for iOS.\n\nFormulary is in early stages of design and development, so if you jump in now, you can have a big impact on its design, power, and utility.\n\nFormulary is inspired by XLForm, written in Swift, and designed for simplicity and development speed.\n\n## Basic Use\n\n### Text Entry\n\nA basic text entry form shows Formulary's simple declarative style. A row's name is shown as placeholder text and as a label for the row. A row may also specify the kind of text entry it expects, controlling the keyboard style.\n\n```swift\nlet form = Form(sections: [FormSection(rows: [TextEntryFormRow(name:\"Name\"),\n                                              TextEntryFormRow(name: \"Email\", textType: TextEntryType.Email),\n                                              TextEntryFormRow(name:\"Age\", textType: TextEntryType.Number)],\n                                       name:\"Profile\")])\nlet formViewController = FormViewController(form: form)\npresentViewController(formViewController, animated: true, completion: nil)\n```\n\n\u003cimg src=\"https://raw.github.com/fcanas/Formulary/master/Screenshots/formulary_basic.gif\" alt=\"Screen-Capture of Basic Example Form\" width=\"396\" /\u003e\n\u003c!--![](/Screenshots/formulary_basic.gif)--\u003e\n\n\n#### NSFormatters in Text Entry\n\n`NSFormatter`s can be injected to format text entry or enforce valid text. In this example the number formatter will prevent the user from entering more than two decimal places, more than one decimal point, or any non-numeric characters.\n\n```swift\nlet decimalFormatter = NSNumberFormatter()\ndecimalFormatter.maximumFractionDigits = 2\n\nTextEntryFormRow(name:\"Age\", textType: .Decimal, formatter: decimalFormatter)\n```\n\n#### Validations\n\nText entry rows can have validations. Validations are assertions about the value of a row.\nValidations show users error messages. Validation results for individual rows are aggregated to validate the overall Form.\nSome Validations are provided such as `MaximumNumber`, `MinimumNumber`, and `RequiredString`.\n\n```swift\nTextEntryFormRow(name:\"Name\", validation: RequiredString(\"Name\"))\nTextEntryFormRow(name:\"Age\", textType: TextEntryType.Number, validation:MinimumNumber(\"Age\", 13))\n```\n\nA Validation is any function that accepts a `String` and returns a tuple indicating the validity of the input and any reason for it.\n\n```swift\ntypealias Validation = (String?) -\u003e (valid: Bool, reason: String)\n```\n\nThis allows for powerful and flexible composition of Validations, which Formulary facilitates with logical operations on Validations.\n\n\u003cimg src=\"https://raw.github.com/fcanas/Formulary/master/Screenshots/formulary_validations.gif\" alt=\"Screen-Capture of a Form with Validations\" width=\"396\" /\u003e\n\u003c!--![](/Screenshots/formulary_validations.gif)--\u003e\n\n### Other Row Types\n\n#### Toggle Switch\n\n```swift\nFormRow(name:\"Do you like goats?\", type: .Switch)\n```\n\n#### Buttons\n\n```swift\nFormRow(name:\"Show an Alert\", type: .Button, action: { _ in\n    let alert = UIAlertController(title: \"Hi!\", message: \"Somebody pressed a button.\", preferredStyle: UIAlertControllerStyle.Alert)\n    alert.addAction(UIAlertAction(title: \"Ok\", style: UIAlertActionStyle.Default, handler: nil))\n    self.presentViewController(alert, animated: true, completion: nil)\n})\n```\n\n#### Options\n\n```swift\nOptionSection(rowValues:[\"Ice Cream\", \"Pizza\", \"Beer\"], name: \"Food\")\n```\n\n## Example\n\n\u003cimg src=\"https://raw.github.com/fcanas/Formulary/master/Screenshots/animated-capture.gif\" alt=\"Screen-Capture of Example Form\" width=\"396\" /\u003e\n\u003c!--![](/Screenshots/animated-capture.gif)--\u003e\n\n```swift\nlet decimalFormatter = NSNumberFormatter()\ndecimalFormatter.maximumFractionDigits = 5\n\nlet integerFormatter = NSNumberFormatter()\n\nself.form = Form(sections: [\n    FormSection(rows: [\n        TextEntryFormRow(name:\"Name\", tag: \"name\", validation: RequiredString(\"Name\")),\n        TextEntryFormRow(name: \"Email\", tag: \"email\", textType: TextEntryType.Email),\n        TextEntryFormRow(name:\"Age\", tag: \"age\", textType: TextEntryType.Number, validation: MinimumNumber(\"Age\", 13), formatter: integerFormatter)],\n        name:\"Profile\"),\n    FormSection(rows: [\n        TextEntryFormRow(name:\"Favorite Number\", tag: \"favoriteNumber\", value: nil, textType: .Decimal, validation: MinimumNumber(\"Your favorite number\", 47) \u0026\u0026 MaximumNumber(\"Your favorite number\", 47), formatter: decimalFormatter),\n        FormRow(name:\"Do you like goats?\", tag: \"likesGoats\", type: .Switch, value: false),\n        TextEntryFormRow(name:\"Other Thoughts?\", tag: \"thoughts\", textType: .Plain),],\n        name:\"Preferences\",\n        footerName: \"Fin\"),\n    OptionSection(rowValues:[\"Ice Cream\", \"Pizza\", \"Beer\"], name: \"Food\", value: [\"Pizza\", \"Ice Cream\"]),\n    FormSection(rows: [\n        FormRow(name:\"Show Values\", tag: \"show\", type: .Button, value: nil, action: { _ in\n\n            let data = NSJSONSerialization.dataWithJSONObject(values(self.form), options: nil, error: nil)!\n            let s = NSString(data: data, encoding: NSUTF8StringEncoding)\n\n            let alert = UIAlertController(title: \"Form Values\", message: s as? String, preferredStyle: UIAlertControllerStyle.Alert)\n            alert.addAction(UIAlertAction(title: \"Ok\", style: UIAlertActionStyle.Default, handler: nil))\n            self.presentViewController(alert, animated: true, completion: nil)\n        })\n    ])\n])\n```\n\n## Development Status\n\nI'm using this in production, and the way I'm using works fine. YMMV.\n\nBefore a 1.0.0 release, this project follows a modified [SemVer](http://semver.org/).\n\n\u003e Major version zero (0.y.z) is for initial development. Anything may change at any time. The public API should not be considered stable.\n\nReasonable effort is put forth to use Patch version Z (x.y.Z | x = 0) when new, backwards compatible functionality is introduced to the public API. And for Minor version Y (x.Y.z | x = 0) when any backwards incompatible changes are introduced to the public API.\n\nI intend to release a 1.0.0 early and have the major version number jump quickly rather than continuing with 0.y.z releases. Check Formulary's [pulse](https://github.com/fcanas/Formulary/pulse) if you're wondering about the health of the project.\n\n## Author\n\nFabian Canas ([@fcanas](http://twitter.com/fcanas))\n\n## License\n\nFormulary is available under the MIT license.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffcanas%2Fformulary","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffcanas%2Fformulary","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffcanas%2Fformulary/lists"}