RxSwift enable/disable button based on textfield input

烈酒焚心 提交于 2021-02-11 12:29:42

问题


I have to implement below scenarios with RxSwift MVVM

I have two textfields (OTP & Confirm OTP) and a Submit button, If user clicks on the OTP textfield when there is no value on the OTP textfield then submit button should be disabled, Now if user types something in otp textfield button should be enabled. Now if user taps on the second text field as it is blank now then the button should be disabled again & its get enabled only when there is a value.

So basically I want to enable/disable the button by checking:

  1. If OTP field has value then enable the button or disable it if no value
  2. User taps on the Confirm OTP field, it is empty now so disable the button again
  3. If user deletes the value from OTP field, disable the button again (As it is empty, same with Confirm OTP field)

Thanks


回答1:


Updated answer:

As @Daniel T. noted, this can be solved without using the Subject:

let disposeBag = DisposeBag()

let otpFieldIsFocused = Observable.merge(
    otpField.rx.controlEvent(.editingDidBegin).map { true },
    otpField.rx.controlEvent(.editingDidEnd).map { false }
)

// Sends only when the field is first responder
let otpFieldIsNotEmpty = otpField.rx.text.orEmpty
    .map { $0.isEmpty }
    .withLatestFrom(otpFieldIsFocused) {
        (isEmpty: $0, isFocused: $1)
    }
    .filter { $0.isFocused }
    .map { !$0.isEmpty }

let otpConfirmFieldIsFocused = Observable<Bool>.merge(
    otpConfirmField.rx.controlEvent(.editingDidBegin).map { true },
    otpConfirmField.rx.controlEvent(.editingDidEnd).map { false }
)

let otpConfirmFieldIsNotEmpty = otpConfirmField.rx.text.orEmpty
    .map { $0.isEmpty }
    .withLatestFrom(otpConfirmFieldIsFocused) {
        (isEmpty: $0, isFocused: $1)
    }
    .filter { $0.isFocused }
    .map { !$0.isEmpty }

Observable.merge(otpFieldIsNotEmpty, otpConfirmFieldIsNotEmpty)
    .startWith(false)
    .bind(to: button.rx.isEnabled)
    .disposed(by: disposeBag)

Old answer:

This can be done using the switchLatest statement:

import RxSwift
import RxCocoa

...

let disposeBag = DisposeBag()
let subject = PublishSubject<Observable<String>>()

otpField.rx
    .controlEvent(.editingDidBegin)
    .subscribe(onNext: {
        subject.onNext(otpField.rx.text.orEmpty.asObservable())
    })
    .disposed(by: disposeBag)

otpConfirmField.rx
    .controlEvent(.editingDidBegin)
    .subscribe(onNext: {
        subject.onNext(otpConfirmField.rx.text.orEmpty.asObservable())
    })
    .disposed(by: disposeBag)

subject
    .switchLatest()
    .map { !$0.isEmpty }
    .startWith(false)
    .distinctUntilChanged()
    .bind(to: button.rx.isEnabled)
    .disposed(by: disposeBag)

otpField.becomeFirstResponder()

If you need to disable the button, for example, when both fields lose focus, then you can do it like this:

subject.onNext(.just(""))


来源:https://stackoverflow.com/questions/65810539/rxswift-enable-disable-button-based-on-textfield-input

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