From 4009c9545f66b0d5d997a65c32afa80e227bd7e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zden=C4=9Bk=20Bal=C3=A1k?= Date: Thu, 2 May 2019 15:26:00 +0200 Subject: [PATCH] FEAT: implement proper validation --- .../formbuilderproject/MainActivity.kt | 3 +- .../qase/android/formbuilderlibrary/Form.kt | 10 ++++++- .../element/EditTextElement.kt | 28 +++++++++++-------- .../element/LabelDateTimeElement.kt | 22 +++++++++++++++ .../element/LabelInputElement.kt | 25 +++++++++-------- .../element/generic/FormElementValidatable.kt | 13 ++------- .../validator/NotInFutureValidator.kt | 19 +++++++++++++ .../validator/NotInPastValidator.kt | 19 +++++++++++++ 8 files changed, 104 insertions(+), 35 deletions(-) create mode 100644 formbuilderlibrary/src/main/java/cz/qase/android/formbuilderlibrary/validator/NotInFutureValidator.kt create mode 100644 formbuilderlibrary/src/main/java/cz/qase/android/formbuilderlibrary/validator/NotInPastValidator.kt diff --git a/app/src/main/java/cz/qase/android/formbuilderproject/MainActivity.kt b/app/src/main/java/cz/qase/android/formbuilderproject/MainActivity.kt index f468817..42290b6 100644 --- a/app/src/main/java/cz/qase/android/formbuilderproject/MainActivity.kt +++ b/app/src/main/java/cz/qase/android/formbuilderproject/MainActivity.kt @@ -13,6 +13,7 @@ import cz.qase.android.formbuilderlibrary.element.generic.CheckboxCallback import cz.qase.android.formbuilderlibrary.element.generic.ValueCallback import cz.qase.android.formbuilderlibrary.validator.MaxLengthFormValidator import cz.qase.android.formbuilderlibrary.validator.NotBlankFormValidator +import cz.qase.android.formbuilderlibrary.validator.NotInPastValidator import kotlinx.android.synthetic.main.activity_main.* import org.joda.time.DateTime import java.text.SimpleDateFormat @@ -96,7 +97,7 @@ class MainActivity : AppCompatActivity() { addElement(LabelSwitchElement("LabelSwitchElement label", true, showToastCheckboxCallback), true) addElement(LabelSpinnerElement("LabelSpinnerElement label", "Option one", stringValues, showToastStringValueCallback), true) addElement(LabelCheckboxElement("LabelCheckboxElement label", true, showToastCheckboxCallback), true) - addElement(LabelDateTimeElement("Date picker", "Vyberte datum...", supportFragmentManager, valueChangeListener = showToastDateTimeValueCallback)) + addElement(LabelDateTimeElement("Date picker", "Vyberte datum...", supportFragmentManager, showToastDateTimeValueCallback, formValidators = arrayListOf(NotInPastValidator("Date cannot be in past")))) addSpace() diff --git a/formbuilderlibrary/src/main/java/cz/qase/android/formbuilderlibrary/Form.kt b/formbuilderlibrary/src/main/java/cz/qase/android/formbuilderlibrary/Form.kt index 0f8034b..65491cc 100644 --- a/formbuilderlibrary/src/main/java/cz/qase/android/formbuilderlibrary/Form.kt +++ b/formbuilderlibrary/src/main/java/cz/qase/android/formbuilderlibrary/Form.kt @@ -20,8 +20,16 @@ class Form(val context: Context, @Throws(ValidationException::class) fun validate() { + var validationException: ValidationException? = null for (formElement in elements) { - formElement.validate() + try { + formElement.validate() + } catch (e: ValidationException) { + validationException = e + } + } + if(validationException!=null){ + throw validationException } } diff --git a/formbuilderlibrary/src/main/java/cz/qase/android/formbuilderlibrary/element/EditTextElement.kt b/formbuilderlibrary/src/main/java/cz/qase/android/formbuilderlibrary/element/EditTextElement.kt index 77b360c..f8ba613 100644 --- a/formbuilderlibrary/src/main/java/cz/qase/android/formbuilderlibrary/element/EditTextElement.kt +++ b/formbuilderlibrary/src/main/java/cz/qase/android/formbuilderlibrary/element/EditTextElement.kt @@ -7,6 +7,7 @@ import android.text.Editable import android.text.TextWatcher import android.view.View import cz.qase.android.formbuilderlibrary.FormStyleBundle +import cz.qase.android.formbuilderlibrary.ValidationException import cz.qase.android.formbuilderlibrary.common.setBackgroundColorResourceId import cz.qase.android.formbuilderlibrary.common.setTextColorResourceId import cz.qase.android.formbuilderlibrary.element.generic.FormElementValidatable @@ -52,10 +53,8 @@ open class EditTextElement( editText?.addTextChangedListener(object : TextWatcher { override fun afterTextChanged(s: Editable) { text = s.toString() - validate() - if(!invalid) { - valueChangeListener?.callback(s.toString()) - } + positiveValidation() + valueChangeListener?.callback(s.toString()) } override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { @@ -68,14 +67,21 @@ open class EditTextElement( return textInputLayout!! } + private fun positiveValidation() { + try { + super.validate() + textInputLayout?.error = null + } catch (e: ValidationException) { + } + } + override fun validate() { - super.validate() - if (textInputLayout != null) { - if (invalid) { - textInputLayout?.error = invalidMessage - } else { - textInputLayout?.error = null - } + try { + super.validate() + textInputLayout?.error = null + } catch (e: ValidationException) { + textInputLayout?.error = e.message + throw e } } diff --git a/formbuilderlibrary/src/main/java/cz/qase/android/formbuilderlibrary/element/LabelDateTimeElement.kt b/formbuilderlibrary/src/main/java/cz/qase/android/formbuilderlibrary/element/LabelDateTimeElement.kt index bc13b53..6421775 100644 --- a/formbuilderlibrary/src/main/java/cz/qase/android/formbuilderlibrary/element/LabelDateTimeElement.kt +++ b/formbuilderlibrary/src/main/java/cz/qase/android/formbuilderlibrary/element/LabelDateTimeElement.kt @@ -9,6 +9,7 @@ import android.view.ViewGroup import android.widget.TextView import cz.qase.android.formbuilderlibrary.FormStyleBundle import cz.qase.android.formbuilderlibrary.R +import cz.qase.android.formbuilderlibrary.ValidationException import cz.qase.android.formbuilderlibrary.common.setBackgroundColorResourceId import cz.qase.android.formbuilderlibrary.common.setTextColorResourceId import cz.qase.android.formbuilderlibrary.element.generic.FormElementValidatable @@ -58,6 +59,7 @@ class LabelDateTimeElement(private val label: String, view.setBackgroundColorResourceId(context, formStyleBundle.secondaryBackgroundColor) } MotionEvent.ACTION_DOWN -> { + textView.requestFocus() view.setBackgroundColorResourceId(context, formStyleBundle.primaryBackgroundColor) } } @@ -78,6 +80,7 @@ class LabelDateTimeElement(private val label: String, val dateTime = DateTime(newDate) value = dateTime textView.text = sdf.format(newDate) + positiveValidation() valueChangeListener.callback(dateTime) } textView.setOnClickListener { @@ -102,6 +105,25 @@ class LabelDateTimeElement(private val label: String, textView?.text = text } + private fun positiveValidation() { + try { + super.validate() + textView?.error = null + } catch (e: ValidationException) { + } + } + + override fun validate() { + try { + super.validate() + textView?.error = null + } catch (e: ValidationException) { + textView?.text = e.message + textView?.error = e.message + throw e + } + } + private fun prepareLabel(inflater: LayoutInflater, context: Context, formStyleBundle: FormStyleBundle, root: ViewGroup): TextView { val headerView = inflater.inflate(headerComponent, root, false) as TextView headerView.setTextColorResourceId(context, formStyleBundle.primaryTextColor) diff --git a/formbuilderlibrary/src/main/java/cz/qase/android/formbuilderlibrary/element/LabelInputElement.kt b/formbuilderlibrary/src/main/java/cz/qase/android/formbuilderlibrary/element/LabelInputElement.kt index f4a0cd1..ca129a7 100644 --- a/formbuilderlibrary/src/main/java/cz/qase/android/formbuilderlibrary/element/LabelInputElement.kt +++ b/formbuilderlibrary/src/main/java/cz/qase/android/formbuilderlibrary/element/LabelInputElement.kt @@ -11,6 +11,7 @@ import android.view.ViewGroup import android.widget.TextView import cz.qase.android.formbuilderlibrary.FormStyleBundle import cz.qase.android.formbuilderlibrary.R +import cz.qase.android.formbuilderlibrary.ValidationException import cz.qase.android.formbuilderlibrary.common.setBackgroundColorResourceId import cz.qase.android.formbuilderlibrary.common.setTextColorResourceId import cz.qase.android.formbuilderlibrary.element.generic.FormElementValidatable @@ -40,7 +41,8 @@ class LabelInputElement(private val label: String, val view = inflater.inflate(groupComponent, null) as ViewGroup val headerView = prepareLabel(inflater, context, this.formStyleBundle ?: formStyleBundle, view) - val inputView = prepareText(inflater, context, this.formStyleBundle ?: formStyleBundle, view) + val inputView = prepareText(inflater, context, this.formStyleBundle + ?: formStyleBundle, view) view.setBackgroundColorResourceId(context, formStyleBundle.secondaryBackgroundColor) view.addView(headerView) view.addView(inputView) @@ -59,9 +61,8 @@ class LabelInputElement(private val label: String, override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { value = s.toString() positiveValidation() - if (!invalid) { - valueChangeListener.callback(s.toString()) - } + valueChangeListener.callback(s.toString()) + } override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { @@ -83,19 +84,21 @@ class LabelInputElement(private val label: String, textInputEditText?.setText(text) } - private fun positiveValidation(){ - super.validate() - if (!invalid) { + private fun positiveValidation() { + try { + super.validate() textInputLayout?.error = null + } catch (e: ValidationException) { } } override fun validate() { - super.validate() - if (invalid) { - textInputLayout?.error = invalidMessage - } else { + try { + super.validate() textInputLayout?.error = null + } catch (e: ValidationException) { + textInputLayout?.error = e.message + throw e } } diff --git a/formbuilderlibrary/src/main/java/cz/qase/android/formbuilderlibrary/element/generic/FormElementValidatable.kt b/formbuilderlibrary/src/main/java/cz/qase/android/formbuilderlibrary/element/generic/FormElementValidatable.kt index e4c20f9..45d3deb 100644 --- a/formbuilderlibrary/src/main/java/cz/qase/android/formbuilderlibrary/element/generic/FormElementValidatable.kt +++ b/formbuilderlibrary/src/main/java/cz/qase/android/formbuilderlibrary/element/generic/FormElementValidatable.kt @@ -3,9 +3,7 @@ package cz.qase.android.formbuilderlibrary.element.generic import cz.qase.android.formbuilderlibrary.ValidationException import cz.qase.android.formbuilderlibrary.validator.FormValidator -abstract class FormElementValidatable(val formValidators: MutableList> = ArrayList(), - var invalid: Boolean = false, - var invalidMessage: String? = null) : FormElement() { +abstract class FormElementValidatable(val formValidators: MutableList> = ArrayList()) : FormElement() { fun addValidator(formValidator: FormValidator) { formValidators.add(formValidator) @@ -13,15 +11,8 @@ abstract class FormElementValidatable(val formValidators: MutableList { + override fun validate(value: DateTime?) { + if (value != null && value.isAfterNow) { + throw ValidationException(errorMsg) + } + } +} diff --git a/formbuilderlibrary/src/main/java/cz/qase/android/formbuilderlibrary/validator/NotInPastValidator.kt b/formbuilderlibrary/src/main/java/cz/qase/android/formbuilderlibrary/validator/NotInPastValidator.kt new file mode 100644 index 0000000..79669bd --- /dev/null +++ b/formbuilderlibrary/src/main/java/cz/qase/android/formbuilderlibrary/validator/NotInPastValidator.kt @@ -0,0 +1,19 @@ +package cz.qase.android.formbuilderlibrary.validator + +import cz.qase.android.formbuilderlibrary.ValidationException +import org.joda.time.DateTime + +/** + * MaxLengthFormValidator + * + * Check if length of form value is bigger than specified value + */ +class NotInPastValidator( + private val errorMsg: String +) : FormValidator { + override fun validate(value: DateTime?) { + if (value != null && value.isBeforeNow) { + throw ValidationException(errorMsg) + } + } +}