Hot questions for Using Eureka in swift2

Question:

We are evaluating Eureka Forms, and have created a simple form with a couple FieldRows. I see how you can get all the values out of a form, and how you can respond when any row is changed at all using onChange() (on a character by character basis) but it is not obvious to me how one responds to a field's editing finishing completely, rather than as each character is typed.

In a normal textfield, we could set the view controller or the cell of a tableview to be the textfield's delegate and respond to textField:didFinishEditing: and handle it there.

How does one do that with a Eureka Forms field row?

Thanks


Answer:

just to add to the answer here, I ended up using

        .onCellHighlightChanged({ (cell, row) in
            if row.isHighlighted == false {
                self.updateUser()
            }
        })

and then just checking if the cell isHighlighted or not.

This was using Eureka 4.0

Question:

My use case describes the necessity of a field in which the user can select multiple phases that goes from A to F. To achieve that I used the MultipleSelectorRow n Eureka library:

<<< MultipleSelectorRow<String>("phase") {
        $0.title = "Phase"
        $0.options = ["A", "B", "C", "D", "E", "F"]
    }

When the user selects any of the options I want the value to display the selected options in alphabetical order "A,B,C...", what happens is that the text is always displayed in a random order, I've tried to achieve the alphabetical order by extending the code:

<<< MultipleSelectorRow<String>("phase") {
        $0.title = "Phase"
        $0.options = ["A", "B", "C", "D", "E", "F"]
    }.onChange { row in
        row.value = Set(row.value!.sort())
    }

The expression is evaluated correctly, but I still can't get the values sorted in the alphabetical order.


Answer:

While posting the question I realize that as Eureka uses a Set to store the fields it will never be sorted.

In this case I've changed the cellUpdate method to update the detailTextLabel with the sorted values as stated bellow:

<<< MultipleSelectorRow<String>("phase") {
        $0.title = "Phase"
        $0.options = ["A", "B", "C", "D", "E", "F"]
    }.cellUpdate { cell, row in
        if (row.value != nil) {
            cell.detailTextLabel?.text =  row.value!.sort().joinWithSeparator(", ")
        }
    }

I also proposed a fix on the Eureka library to sort alphabetically by default. More details on https://github.com/xmartlabs/Eureka/pull/474

Update This was fixed and released on Eureka 1.7.0 (2016.07.07)

Question:

This is a question related to the Swift open source project called Eureka and I'm posting this question here on SO since they monitor their tag here.

Okay so I create a form in the viewDidLoad method of a view controller. At the same time I make a http call to an API to get a list of data (jobs). This call is asynchronous. I want to display these jobs as option values in a PushRow.

Since this API call is asynchronous, by the time this data is received, the form is already set up. I have a class level array setup to be populated with the list of jobs from the http call. That same array is assigned to that row's options property. I assign the values to the array when I receive the data. But then when I go and tap on the PushRow, it's empty.

class CreateEventViewController: FormViewController {

    private var jobs = [Job]()

    override func viewDidLoad() {
        super.viewDidLoad()

        setupForm()

        api.getJobs(.LeadCreated) { jobs, error in
            if let error = error {
                print(error.localizedDescription)
                return
            }

            if let jobs = jobs {
                self.jobs = jobs
            }
        }
    }

    private func setupForm() {
        form
            +++ Section()
            <<< PushRow<String>("Jobs") {
                $0.title = "Choose Job"
                $0.options = jobs.map { $0.description }
                $0.selectorTitle = "Choose..."
            }.onPresent { from, to in
                to.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Done, target: from, action: #selector(CreateEventViewController.multipleSelectorDone(_:)))
            }
    }

}

Is there some sort of a way to refresh or reload the data for a specific row or the form as a whole?


Update 1

As per Kevin's answer below, I modified my code as below.

override func viewDidLoad() {
    super.viewDidLoad()

    api.getJobs(.LeadCreated) { jobs, error in
        if let error = error {
            print(error.localizedDescription)
            return
        }

        if let jobs = jobs {
            self.jobs = jobs

            if let jobsRow = self.form.rowByTag("Jobs") {
                jobsRow.updateCell()
            }
        }
    }

    setupForm()
}

But for some reason, it's still not working. The options are empty. The cell is correctly picked up via the tag, I checked. Anyway failing this, I also tried tableView.reloadData() as well but to no avail.


Answer:

I found it! You had to add the .cellUpdate {...} closure to the row and inside it assign the values to the options property. Like so,

<<< PushRow<String>("Jobs") {
    $0.title = "Choose Job"
    $0.options = jobs.map { $0.description }
    $0.selectorTitle = "Choose..."
}
.cellUpdate { cell, row in
    row.options = self.jobs.map { $0.description }
}

Question:

This is a question related to the Swift open source project called Eureka and I'm posting this question here on SO since they monitor their tag here.

I have created a form which has a MultipleSelectorRow and following that, a TextRow. That TextRow is disabled by default. The MultipleSelectorRow shows a list of options.

form
    +++ Section()
    <<< MultipleSelectorRow<String>("Lead") {
        $0.title = "Lead"
        $0.options = ["Yahoo", "Yelp", "Google", "Referral or Other"]
    }
    .onPresent { from, to in
        to.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Done, target: from, action: #selector(ViewController.multipleSelectorDone(_:)))
    }
    <<< TextRow("Referral") {
        $0.title = "Note Referral or Other"
        $0.disabled = "$Lead != 'Referral or Other'"
    }

What I want is if the user selects the last option, Referral or Other, I want the TextRow to be enabled.

My current implementation above doesn't do this. It stays disabled. What am I doing wrong here?


Answer:

By definition MultipleSelectorRow<T> holds a Set<T> as a value type and seems you are wrongly expecting a String value.

Having said that you should try on with this predicate...

$0.disabled = "NOT $Lead contains 'Referral or Other'"

or alternatively..

$0.hidden = Condition.Function(["Lead"]) { form in
        if let r1 : MultipleSelectorRow <String> = form?.rowByTag("tag1") {
            return r1.value.contains("Referral or Other") == false
        }
        return false
}

Question:

I'm trying display the integer values instead of float. I tried the following:

    section.append(SliderRow() {
        $0.title = "Number of items"
        $0.tag = "numberOfItems"
        $0.minimumValue = 1
        $0.maximumValue = 10
        $0.steps = 10
        $0.value = 5
        $0.onChange { row in
            let isInteger = floor(row.value!) == row.value!
            if (!isInteger) {
                row.value = floor(row.value!)
            }

            let formattedString = String(format: "%.0f", row.value!)
            row.cell.valueLabel.text = formattedString
        }
    })

formattedString displays the values I want but I'm not able to display them on the screen. I can access all other attributes by row.cell. I change change the text colour, for instance, but not the text. I'm guessing I'm setting the text but it gets overwritten shortly.

Is there a way to make the slider show integer values?

Thanks.


Answer:

since Dec 2, 2016, there's a much simpler approach.....

$0.displayValueFor = {
   return "\(Int($0 ?? 0))"
}

(credit to https://github.com/xmartlabs/Eureka/issues/817 showing how to do it - and the associated fix)

This works great for showing an Int in the Eureka SliderRow as well as StepperRow See this picture of xcode Simulator showing Int values on StepperRow and SliderRow