Android Databinding with LiveData - Validating multiple fields together Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30pm US/Eastern) Data science time! April 2019 and salary with experience The Ask Question Wizard is Live!Is it possible to make one LiveData of two LiveDatas?Android LiveData and DataBindingLivedata class inner members in databindingHow can I do databinding with livedata?Databind LiveData to CustomViewDatabinding not observe LiveData in ViewModelAndroid DataBinding LiveData - not notify changed in DialogFragment & BottomSheetDialogFragmentAndroid databinding and LiveData: Can't bind to value in LiveData propertyBoundService + LiveData + ViewModel best practice in new Android recommended architectureAndroid mvvm livedata and databindingEnable a button when all EditText complete

In musical terms, what properties are varied by the human voice to produce different words / syllables?

Antipodal Land Area Calculation

Why does it sometimes sound good to play a grace note as a lead in to a note in a melody?

How can I prevent/balance waiting and turtling as a response to cooldown mechanics

Does "shooting for effect" have contradictory meanings in different areas?

Tannaka duality for semisimple groups

preposition before coffee

The Nth Gryphon Number

Crossing US/Canada Border for less than 24 hours

C's equality operator on converted pointers

Sliceness of knots

Why can't I install Tomboy in Ubuntu Mate 19.04?

What does Turing mean by this statement?

What order were files/directories output in dir?

What's the point of the test set?

Drawing spherical mirrors

How to report t statistic from R

Is there public access to the Meteor Crater in Arizona?

How does Belgium enforce obligatory attendance in elections?

What does it mean that physics no longer uses mechanical models to describe phenomena?

Most bit efficient text communication method?

Random body shuffle every night—can we still function?

What initially awakened the Balrog?

Has negative voting ever been officially implemented in elections, or seriously proposed, or even studied?



Android Databinding with LiveData - Validating multiple fields together



Announcing the arrival of Valued Associate #679: Cesar Manara
Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30pm US/Eastern)
Data science time! April 2019 and salary with experience
The Ask Question Wizard is Live!Is it possible to make one LiveData of two LiveDatas?Android LiveData and DataBindingLivedata class inner members in databindingHow can I do databinding with livedata?Databind LiveData to CustomViewDatabinding not observe LiveData in ViewModelAndroid DataBinding LiveData - not notify changed in DialogFragment & BottomSheetDialogFragmentAndroid databinding and LiveData: Can't bind to value in LiveData propertyBoundService + LiveData + ViewModel best practice in new Android recommended architectureAndroid mvvm livedata and databindingEnable a button when all EditText complete



.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








0















I am using two-way Databinding with LiveData inside a ViewModel to handle a sign-up form.



As fields are filled out, there are fields that need to be evaluated together for validity (as well as the overall form), and only enable the Submit button when everything is correct.



With a regular Observable object and using @Bindable this would be straightforward by just annotating a 'getter' function for each validation that is required and doing the necessary validation steps and return the appropriate result inside each function.



BUT I am working with LiveData. I came up with a solution using MediatoLiveData (see basic example below), but it seems to me like there should be another, perhaps better, approach.



class RegistrationViewModel : ViewModel() 
val email: MutableLiveData<String> by lazy MutableLiveData<String>()

val emailConf: MutableLiveData<String> by lazy MutableLiveData<String>()

val emailValid: MediatorLiveData<Boolean> = MediatorLiveData()

val emailChanged: (Any) -> Unit = cc@

//Obviously there is more validation needed but this is just an example
if (email.value != null && emailConf.value != null)

emailValid.value = email.value.isNotEmpty() && emailConf.value.isNotEmpty() && email.value == emailConf.value
return@cc


emailValid.value = false


init
emailValid.addSource(email, emailChanged)
emailValid.addSource(emailConf, emailChanged)




To tie it to the UI, for example, the enabled property of a button or the visibility property of a label could be bound to the emailValid property appropriately.










share|improve this question
























  • You sound like you want to "combine" multiple LiveData just like I did here.

    – EpicPandaForce
    Mar 11 at 16:22











  • Thanks, but it seems like you are doing exactly what I am doing here only with a level of abstraction. My question really was if there is another way of doing it that I was not seeing.

    – RobertoCuba
    Mar 16 at 22:16











  • In that case, "not really, no".

    – EpicPandaForce
    Mar 16 at 23:08

















0















I am using two-way Databinding with LiveData inside a ViewModel to handle a sign-up form.



As fields are filled out, there are fields that need to be evaluated together for validity (as well as the overall form), and only enable the Submit button when everything is correct.



With a regular Observable object and using @Bindable this would be straightforward by just annotating a 'getter' function for each validation that is required and doing the necessary validation steps and return the appropriate result inside each function.



BUT I am working with LiveData. I came up with a solution using MediatoLiveData (see basic example below), but it seems to me like there should be another, perhaps better, approach.



class RegistrationViewModel : ViewModel() 
val email: MutableLiveData<String> by lazy MutableLiveData<String>()

val emailConf: MutableLiveData<String> by lazy MutableLiveData<String>()

val emailValid: MediatorLiveData<Boolean> = MediatorLiveData()

val emailChanged: (Any) -> Unit = cc@

//Obviously there is more validation needed but this is just an example
if (email.value != null && emailConf.value != null)

emailValid.value = email.value.isNotEmpty() && emailConf.value.isNotEmpty() && email.value == emailConf.value
return@cc


emailValid.value = false


init
emailValid.addSource(email, emailChanged)
emailValid.addSource(emailConf, emailChanged)




To tie it to the UI, for example, the enabled property of a button or the visibility property of a label could be bound to the emailValid property appropriately.










share|improve this question
























  • You sound like you want to "combine" multiple LiveData just like I did here.

    – EpicPandaForce
    Mar 11 at 16:22











  • Thanks, but it seems like you are doing exactly what I am doing here only with a level of abstraction. My question really was if there is another way of doing it that I was not seeing.

    – RobertoCuba
    Mar 16 at 22:16











  • In that case, "not really, no".

    – EpicPandaForce
    Mar 16 at 23:08













0












0








0








I am using two-way Databinding with LiveData inside a ViewModel to handle a sign-up form.



As fields are filled out, there are fields that need to be evaluated together for validity (as well as the overall form), and only enable the Submit button when everything is correct.



With a regular Observable object and using @Bindable this would be straightforward by just annotating a 'getter' function for each validation that is required and doing the necessary validation steps and return the appropriate result inside each function.



BUT I am working with LiveData. I came up with a solution using MediatoLiveData (see basic example below), but it seems to me like there should be another, perhaps better, approach.



class RegistrationViewModel : ViewModel() 
val email: MutableLiveData<String> by lazy MutableLiveData<String>()

val emailConf: MutableLiveData<String> by lazy MutableLiveData<String>()

val emailValid: MediatorLiveData<Boolean> = MediatorLiveData()

val emailChanged: (Any) -> Unit = cc@

//Obviously there is more validation needed but this is just an example
if (email.value != null && emailConf.value != null)

emailValid.value = email.value.isNotEmpty() && emailConf.value.isNotEmpty() && email.value == emailConf.value
return@cc


emailValid.value = false


init
emailValid.addSource(email, emailChanged)
emailValid.addSource(emailConf, emailChanged)




To tie it to the UI, for example, the enabled property of a button or the visibility property of a label could be bound to the emailValid property appropriately.










share|improve this question
















I am using two-way Databinding with LiveData inside a ViewModel to handle a sign-up form.



As fields are filled out, there are fields that need to be evaluated together for validity (as well as the overall form), and only enable the Submit button when everything is correct.



With a regular Observable object and using @Bindable this would be straightforward by just annotating a 'getter' function for each validation that is required and doing the necessary validation steps and return the appropriate result inside each function.



BUT I am working with LiveData. I came up with a solution using MediatoLiveData (see basic example below), but it seems to me like there should be another, perhaps better, approach.



class RegistrationViewModel : ViewModel() 
val email: MutableLiveData<String> by lazy MutableLiveData<String>()

val emailConf: MutableLiveData<String> by lazy MutableLiveData<String>()

val emailValid: MediatorLiveData<Boolean> = MediatorLiveData()

val emailChanged: (Any) -> Unit = cc@

//Obviously there is more validation needed but this is just an example
if (email.value != null && emailConf.value != null)

emailValid.value = email.value.isNotEmpty() && emailConf.value.isNotEmpty() && email.value == emailConf.value
return@cc


emailValid.value = false


init
emailValid.addSource(email, emailChanged)
emailValid.addSource(emailConf, emailChanged)




To tie it to the UI, for example, the enabled property of a button or the visibility property of a label could be bound to the emailValid property appropriately.







android-databinding android-architecture-components android-livedata






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Mar 16 at 22:19







RobertoCuba

















asked Mar 7 at 4:05









RobertoCubaRobertoCuba

389414




389414












  • You sound like you want to "combine" multiple LiveData just like I did here.

    – EpicPandaForce
    Mar 11 at 16:22











  • Thanks, but it seems like you are doing exactly what I am doing here only with a level of abstraction. My question really was if there is another way of doing it that I was not seeing.

    – RobertoCuba
    Mar 16 at 22:16











  • In that case, "not really, no".

    – EpicPandaForce
    Mar 16 at 23:08

















  • You sound like you want to "combine" multiple LiveData just like I did here.

    – EpicPandaForce
    Mar 11 at 16:22











  • Thanks, but it seems like you are doing exactly what I am doing here only with a level of abstraction. My question really was if there is another way of doing it that I was not seeing.

    – RobertoCuba
    Mar 16 at 22:16











  • In that case, "not really, no".

    – EpicPandaForce
    Mar 16 at 23:08
















You sound like you want to "combine" multiple LiveData just like I did here.

– EpicPandaForce
Mar 11 at 16:22





You sound like you want to "combine" multiple LiveData just like I did here.

– EpicPandaForce
Mar 11 at 16:22













Thanks, but it seems like you are doing exactly what I am doing here only with a level of abstraction. My question really was if there is another way of doing it that I was not seeing.

– RobertoCuba
Mar 16 at 22:16





Thanks, but it seems like you are doing exactly what I am doing here only with a level of abstraction. My question really was if there is another way of doing it that I was not seeing.

– RobertoCuba
Mar 16 at 22:16













In that case, "not really, no".

– EpicPandaForce
Mar 16 at 23:08





In that case, "not really, no".

– EpicPandaForce
Mar 16 at 23:08












1 Answer
1






active

oldest

votes


















1














Your approach is correct, but code has some design issues:




  • lazy fields is used in init section. Field become not lazy


  • emailValid field can be exposed as LiveData


  • validation can be encapsulated in inner class, but it's not required



    class RegistrationViewModel : ViewModel() 
    val email = MutableLiveData<String>()
    val emailConf = MutableLiveData<String>()

    @Suppress("UNCHECKED_CAST")
    val emailValid: LiveData<Boolean> = MediatorLiveData<Boolean>().apply
    val validator = Validator(::postValue)
    addSource(email, validator as Observer<String>)
    addSource(emailConf, validator as Observer<String>)


    private inner class Validator(private val validationConsumer: (Boolean) -> Unit) : Observer<Any>
    override fun onChanged(ignored: Any?)
    //Obviously there is more validation needed but this is just an example
    val email = email.value
    val emailConf = emailConf.value
    validationConsumer(when
    email.isNullOrEmpty() -> false
    emailConf.isNullOrEmpty() -> false
    email == emailConf -> true
    else -> false
    )





If you require some heavy validation, you can make hidden mutable field for emailValid and manually update it when background validation completed






share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55035886%2fandroid-databinding-with-livedata-validating-multiple-fields-together%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1














    Your approach is correct, but code has some design issues:




    • lazy fields is used in init section. Field become not lazy


    • emailValid field can be exposed as LiveData


    • validation can be encapsulated in inner class, but it's not required



      class RegistrationViewModel : ViewModel() 
      val email = MutableLiveData<String>()
      val emailConf = MutableLiveData<String>()

      @Suppress("UNCHECKED_CAST")
      val emailValid: LiveData<Boolean> = MediatorLiveData<Boolean>().apply
      val validator = Validator(::postValue)
      addSource(email, validator as Observer<String>)
      addSource(emailConf, validator as Observer<String>)


      private inner class Validator(private val validationConsumer: (Boolean) -> Unit) : Observer<Any>
      override fun onChanged(ignored: Any?)
      //Obviously there is more validation needed but this is just an example
      val email = email.value
      val emailConf = emailConf.value
      validationConsumer(when
      email.isNullOrEmpty() -> false
      emailConf.isNullOrEmpty() -> false
      email == emailConf -> true
      else -> false
      )





    If you require some heavy validation, you can make hidden mutable field for emailValid and manually update it when background validation completed






    share|improve this answer



























      1














      Your approach is correct, but code has some design issues:




      • lazy fields is used in init section. Field become not lazy


      • emailValid field can be exposed as LiveData


      • validation can be encapsulated in inner class, but it's not required



        class RegistrationViewModel : ViewModel() 
        val email = MutableLiveData<String>()
        val emailConf = MutableLiveData<String>()

        @Suppress("UNCHECKED_CAST")
        val emailValid: LiveData<Boolean> = MediatorLiveData<Boolean>().apply
        val validator = Validator(::postValue)
        addSource(email, validator as Observer<String>)
        addSource(emailConf, validator as Observer<String>)


        private inner class Validator(private val validationConsumer: (Boolean) -> Unit) : Observer<Any>
        override fun onChanged(ignored: Any?)
        //Obviously there is more validation needed but this is just an example
        val email = email.value
        val emailConf = emailConf.value
        validationConsumer(when
        email.isNullOrEmpty() -> false
        emailConf.isNullOrEmpty() -> false
        email == emailConf -> true
        else -> false
        )





      If you require some heavy validation, you can make hidden mutable field for emailValid and manually update it when background validation completed






      share|improve this answer

























        1












        1








        1







        Your approach is correct, but code has some design issues:




        • lazy fields is used in init section. Field become not lazy


        • emailValid field can be exposed as LiveData


        • validation can be encapsulated in inner class, but it's not required



          class RegistrationViewModel : ViewModel() 
          val email = MutableLiveData<String>()
          val emailConf = MutableLiveData<String>()

          @Suppress("UNCHECKED_CAST")
          val emailValid: LiveData<Boolean> = MediatorLiveData<Boolean>().apply
          val validator = Validator(::postValue)
          addSource(email, validator as Observer<String>)
          addSource(emailConf, validator as Observer<String>)


          private inner class Validator(private val validationConsumer: (Boolean) -> Unit) : Observer<Any>
          override fun onChanged(ignored: Any?)
          //Obviously there is more validation needed but this is just an example
          val email = email.value
          val emailConf = emailConf.value
          validationConsumer(when
          email.isNullOrEmpty() -> false
          emailConf.isNullOrEmpty() -> false
          email == emailConf -> true
          else -> false
          )





        If you require some heavy validation, you can make hidden mutable field for emailValid and manually update it when background validation completed






        share|improve this answer













        Your approach is correct, but code has some design issues:




        • lazy fields is used in init section. Field become not lazy


        • emailValid field can be exposed as LiveData


        • validation can be encapsulated in inner class, but it's not required



          class RegistrationViewModel : ViewModel() 
          val email = MutableLiveData<String>()
          val emailConf = MutableLiveData<String>()

          @Suppress("UNCHECKED_CAST")
          val emailValid: LiveData<Boolean> = MediatorLiveData<Boolean>().apply
          val validator = Validator(::postValue)
          addSource(email, validator as Observer<String>)
          addSource(emailConf, validator as Observer<String>)


          private inner class Validator(private val validationConsumer: (Boolean) -> Unit) : Observer<Any>
          override fun onChanged(ignored: Any?)
          //Obviously there is more validation needed but this is just an example
          val email = email.value
          val emailConf = emailConf.value
          validationConsumer(when
          email.isNullOrEmpty() -> false
          emailConf.isNullOrEmpty() -> false
          email == emailConf -> true
          else -> false
          )





        If you require some heavy validation, you can make hidden mutable field for emailValid and manually update it when background validation completed







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Mar 22 at 11:04









        XIII-thXIII-th

        3,30321839




        3,30321839





























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55035886%2fandroid-databinding-with-livedata-validating-multiple-fields-together%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Kamusi Yaliyomo Aina za kamusi | Muundo wa kamusi | Faida za kamusi | Dhima ya picha katika kamusi | Marejeo | Tazama pia | Viungo vya nje | UrambazajiKuhusu kamusiGo-SwahiliWiki-KamusiKamusi ya Kiswahili na Kiingerezakuihariri na kuongeza habari

            Swift 4 - func physicsWorld not invoked on collision? The Next CEO of Stack OverflowHow to call Objective-C code from Swift#ifdef replacement in the Swift language@selector() in Swift?#pragma mark in Swift?Swift for loop: for index, element in array?dispatch_after - GCD in Swift?Swift Beta performance: sorting arraysSplit a String into an array in Swift?The use of Swift 3 @objc inference in Swift 4 mode is deprecated?How to optimize UITableViewCell, because my UITableView lags

            Access current req object everywhere in Node.js ExpressWhy are global variables considered bad practice? (node.js)Using req & res across functionsHow do I get the path to the current script with Node.js?What is Node.js' Connect, Express and “middleware”?Node.js w/ express error handling in callbackHow to access the GET parameters after “?” in Express?Modify Node.js req object parametersAccess “app” variable inside of ExpressJS/ConnectJS middleware?Node.js Express app - request objectAngular Http Module considered middleware?Session variables in ExpressJSAdd properties to the req object in expressjs with Typescript