Is possible to do a custom binder on an array of input fields using RxSwift?

时光总嘲笑我的痴心妄想 提交于 2020-01-25 10:13:51

问题


I have two input fields, one for password and another one to confirm the password. I want to create a custom binder that will allow me to compare the value of both input fields but also validate minimum amount of chars. I had a pretty similar question but not regarding comparing two different fields (Is there some sort of Priority operator on RxSwift?) and based on the answer for that previous question I've been trying to do something like this:

enum PasswordCreateValidation {
    case valid
    case lessThanMinimum
    case confirmationLessThanMinimum
    case differentInputs
}

extension Reactive where Base: [InputField] {
    var rxPassword: Binder<PasswordCreateValidation> {
        return Binder<[InputField]>(self.base) { control, value in
            switch value {
            case .valid :
                control[0].errorLabel.isHidden = true
                control[1].errorLabel.isHidden = true
                control[0].separator.backgroundColor = .white
                control[1].separator.backgroundColor = .white
            case .lessThanMinimum:
                control[0].errorLabel.isHidden = false
                control[0].separator.backgroundColor = .red
                control[0].errorLabel.text = "Needs more chars"
            case .confirmationLessThanMinimum:
                control[1].errorLabel.isHidden = false
                control[1].separator.backgroundColor = .red
                control[1].errorLabel.text = "Needs more chars"
            case .differentInputs:
                control[0].errorLabel.isHidden = false
                control[0].separator.backgroundColor = .red
                control[0].errorLabel.text = "Inputs are not the same"
                control[1].errorLabel.isHidden = false
                control[1].separator.backgroundColor = .red
                control[1].errorLabel.text = "Inputs are not the same"
            }
        }
    }
}

...

private func bind() {
    let codeMinimum = codeInputField.textField.rx.text.orEmpty.map { $0.count >= 1 }.skip(2)
    codeMinimum.bind(to: codeInputField.rx.nonEmpty).disposed(by: bag)

    let minimumAmountPassword = 8
    pwdInputField.minimumAmountOfChars = minimumAmountPassword
    confirmPwdInputField.minimumAmountOfChars = minimumAmountPassword

    let pwdMinimum = pwdInputField.textField
        .rx.text.orEmpty.map { $0.count >= minimumAmountPassword }.skip(2)
    let confPwdMinimum = confirmPwdInputField.textField
        .rx.text.orEmpty.map { $0.count >= minimumAmountPassword }.skip(2)

    pwdMinimum.bind(to: pwdInputField.rx.minimumChars).disposed(by: bag)
    confPwdMinimum.bind(to: confirmPwdInputField.rx.minimumChars).disposed(by: bag)

    let pwdEqualA = pwdInputField.textField.rx.text.orEmpty
        .map { $0 == self.confirmPwdInputField.value }.skip(2)

    let pwdEqualB = confirmPwdInputField.textField.rx.text.orEmpty
        .map { $0 == self.pwdInputField.value }.skip(2)

    let equality = Observable.combineLatest(pwdEqualA, pwdEqualB) { $0 && $1 }
    let minimum = Observable.combineLatest(pwdMinimum, confPwdMinimum) { $0 && $1 }
    let pwdValidation = Observable.combineLatest(equality, minimum) { $0 && $1 }

    Observable.combineLatest(pwdValidation, codeMinimum) { $0 && $1 }
        .startWith(false)
        .bind(to: signInButton.rx.isActive)
        .disposed(by: bag)
}

Seems my custom binder is wrong. isn't it allowed to have an array as Base?


回答1:


I’d make a view that has two input fields and use that view as the base



来源:https://stackoverflow.com/questions/59691355/is-possible-to-do-a-custom-binder-on-an-array-of-input-fields-using-rxswift

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!