{"id":19710559,"url":"https://github.com/rootstrap/rsformview","last_synced_at":"2026-02-22T10:43:25.889Z","repository":{"id":62452178,"uuid":"184611074","full_name":"rootstrap/RSFormView","owner":"rootstrap","description":"A Cocoapods library designed to easily create forms with multiple data entry fields ","archived":false,"fork":false,"pushed_at":"2020-04-28T15:50:42.000Z","size":2214,"stargazers_count":87,"open_issues_count":1,"forks_count":6,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-06-12T01:05:09.395Z","etag":null,"topics":["cocoapod","cocoapods","form-builder","form-validation","forms","pod","swift","ui-components"],"latest_commit_sha":null,"homepage":"https://rootstrap.com","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/rootstrap.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":"2019-05-02T16:02:15.000Z","updated_at":"2025-05-12T13:12:19.000Z","dependencies_parsed_at":"2022-11-01T23:45:37.925Z","dependency_job_id":null,"html_url":"https://github.com/rootstrap/RSFormView","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/rootstrap/RSFormView","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rootstrap%2FRSFormView","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rootstrap%2FRSFormView/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rootstrap%2FRSFormView/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rootstrap%2FRSFormView/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rootstrap","download_url":"https://codeload.github.com/rootstrap/RSFormView/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rootstrap%2FRSFormView/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263233296,"owners_count":23434833,"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":["cocoapod","cocoapods","form-builder","form-validation","forms","pod","swift","ui-components"],"created_at":"2024-11-11T22:07:43.197Z","updated_at":"2026-02-22T10:43:25.845Z","avatar_url":"https://github.com/rootstrap.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://img.shields.io/travis/rootstrap/RSFormView/master.svg)](https://travis-ci.org/rootstrap/RSFormView)\n[![Maintainability](https://api.codeclimate.com/v1/badges/7f79bedea0280ec94444/maintainability)](https://codeclimate.com/repos/5cd33d2d08760b668c0049c7/maintainability)\n[![Test Coverage](https://api.codeclimate.com/v1/badges/544a5a1b6aa75ad62eb6/test_coverage)](https://codeclimate.com/github/rootstrap/RSFormView/test_coverage)\n[![License](https://img.shields.io/github/license/rootstrap/RSFormView.svg)](https://github.com/rootstrap/RSFormView/blob/master/LICENSE)\n\n# RSFormView\n\n\n## What is it?\n\nRSFormView is a library that helps you build fully customizable forms for data entry in a few minutes.\n\n\u003cimg src=\"https://github.com/rootstrap/RSFormView/blob/master/formExample.gif\" height=\"440\"\u003e\n\n## Installation\n\nRSFormView is available through [CocoaPods](http://cocoapods.org). To install it, simply add the following line to your Podfile:\n\n```ruby\npod 'RSFormView', '~\u003e 2.1.1' \n```\n## Usage\n\n1. Add a FormView to your view controller, you can do this either programatically or via Storyboards.\n\n\nProgramatically:\n```swift\nlet formView = FormView(frame: frame)\nview.addSubview(formView)\n```\nStoryboards:\nAdd a `UIView` to your view controller and change the class name to `FormView` and the module to `RSFormView`.\n\n\n2. Set your view controller as FormViewDelegate:\n```swift\nimport RSFormView\n\nclass YourViewController: UIViewController, FormViewDelegate { ... }\n```\nand implement\n```swift\nfunc didUpdateFields(in formView: FormView, allFieldsValid: Bool)\n```\nThis function will be called any time a user enters any data in the form, so it's a great place to update other views dependent on the entered data.\n\n3. Set your view controller as the FormView delegate\n```swift\nformView.delegate = self\n```\n\n4. Set a FormViewModel to your formView\n\n\nA `FormViewModel` can be any class that implements the `FormViewModel` delegate.\nFor a class to implement `FormViewModel` delegate  you only need to define an array of `FormItem`.\nEach `FormItem` will determine the behavior and validation of each text field in your form.\nOut of the box, RSFormView provides the following subclasses of `FormItem`:\n- `TextCellItem`: A single label, or a \"section header\"\n- `TextFieldCellItem`: A single text field.\n- `TwoTextFieldCellItem`: Two text fields.\n\nYou can add your own custom `FormItem`s, check the `Custom Items` section for more information.\n\n## FieldType\n\n`fieldType` is a FormField property that determines the behaviour of the represented TextField.\n\nCases:\n - email: Will present the email keyboard when the field is selected and validate that the text entry is in an email format\n - date: Will present a native date picker when the field is selected and validate that the entry is not empty\n - integer: Will present the numeric keyboard when the field is selected and validate that the text entry can be casted to Int\n - double: Will present the decimal keyboard when the field is selected and validate that the text entry can be casted to Double, pass the max decimal places as a parameter of this enum case\n - password: Will mask the text entry in UI and validate that the text entry is not empty\n - usPhone: Will decorate the text entry with slashes (111-111-1111) and validate that the text entry is in a valid US phone number format\n\n Check `FieldType` definition for more supported cases.\n\n ## ValidationType\n\n `validationType` is a `FormField` property that determines the validation behaviour of the represented TextField.\n Different `FieldType`s provide different default validations but the validation can be overriden by setting a `ValidationType` to the `FormField`.\n\n Cases:\n - nonEmpty: Will mark the field invalid if the text entry is empty\n - none: No validation will be made, the field will never be marked invalid unless manually made so\n - integer: Will mark the field invalid if the text entry is not an integer\n - double: Will mark the field invalid if the text entry is not a double, max 2 decimal places\n - usState: Will validate that the text entry matches the name or abbreviation of any of the US states\n - custom: Pass this case a block with your custom validation.\n\nCustom example:\n```swift\nyourFormField.validationType = .custom(evaluator: { [weak self] updatedValue in\n  let otherFormField = self?.fields().first { $0.name == \"OtherFormFieldName\" }\n  let otherFormFieldValue = otherFormField?.value ?? \"\"\n  return updatedValue.count \u003e 5 \u0026\u0026 updatedValue == otherFormFieldValue\n})\n//In this example the field will be marked valid if the text entry has mora characters than 5 and its text entry is the same as the field with identifier \"OtherTextFieldName\"\n```\n\n## FormItem\n\nA `FormItem` defines the basic behaviour of a row which is then specialized by subclassing it. You should never use instances of FormItem directly, RSFormView provides the following subclasses of FormItem out of the box:\n\nTextCellItem: A single label, or a \"section header\"\nTextFieldCellItem: A single text field.\nTwoTextFieldCellItem: Two text fields.\n\n1. One Text Field item:\n\n```swift\nlet birthdateField = FormField(name: \"Birthdate field\", // the identifier of the field, use this to collect the data later\n                               initialValue: \"\", // the inital value of the field, if its in a date formate it will auto select that date in the picker\n                               placeholder: FieldName.birthdate.rawValue, // The placeholder when there's no value and text field title when there is\n                               fieldType: .date, //The Type of the field, .date will present a native picker view when tapping on the text field\n                               isValid: false, //The initial validation state. The field won't be marked invalid until data is entered or removed\n                               errorMessage: \"Please enter a birthdate\") //The error message to be displayed when the entry is invalid or empty\n\nlet formItem = TextFieldCellItem(with: birthdateField)\n```\n\n2. Two Text Field item:\n\n```swift\nlet firstFormField = FormField(...)\nlet secondFormField = FormField(...)\n\nlet formItem = TwoTextFieldCellItem(firstField: firstFormField, secondField: secondFormField)\n```\n\n3. Text Cell Item (may be used as a section header or text hint):\n```swift\nlet attributedString = NSAttributedString(...)\nlet formItem = TextCellItem()\nformItem.attributedString = attributedString\n```\n\nAs an easy way to test the pod, we provide a the class BasaicFormViewModel. It receives a list of items and will show the form without additional customization. \n\n```swift\n//  birthdateField defined above\n        \nformView.viewModel = BasicFormViewModel(items: [TextFieldCellItem(with: birthdateField)])\n```\n\nYou can see this approach in the VanillaExample folder on this repository. \n\n1. Configure your form looks\n\nCreate a `FormConfigurator` change any colors or fonts you need and set it to your form view.\n```swift\nlet configurator = FormConfigurator()\nconfigurator.textColor = UIColor.lightGray\nconfigurator.validTitleColor = UIColor.blue\nconfigurator.titleFont = UIFont.systemFont(withSize: 13)\n...\nformView.formConfigurator = configurator\n```\n\nUse the UIColor extension `formColor(red: Int, green: Int, blue: Int)`  to create new UIColors.\n```swift\nlet configurator = FormConfigurator()\n...\nlet darkPurple = UIColor.formColor(red: 140, green: 20, blue: 252)\nconfigurator.editingTitleColor = darkPurple\n...\nformView.formConfigurator = configurator\n```\n\nChoose whether to hide the bottom line by setting the bottom line colors to clear (they are set colored by default)\n```swift\nlet configurator = FormConfigurator()\n...\nconfigurator.validLineColor = UIColor.clear\nconfigurator.invalidLineColor = UIColor.clear\nconfigurator.editingLineColor = UIColor.clear\n...\nformView.formConfigurator = configurator\n```\n\nChoose whether to show borders by setting the border colors to the value desired (they are set clear by default).\nAlso set the border width and corner radius as desired.\n```swift\nlet configurator = FormConfigurator()\n...\nconfigurator.validBorderColor = UIColor.gray\nconfigurator.invalidBorderColor = UIColor.orange\nconfigurator.editingBorderColor = UIColor.darkPurple\nconfigurator.borderCornerRadius = 20\nconfigurator.borderWidth = 2\n...\nformView.formConfigurator = configurator\n```\n\n\u003cimg src=\"https://github.com/rootstrap/RSFormView/blob/master/editBorders.gif\" height=\"440\"\u003e\n\nDisable tableView scrolling, which is enabled by default.\n```swift\nlet configurator = FormConfigurator()\n...\nconfigurator.isScrollEnabled = false\n...\nformView.formConfigurator = configurator\n```\n\n6. Collect data\n\n\nAny text entry made in your form will be collected in your `FormViewModel`  `items`.\nSince you may have more than one text field per item a better way for collecting your data is making use of the `fields()` function of the `FormViewModel`, like this:\n```swift\nvar user = User()\nformViewModel.fields().forEach {\n  switch $0.name {\n  case \"First Name\":\n    user.firstName = $0.value\n  case \"Birthdate\":\n    user.birthdate = $0.value\n  default:\n    print(\"\\($0.name): \\($0.value)\")\n  }\n}\n```\n\n\n## Custom Form Items\nIf you need custom fields and the customization possibilities of the `FormConfigurator` are not enough, you can implement your own Fields.\nTo do so, follow these steps:\n1- Create your custom `UITableViewCell` as you would normally do for any tableView.\n2- Instead of subclassing from `UITableViewCell`, use `FormTableViewCell` as a base class.\n3- Override `update` and `updateErrorState` to implement your own UI updates for the field.\n4- Create a subclass of `FormItem` that overrides `cellIdentifier` and returns a valid reuseID.\n5- In your formViewModel implementation, override the `customCellSetup` callback and register your new cell on the tableView.\n\nIf you need an example, you can check the `StepperCell` and `StepperCellItem` classes on the Example project.\n\n## Server Side Validation\n\nTo manually mark fields invalid (for example after a server side validation) you can simply do:\n\n``` swift\nyourFormView.markItemInvalid(fieldName: \"EmailFieldName\", errorMessage: \"Oops, This email is already taken\")\n```\n\nAfter the user makes any edit in the invalid field it will no longer be marked invalid unless the real time validation doesn't pass.\n\n## Example App\n\nClone this repo and run the example app to take a look at some of the RSFormView functionalities\n\n## Contribute\n\nTo contribute to this library: fork this repository and create a Pull Request from your fork, detailing what are you improving/extending, the approach taken and screenshots to proof functionality added.\n\nYou can also open issues in this repository and our team will tackle them as soon as possible.\n\n## License\n\nRSFormView is available under the MIT license. See the LICENSE file for more info.\n\n## Credits\n\n**RSFormView** is authored and mantained by [Rootstrap](http://www.rootstrap.com) and [German Stabile](https://github.com/germanStabile) with the help of our [contributors](https://github.com/rootstrap/RSFormView/contributors).\n\n[\u003cimg src=\"https://s3-us-west-1.amazonaws.com/rootstrap.com/img/rs.png\" width=\"100\"/\u003e](http://www.rootstrap.com)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frootstrap%2Frsformview","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frootstrap%2Frsformview","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frootstrap%2Frsformview/lists"}