I was trying to get familiar with RxBinding and how it could be applied on simple forms. I was wondering if there is way to create one Action1 that performs the checks and updates the model. If I am not clear enough I hope the code below will help you understand what I mean.
Observable<CharSequence> nameObservable = RxTextView.textChanges(name).share();
Action1<CharSequence> validateAction;
Observable<CharSequence> surnameObservable = RxTextView.textChanges(surname).share();
Observable<CharSequence> emailObservable = RxTextView.textChanges(mail).share();
validateAction = new Action1<CharSequence>() {
@Override
public void call(CharSequence charSequence) {
if(state.nameState && state.surnameState && state.emailState)
submit.setBackgroundColor(getResources().getColor(R.color.green));
else
submit.setBackgroundColor(getResources().getColor(R.color.blue));
}
};
Subscription nameState = nameObservable
.subscribe(new Action1<CharSequence>() {
@Override
public void call(CharSequence charSequence) {
Log.d("Length","Len : " + charSequence.length());
if(charSequence.length() > 5)
state.nameState = true;
else
state.nameState = false;
}
});
Subscription surnameState = surnameObservable
.subscribe(new Action1<CharSequence>() {
@Override
public void call(CharSequence charSequence) {
Log.d("Length","Len : " + charSequence.length());
if(charSequence.length() > 5)
state.surnameState = true;
else
state.surnameState = false;
}
});
Subscription mailState = emailObservable
.subscribe(new Action1<CharSequence>() {
@Override
public void call(CharSequence charSequence) {
Log.d("Length","Len : " + charSequence.length());
if(charSequence.length() > 5)
state.emailState = true;
else
state.emailState = false;
}
});
Subscription nameValidate = nameObservable.subscribe(validateAction);
Subscription surnameValidate = surnameObservable.subscribe(validateAction);
Subscription mailValidate = emailObservable.subscribe(validateAction);
I have created an Action1 whose responsibility is to check the state of the model and change the color of the button, created subscriptions equal to the number of Observables and passed it as a parameter.
Something like this for example
Action1<CharSequence> lengthCheck = new Action1<CharSequence>() {
@Override
public void call(CharSequence charSequence) {
if(field is name){
if(charSequence.length() > 5)
...
}
...
}
};
So my question is , is there a way to succeed something similar to this for the Action1 that check the length ? Is it even the correct place to put a check like this? It just seems silly to me that I have the exact same code , copy and pasted three times with minimal changes.
Thanks a lot for your time.
For name validation
private Observable<Boolean> getNameObservable() {
return RxTextView.textChanges(name)
.map(charSequence -> charSequence.toString().trim().length() > 0);
}
For surname validation
private Observable<Boolean> getSurNameObservable() {
return RxTextView.textChanges(email)
.map(charSequence -> charSequence.toString().trim().length() > 0);
}
For email validation
private Observable<Boolean> getEmailObservable() {
return RxTextView.textChanges(email)
.map(charSequence -> charSequence.toString().trim().length() > 0);
}
Using combineLatest
to combine 3 observables as 1 stream
Observable.combineLatest(getNameObservable(),getSurNameObservable(), getEmailObservable,
(nameValid, surnameValid,emailValid) -> nameValid && surnameValid && emailValid)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(isAllFieldsValid ->
enableButton(yourButton, isAllFieldsValid));
The enable function
private void enableButton(Button button, boolean isAvailable) {
button.setEnabled(isAvailable);
if (isAvailable) {
button.setBackgroundResource(R.drawable.green);
} else {
button.setBackgroundResource(R.drawable.blue);
}
}
=========================================================================
PS: You can create a function that create an Observable for 3 EditText
private Observable<Boolean> getNameObservable(EditText et) {
return RxTextView.textChanges(et)
.map(charSequence -> charSequence.toString().trim().length() > 0);
}