title: How to implement validation using ViewModel and Databinding?
body: <p>What is the best approach to validate form data using ViewModel and Databinding?</p>
  
  <p>I have a simple Sign-Up activity that links binding layout and ViewModel</p>
  
  <pre><code>class StartActivity : AppCompatActivity() {
  
      private lateinit var binding: StartActivityBinding
      private lateinit var viewModel: SignUpViewModel
  
      override fun onCreate(savedInstanceState: Bundle?) {
          super.onCreate(savedInstanceState)
  
          viewModel = ViewModelProviders.of(this, SignUpViewModelFactory(AuthFirebase()))
                  .get(SignUpViewModel::class.java);
  
          binding = DataBindingUtil.setContentView(this, R.layout.start_activity)
          binding.viewModel = viewModel;
  
          signUpButton.setOnClickListener {
  
          }
      }
  }
  </code></pre>
  
  <p><code>ViewModel</code> with 4 <code>ObservableFields</code> and <code>signUp()</code> method that should validate data before submitting data to the server.</p>
  
  <pre><code>class SignUpViewModel(val auth: Auth) : ViewModel() {
      val name: MutableLiveData&lt;String&gt; = MutableLiveData()
      val email: MutableLiveData&lt;String&gt; = MutableLiveData()
      val password: MutableLiveData&lt;String&gt; = MutableLiveData()
      val passwordConfirm: MutableLiveData&lt;String&gt; = MutableLiveData()
  
      fun signUp() {
  
          auth.createUser(email.value!!, password.value!!)
      }
  }
  </code></pre>
  
  <p>I guess we can add four boolean ObservableFields for each input, and in <code>signUp()</code> we can check inputs and change state of boolean ObservableField that will produce an appearing error on layout </p>
  
  <pre><code>val isNameError: ObservableField&lt;Boolean&gt; = ObservableField()
  
  
  fun signUp() {
  
          if (name.value == null || name.value!!.length &lt; 2 ) {
              isNameError.set(true)
          }
  
          auth.createUser(email.value!!, password.value!!)
      }
  </code></pre>
  
  <p>But I am not sure that <code>ViewModel</code> should be responsible for validation and showing an error for a user and we will have boilerplate code</p>
  
  <pre><code>&lt;layout xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto"&gt;
  
      &lt;data&gt;
  
          &lt;import type="android.view.View" /&gt;
  
          &lt;variable
              name="viewModel"
              type="com.maximdrobonoh.fitnessx.SignUpViewModel" /&gt;
      &lt;/data&gt;
  
      &lt;android.support.constraint.ConstraintLayout
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:background="@color/colorGreyDark"
          android:orientation="vertical"
          android:padding="24dp"&gt;
  
          &lt;TextView
              android:id="@+id/appTitle"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:layout_marginEnd="8dp"
              android:layout_marginStart="8dp"
              android:layout_marginTop="8dp"
              android:text="@string/app_title"
              android:textColor="@color/colorWhite"
              android:textSize="12sp"
              app:layout_constraintEnd_toEndOf="parent"
              app:layout_constraintStart_toStartOf="parent"
              app:layout_constraintTop_toTopOf="parent" /&gt;
  
          &lt;LinearLayout
              android:id="@+id/screenTitle"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:layout_marginEnd="8dp"
              android:layout_marginStart="8dp"
              android:orientation="horizontal"
              app:layout_constraintEnd_toEndOf="parent"
              app:layout_constraintStart_toStartOf="parent"
              app:layout_constraintTop_toBottomOf="@+id/appTitle"&gt;
  
              &lt;TextView
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:layout_marginEnd="4dp"
                  android:text="@string/sign"
                  android:textColor="@color/colorWhite"
                  android:textSize="26sp"
                  android:textStyle="bold" /&gt;
  
              &lt;TextView
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
                  android:text="@string/up"
                  android:textColor="@color/colorWhite"
                  android:textSize="26sp" /&gt;
          &lt;/LinearLayout&gt;
  
          &lt;LinearLayout
              android:id="@+id/form"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:layout_marginEnd="8dp"
              android:layout_marginStart="8dp"
              android:layout_marginTop="24dp"
              android:orientation="vertical"
              app:layout_constraintEnd_toEndOf="parent"
              app:layout_constraintStart_toStartOf="parent"
              app:layout_constraintTop_toBottomOf="@+id/screenTitle"&gt;
  
              &lt;android.support.v7.widget.AppCompatEditText
                  style="@style/SignUp.InputBox"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:hint="@string/sign_up_name"
                  android:inputType="textPersonName"
                  android:text="@={viewModel.name}" /&gt;
  
              &lt;android.support.v7.widget.AppCompatEditText
                  style="@style/SignUp.InputBox"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:hint="@string/sign_up_email"
                  android:inputType="textEmailAddress"
                  android:text="@={viewModel.email}"
                 /&gt;
  
              &lt;android.support.v7.widget.AppCompatEditText
                  style="@style/SignUp.InputBox"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:hint="@string/sign_up_password"
                  android:inputType="textPassword"
                  android:text="@={viewModel.password}" /&gt;
  
              &lt;android.support.v7.widget.AppCompatEditText
                  style="@style/SignUp.InputBox"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:hint="@string/sign_up_confirm_password"
                  android:inputType="textPassword"
                  android:text="@={viewModel.passwordConfirm}" /&gt;
  
              &lt;Button
                  android:id="@+id/signUpButton"
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:layout_marginTop="16dp"
                  android:background="@drawable/button_gradient"
                  android:text="@string/sign_up_next_btn"
                  android:textAllCaps="true"
                  android:textColor="@color/colorBlack" /&gt;
  
          &lt;/LinearLayout&gt;
  
      &lt;/android.support.constraint.ConstraintLayout&gt;
  &lt;/layout&gt;
  </code></pre>