Skip to content

Connect enabledIf after init #170

@AlexisQapa

Description

@AlexisQapa

Hello,

I've been looking into this lib and it's working nice. The only thing I can't manage is to bind the enabledIf observable after the action init. This would be useful to inject actions into viewModels. Right now providing the work factory and the enabledIf at the same time is very inconvenient.

Here is an example of my viewModel :
`final class ExampleViewModel {

private let bag = DisposeBag()
let input: Input
let output: Output

init() {

    let isFormValid = PublishSubject<Bool>()
    let formValue = PublishSubject<MyFormValue>()
    let tap = PublishSubject<Void>()
    let isEnabled = PublishSubject<Bool>()
    let isExecuting = PublishSubject<Bool>()
    let error = PublishSubject<Error>()
    let success = PublishSubject<Void>()

    self.input = Input(isValid: isFormValid.asObserver(),
                       formValue: formValue.asObserver(),
                       tap: tap.asObserver())
    self.output = Output(isEnabled: isEnabled.asDriverAssertError(),
                         isExecuting: isExecuting.asDriverAssertError(),
                         error: error.asDriverAssertError(),
                         success: success.asDriverAssertError())

    let saveAction =  Action(enabledIf: isFormValid.asObservable(), workFactory: save)

    saveAction.enabled
        .asDriverIgnoreError()
        .drive(isEnabled)
        .disposed(by: bag)

    saveAction.executing
        .asDriverIgnoreError()
        .drive(isExecuting)
        .disposed(by: bag)

    saveAction.executionObservables
        .switchLatest()
        .filterMap { (result) -> FilterMap<Error> in
            guard case .failure(let underlyingError) = result else { return .ignore }
            return .map(underlyingError)
        }
        .asDriverAssertError()
        .drive(error)
        .disposed(by: bag)

    saveAction.executionObservables
        .switchLatest()
        .filterMap { (result) -> FilterMap<Void> in
            guard case .success = result else { return .ignore }
            return .map(())
        }
        .asDriverIgnoreError()
        .drive(success)
        .disposed(by: bag)

    tap
        .withLatestFrom(formValue)
        .subscribe(onNext: { (value) in
            saveAction.execute(value)
        })
        .disposed(by: bag)
}

func save(formData: MyFormValue) -> Observable<Either<Void, Error>> {
    return Observable<Either<Void, Error>>.create { observer in
        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
            let result: Either<Void, Error> = Bool.random() ? .success : .failure(MyError)
            observer.onNext(result)
            observer.onCompleted()
        }
        return Disposables.create()
    }
}

}

extension ExampleViewModel {
struct Input {
let isValid: AnyObserver
let formValue: AnyObserver
let tap: AnyObserver
}

struct Output {
    let isEnabled: Driver<Bool>
    let isExecuting: Driver<Bool>
    let error: Driver<Error>
    let success: Driver<Void>
}

}`

Being able to bind enabledIf after the init would allow me to drop most of the subjects.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions