Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Data Binding - EditText SetError

We are using the Kubwa validation library to validate the forms with android data binding library, but the error is not showing in the EditTexts.

ViewModel:

@Override
public void onLoginClick(View view) {

    validator.validateEmail(user.getEmail());
    validator.validatePassword(user.getPassword());

    notifyChange();

    if (validator.isValid()) connector.login(user);
}

@Bindable
@Override
public String getEmailError() {
    return validator.getEmailErrorMessage();
}

@Bindable
@Override
public String getPasswordError() {
    return validator.getPasswordErrorMessage();
}

And my xml:

<EditText
android:id="@+id/email"
android:text="@={viewModel.user.email}"
app:error="@{viewModel.emailError}"/> <!-- As the wiki said -->

When I realized that that doesn't work I created a BindingAdapter and changed the xml attribute, but it isn't working either.

@BindingAdapter("app:errorText")
public static void BindError(EditText view, String error){
    view.setError(error);
}

Any insight is greatly appreciated

like image 707
J. Pichardo Avatar asked Dec 09 '16 21:12

J. Pichardo


2 Answers

I tried out something similar to your example and it worked fine.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    User user = new User();
    ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
    binding.setUser(user);
}

and the Observable -- I put the validation in the setName, but yours should be the same. You may prefer to have it in the InverseBindingAdapter instead:

public class User extends BaseObservable {
    private String name;

    @Bindable
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        notifyPropertyChanged(com.example.gmount.tryoutdamnthing.BR.name);
        notifyPropertyChanged(com.example.gmount.tryoutdamnthing.BR.error);
    }

    @Bindable
    public String getError() {
        if (name == null || name.length() < 3) {
            return "Too short!";
        } else {
            return null;
        }
    }
}

and the layout:

<layout>
    <data>
        <variable name="user" type="com.example.gmount.tryoutdamnthing.User"/>
    </data>

    <FrameLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            android:id="@+id/activity_main"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
    >

        <EditText
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@={user.name}"
                app:error="@{user.error}"
        />

    </FrameLayout>
</layout>

My guess is that you didn't use the DataBindingUtil.setContentView() or forgot to set the ViewModel object in the binding. Sometimes this happens because people use Activity.setContentView() after DataBindingUtil.setContentView().

You can see here that I don't need a BindingAdapter for app:error because the setter's name is the same as the attribute.

like image 173
George Mount Avatar answered Oct 07 '22 14:10

George Mount


This is more a question on how to use the Data Binding library. You're binding errorText to the error, but in the layout you use error. Changing the BindingAdapter to @BindingAdapter({"app:error"}) should fix the error

like image 36
Boots Avatar answered Oct 07 '22 14:10

Boots