# Eureka **Repository Path**: gitmaster/Eureka ## Basic Information - **Project Name**: Eureka - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 0 - **Created**: 2017-04-16 - **Last Updated**: 2020-12-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README 
Made with ❤️ by [XMARTLABS](http://xmartlabs.com). This is the re-creation of [XLForm] in Swift. ## Overview
|
|
|
|---|
|
|
|---|
#### Callbacks list
* **onChange()**
Called when the value of a row changes. You might be interested in adjusting some parameters here or even make some other rows appear or disappear.
* **onCellSelection()**
Called each time the user taps on the row and it gets selected.
* **cellSetup()**
Called only once when the cell is first configured. Set permanent settings here.
* **cellUpdate()**
Called each time the cell appears on screen. You can change the appearance here using variables that may not be present on cellSetup().
* **onCellHighlightChanged()**
Called whenever the cell or any subview become or resign the first responder.
* **onRowValidationChanged()**
Called whenever the the validation errors associated with a row changes.
* **onExpandInlineRow()**
Called before expanding the inline row. Applies to rows conforming `InlineRowType` protocol.
* **onCollapseInlineRow()**
Called before collapsing the inline row. Applies to rows conforming `InlineRowType` protocol.
* **onPresent()**
Called by a row just before presenting another view controller. Applies to rows conforming `PresenterRowType` protocol. Use it to set up the presented controller.
### Section Header and Footer
You can set a title `String` or a custom `View` as the header or footer of a `Section`.
#### String title
```swift
Section("Title")
Section(header: "Title", footer: "Footer Title")
Section(footer: "Footer Title")
```
#### Custom view
You can use a Custom View from a `.xib` file:
```swift
Section() { section in
var header = HeaderFooterView
In this case we are hiding and showing whole sections.
To accomplish this each row has an `hidden` variable of optional type `Condition` which can be set using a function or `NSPredicate`.
#### Hiding using a function condition
Using the `function` case of `Condition`:
```swift
Condition.function([String], (Form)->Bool)
```
The array of `String` to pass should contain the tags of the rows this row depends on. Each time the value of any of those rows changes the function is reevaluated.
The function then takes the `Form` and returns a `Bool` indicating whether the row should be hidden or not. This the most powerful way of setting up the `hidden` property as it has no explicit limitations of what can be done.
```swift
form +++ Section()
<<< SwitchRow("switchRowTag"){
$0.title = "Show message"
}
<<< LabelRow(){
$0.hidden = Condition.function(["switchRowTag"], { form in
return !((form.rowBy(tag: "switchRowTag") as? SwitchRow)?.value ?? false)
})
$0.title = "Switch is on!"
}
```
```swift
public enum Condition {
case function([String], (Form)->Bool)
case predicate(NSPredicate)
}
```
#### Hiding using an NSPredicate
The `hidden` variable can also be set with a NSPredicate. In the predicate string you can reference values of other rows by their tags to determine if a row should be hidden or visible.
This will only work if the values of the rows the predicate has to check are NSObjects (String and Int will work as they are bridged to their ObjC counterparts, but enums won't work).
Why could it then be useful to use predicates when they are more limited? Well, they can be much simpler, shorter and readable than functions. Look at this example:
```swift
$0.hidden = Condition.predicate(NSPredicate(format: "$switchTag == false"))
```
And we can write it even shorter since `Condition` conforms to `ExpressibleByStringLiteral`:
```swift
$0.hidden = "$switchTag == false"
```
*Note: we will substitute the value of the row whose tag is 'switchTag' instead of '$switchTag'*
For all of this to work, **all of the implicated rows must have a tag** as the tag will identify them.
We can also hide a row by doing:
```swift
$0.hidden = true
```
as `Condition` conforms to `ExpressibleByBooleanLiteral`.
Not setting the `hidden` variable will leave the row always visible.
##### Sections
For sections this works just the same. That means we can set up section `hidden` property to show/hide it dynamically.
##### Disabling rows
To disable rows, each row has an `disabled` variable which is also an optional `Condition` type property. This variable also works the same as the `hidden` variable so that it requires the rows to have a tag.
Note that if you want to disable a row permanently you can also set `disabled` variable to `true`.
### List Sections
To display a list of options, Eureka includes a special section called `SelectableSection`.
When creating one you need to pass the type of row to use in the options and the `selectionStyle`. The `selectionStyle` is an enum which can be either `multipleSelection` or `singleSelection(enableDeselection: Bool)` where the `enableDeselection` parameter determines if the selected rows can be deselected or not.
```swift
form +++ SelectableSection
#### How to create a multivalued section
In order to create a multivalued section we have to use `MultivaluedSection` type instead of the regular `Section` type. `MultivaluedSection` extends `Section` and has some additional properties to configure multivalued section behavior.
let's dive into a code example...
```swift
form +++
MultivaluedSection(multivaluedOptions: [.Reorder, .Insert, .Delete],
header: "Multivalued TextField",
footer: ".Insert adds a 'Add Item' (Add New Tag) button row as last cell.") {
$0.addButtonProvider = { section in
return ButtonRow(){
$0.title = "Add New Tag"
}
}
$0.multivaluedRowToInsertAt = { index in
return NameRow() {
$0.placeholder = "Tag Name"
}
}
$0 <<< NameRow() {
$0.placeholder = "Tag Name"
}
}
```
Previous code snippet shows how to create a multivalued section. In this case we want to insert, delete and reorder rows as multivaluedOptions argument indicates.
`addButtonProvider` allows us to customize the button row which inserts a new row when tapped and `multivaluedOptions` contains .Insert` value.
`multivaluedRowToInsertAt` closure property is called by Eureka each time a new row needs to be inserted. In order to provide the row to add into multivalued section we should set this property. Eureka passes the index as closure parameter. Notice that we can return any kind of row, even custom rows, even though in most cases multivalued section rows are of the same type.
Eureka automatically adds a button row when we create a insertable multivalued section. We can customize how the this button row looks like as we explained before. `showInsertIconInAddButton` property indicates if plus button (insert style) should appear in the left of the button, true by default.
There are some considerations we need to have in mind when creating insertable sections. Any row added to the insertable multivalued section should be placed above the row that Eureka automatically adds to insert new rows. This can be easily achieved by adding these additional rows to the section from inside section's initializer closure (last parameter of section initializer) so then Eureka adds the adds insert button at the end of the section.
For more information on how to use multivalued sections please take a look at Eureka example project which contains several usage examples.
### Validations
Eureka 2.0.0 introduces the very requested build-in validations feature.
A row has a collection of `Rules` and a specific configuration that determines when validation rules should be evaluated.
There are some rules provided by default, but you can also create new ones on your own.
The provided rules are:
* RuleRequired
* RuleEmail
* RuleURL
* RuleGreaterThan, RuleGreaterOrEqualThan, RuleSmallerThan, RuleSmallerOrEqualThan
* RuleMinLength, RuleMaxLength
* RuleClosure
Let's see how to set up the validation rules.
```swift
override func viewDidLoad() {
super.viewDidLoad()
form
+++ Section(header: "Required Rule", footer: "Options: Validates on change")
<<< TextRow() {
$0.title = "Required Rule"
$0.add(rule: RuleRequired())
// This could also have been achieved using a closure that returns nil if valid, or a ValidationError otherwise.
/*
let ruleRequiredViaClosure = RuleClosure
|
|
|
|
|
|
|
|
TextRow NameRow URLRow IntRow PhoneRow PasswordRow EmailRow DecimalRow TwitterRow AccountRow ZipCodeRow |
Picker shown in the keyboard. |
The row expands. |
The picker is always visible. |
Will show an alert with the options to choose from. |
Will show an action sheet with the options to choose from. |
Will push to a new controller from where to choose options listed using Check rows. |
Like PushRow but allows the selection of multiple options. |
|
|
Presents options of a generic type through a picker view (There is also Picker Inline Row) |
## Installation
#### CocoaPods
[CocoaPods](https://cocoapods.org/) is a dependency manager for Cocoa projects.
Specify Eureka into your project's `Podfile`:
```ruby
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '9.0'
use_frameworks!
pod 'Eureka'
```
Then run the following command:
```bash
$ pod install
```
#### Carthage
[Carthage](https://github.com/Carthage/Carthage) is a simple, decentralized dependency manager for Cocoa.
Specify Eureka into your project's `Cartfile`:
```ogdl
github "xmartlabs/Eureka" ~> 3.0
```
#### Manually as Embedded Framework
* Clone Eureka as a git [submodule](http://git-scm.com/docs/git-submodule) by running the following command from your project root git folder.
```bash
$ git submodule add https://github.com/xmartlabs/Eureka.git
```
* Open Eureka folder that was created by the previous git submodule command and drag the Eureka.xcodeproj into the Project Navigator of your application's Xcode project.
* Select the Eureka.xcodeproj in the Project Navigator and verify the deployment target matches with your application deployment target.
* Select your project in the Xcode Navigation and then select your application target from the sidebar. Next select the "General" tab and click on the + button under the "Embedded Binaries" section.
* Select `Eureka.framework` and we are done!
## Getting involved
* If you **want to contribute** please feel free to **submit pull requests**.
* If you **have a feature request** please **open an issue**.
* If you **found a bug** check older issues before submitting an issue.
* If you **need help** or would like to **ask general question**, use [StackOverflow]. (Tag `eureka-forms`).
**Before contribute check the [CONTRIBUTING](CONTRIBUTING.md) file for more info.**
If you use **Eureka** in your app We would love to hear about it! Drop us a line on [twitter].
## Authors
* [Martin Barreto](https://github.com/mtnBarreto) ([@mtnBarreto](https://twitter.com/mtnBarreto))
* [Mathias Claassen](https://github.com/mats-claassen) ([@mClaassen26](https://twitter.com/mClaassen26))
## FAQ
#### How to get a Row using its tag value
We can get a particular row by invoking any of the following functions exposed by the `Form` class:
```swift
public func rowBy
](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=HRMAH7WZ4QQ8E)
# Change Log
This can be found in the [CHANGELOG.md](CHANGELOG.md) file.