Vue - Is there a way to scope $refs on a form












0















I am passing in props to my form. So the data in the form can be populated from these props or from user entry. Because I'm using props I don't have data defined for these elements. But instead am using v-model and passing in my props.



The problem then is when I want to submit, how can I get all the form data.



I realized I can define refs on the form inputs in order to grab the data from the form in order to submit it. But with that solution I have to step thru each data element individually. What I would like to do is just step thru the form and pull the data out in a forEach loop.



Is that possible?



Here is my code running.



And this is the top of my template (using Vuetify as a framework) with one of the elements of my form:



<template>
<v-container fluid grid-list-lg class="come_closer">
<v-layout row wrap>
<v-flex xs12 v-for="(creds, index) in amazonCredsArray" :key="creds.id" class="pb-4">
<v-card class="lightpurple">
<v-card-title>
<v-icon class="my_dark_purple_text">language</v-icon>
<h1 class="title oswald my_dark_purple_text pl-2 pr-5">ENTER YOUR CREDENTIALS BELOW</h1>
</v-card-title>

<v-form ref="form" lazy-validation>
<v-layout xs12 row wrap class="mx-auto" >
<v-flex xs12>
<v-text-field
ref="seller_id"
:rules="[ v => sellerIdRules(v, index) ]"
validate-on-blur
required
color="indigo"
label="Amazon Seller Id"
v-model="creds.seller_id"
prepend-icon="person"
></v-text-field>
</v-flex>


Then on submit I would have to run a method for each element that contains this:



this.$refs.seller_id.forEach(function(element){console.log(element.value)});


Is there an easier way to do this? Can I scope my refs so I can just use 1 forEach loop. Or any other suggestions?










share|improve this question



























    0















    I am passing in props to my form. So the data in the form can be populated from these props or from user entry. Because I'm using props I don't have data defined for these elements. But instead am using v-model and passing in my props.



    The problem then is when I want to submit, how can I get all the form data.



    I realized I can define refs on the form inputs in order to grab the data from the form in order to submit it. But with that solution I have to step thru each data element individually. What I would like to do is just step thru the form and pull the data out in a forEach loop.



    Is that possible?



    Here is my code running.



    And this is the top of my template (using Vuetify as a framework) with one of the elements of my form:



    <template>
    <v-container fluid grid-list-lg class="come_closer">
    <v-layout row wrap>
    <v-flex xs12 v-for="(creds, index) in amazonCredsArray" :key="creds.id" class="pb-4">
    <v-card class="lightpurple">
    <v-card-title>
    <v-icon class="my_dark_purple_text">language</v-icon>
    <h1 class="title oswald my_dark_purple_text pl-2 pr-5">ENTER YOUR CREDENTIALS BELOW</h1>
    </v-card-title>

    <v-form ref="form" lazy-validation>
    <v-layout xs12 row wrap class="mx-auto" >
    <v-flex xs12>
    <v-text-field
    ref="seller_id"
    :rules="[ v => sellerIdRules(v, index) ]"
    validate-on-blur
    required
    color="indigo"
    label="Amazon Seller Id"
    v-model="creds.seller_id"
    prepend-icon="person"
    ></v-text-field>
    </v-flex>


    Then on submit I would have to run a method for each element that contains this:



    this.$refs.seller_id.forEach(function(element){console.log(element.value)});


    Is there an easier way to do this? Can I scope my refs so I can just use 1 forEach loop. Or any other suggestions?










    share|improve this question

























      0












      0








      0








      I am passing in props to my form. So the data in the form can be populated from these props or from user entry. Because I'm using props I don't have data defined for these elements. But instead am using v-model and passing in my props.



      The problem then is when I want to submit, how can I get all the form data.



      I realized I can define refs on the form inputs in order to grab the data from the form in order to submit it. But with that solution I have to step thru each data element individually. What I would like to do is just step thru the form and pull the data out in a forEach loop.



      Is that possible?



      Here is my code running.



      And this is the top of my template (using Vuetify as a framework) with one of the elements of my form:



      <template>
      <v-container fluid grid-list-lg class="come_closer">
      <v-layout row wrap>
      <v-flex xs12 v-for="(creds, index) in amazonCredsArray" :key="creds.id" class="pb-4">
      <v-card class="lightpurple">
      <v-card-title>
      <v-icon class="my_dark_purple_text">language</v-icon>
      <h1 class="title oswald my_dark_purple_text pl-2 pr-5">ENTER YOUR CREDENTIALS BELOW</h1>
      </v-card-title>

      <v-form ref="form" lazy-validation>
      <v-layout xs12 row wrap class="mx-auto" >
      <v-flex xs12>
      <v-text-field
      ref="seller_id"
      :rules="[ v => sellerIdRules(v, index) ]"
      validate-on-blur
      required
      color="indigo"
      label="Amazon Seller Id"
      v-model="creds.seller_id"
      prepend-icon="person"
      ></v-text-field>
      </v-flex>


      Then on submit I would have to run a method for each element that contains this:



      this.$refs.seller_id.forEach(function(element){console.log(element.value)});


      Is there an easier way to do this? Can I scope my refs so I can just use 1 forEach loop. Or any other suggestions?










      share|improve this question














      I am passing in props to my form. So the data in the form can be populated from these props or from user entry. Because I'm using props I don't have data defined for these elements. But instead am using v-model and passing in my props.



      The problem then is when I want to submit, how can I get all the form data.



      I realized I can define refs on the form inputs in order to grab the data from the form in order to submit it. But with that solution I have to step thru each data element individually. What I would like to do is just step thru the form and pull the data out in a forEach loop.



      Is that possible?



      Here is my code running.



      And this is the top of my template (using Vuetify as a framework) with one of the elements of my form:



      <template>
      <v-container fluid grid-list-lg class="come_closer">
      <v-layout row wrap>
      <v-flex xs12 v-for="(creds, index) in amazonCredsArray" :key="creds.id" class="pb-4">
      <v-card class="lightpurple">
      <v-card-title>
      <v-icon class="my_dark_purple_text">language</v-icon>
      <h1 class="title oswald my_dark_purple_text pl-2 pr-5">ENTER YOUR CREDENTIALS BELOW</h1>
      </v-card-title>

      <v-form ref="form" lazy-validation>
      <v-layout xs12 row wrap class="mx-auto" >
      <v-flex xs12>
      <v-text-field
      ref="seller_id"
      :rules="[ v => sellerIdRules(v, index) ]"
      validate-on-blur
      required
      color="indigo"
      label="Amazon Seller Id"
      v-model="creds.seller_id"
      prepend-icon="person"
      ></v-text-field>
      </v-flex>


      Then on submit I would have to run a method for each element that contains this:



      this.$refs.seller_id.forEach(function(element){console.log(element.value)});


      Is there an easier way to do this? Can I scope my refs so I can just use 1 forEach loop. Or any other suggestions?







      javascript vue.js vuetify.js






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 20 '18 at 22:39









      ToddTToddT

      7151724




      7151724
























          1 Answer
          1






          active

          oldest

          votes


















          1














          There are several ways to solve this problem.



          The simplest is probably to create data properties that should hold the state of your input fields and initialize them with props.



          props: ['value'],

          data () {
          return {
          valueLocal: this.value
          }
          }


          Now, data properties can be used to reflect the value of your input fields again:



          <input v-model="valueLocal">


          Downside is, if the prop value changes after the component is mounted, those changes are ignored by your component.



          You can however, extend the component definition with watchers. This way valueLocal is always equal to whatever changed last. The prop or the user input.



          props: ['value'],

          data () {
          return {
          valueLocal: this.value
          }
          },

          watch: {
          value (newValue) {
          this.valueLocal = newValue
          }
          }


          Note, that v-model is basically just syntax sugar for binding the value attribute and listening for the input event. So v-model is just short for:



          <input :value="valueLocal" @input="valueLocal = $event.target.value">


          So you might as well keep your form component generic and let the parent component handle the state.



          Form component



          The template of your from component:



          <input :value="value" @input="$emit('input', $event.target.value)">
          <!-- ... --->
          <input type="submit" @submit="$emit('submit')">


          No data properties required, only props:



          props: ['value']


          Parent component



          In the parent component template:



          <form-component :value="value" @input="value = $event" @submit="...">


          Or use v-model again



          <form-component :v-model="value" @submit="...">


          Since you have multiple input elements in your from component this is less of an option though.






          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%2f53402662%2fvue-is-there-a-way-to-scope-refs-on-a-form%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














            There are several ways to solve this problem.



            The simplest is probably to create data properties that should hold the state of your input fields and initialize them with props.



            props: ['value'],

            data () {
            return {
            valueLocal: this.value
            }
            }


            Now, data properties can be used to reflect the value of your input fields again:



            <input v-model="valueLocal">


            Downside is, if the prop value changes after the component is mounted, those changes are ignored by your component.



            You can however, extend the component definition with watchers. This way valueLocal is always equal to whatever changed last. The prop or the user input.



            props: ['value'],

            data () {
            return {
            valueLocal: this.value
            }
            },

            watch: {
            value (newValue) {
            this.valueLocal = newValue
            }
            }


            Note, that v-model is basically just syntax sugar for binding the value attribute and listening for the input event. So v-model is just short for:



            <input :value="valueLocal" @input="valueLocal = $event.target.value">


            So you might as well keep your form component generic and let the parent component handle the state.



            Form component



            The template of your from component:



            <input :value="value" @input="$emit('input', $event.target.value)">
            <!-- ... --->
            <input type="submit" @submit="$emit('submit')">


            No data properties required, only props:



            props: ['value']


            Parent component



            In the parent component template:



            <form-component :value="value" @input="value = $event" @submit="...">


            Or use v-model again



            <form-component :v-model="value" @submit="...">


            Since you have multiple input elements in your from component this is less of an option though.






            share|improve this answer




























              1














              There are several ways to solve this problem.



              The simplest is probably to create data properties that should hold the state of your input fields and initialize them with props.



              props: ['value'],

              data () {
              return {
              valueLocal: this.value
              }
              }


              Now, data properties can be used to reflect the value of your input fields again:



              <input v-model="valueLocal">


              Downside is, if the prop value changes after the component is mounted, those changes are ignored by your component.



              You can however, extend the component definition with watchers. This way valueLocal is always equal to whatever changed last. The prop or the user input.



              props: ['value'],

              data () {
              return {
              valueLocal: this.value
              }
              },

              watch: {
              value (newValue) {
              this.valueLocal = newValue
              }
              }


              Note, that v-model is basically just syntax sugar for binding the value attribute and listening for the input event. So v-model is just short for:



              <input :value="valueLocal" @input="valueLocal = $event.target.value">


              So you might as well keep your form component generic and let the parent component handle the state.



              Form component



              The template of your from component:



              <input :value="value" @input="$emit('input', $event.target.value)">
              <!-- ... --->
              <input type="submit" @submit="$emit('submit')">


              No data properties required, only props:



              props: ['value']


              Parent component



              In the parent component template:



              <form-component :value="value" @input="value = $event" @submit="...">


              Or use v-model again



              <form-component :v-model="value" @submit="...">


              Since you have multiple input elements in your from component this is less of an option though.






              share|improve this answer


























                1












                1








                1







                There are several ways to solve this problem.



                The simplest is probably to create data properties that should hold the state of your input fields and initialize them with props.



                props: ['value'],

                data () {
                return {
                valueLocal: this.value
                }
                }


                Now, data properties can be used to reflect the value of your input fields again:



                <input v-model="valueLocal">


                Downside is, if the prop value changes after the component is mounted, those changes are ignored by your component.



                You can however, extend the component definition with watchers. This way valueLocal is always equal to whatever changed last. The prop or the user input.



                props: ['value'],

                data () {
                return {
                valueLocal: this.value
                }
                },

                watch: {
                value (newValue) {
                this.valueLocal = newValue
                }
                }


                Note, that v-model is basically just syntax sugar for binding the value attribute and listening for the input event. So v-model is just short for:



                <input :value="valueLocal" @input="valueLocal = $event.target.value">


                So you might as well keep your form component generic and let the parent component handle the state.



                Form component



                The template of your from component:



                <input :value="value" @input="$emit('input', $event.target.value)">
                <!-- ... --->
                <input type="submit" @submit="$emit('submit')">


                No data properties required, only props:



                props: ['value']


                Parent component



                In the parent component template:



                <form-component :value="value" @input="value = $event" @submit="...">


                Or use v-model again



                <form-component :v-model="value" @submit="...">


                Since you have multiple input elements in your from component this is less of an option though.






                share|improve this answer













                There are several ways to solve this problem.



                The simplest is probably to create data properties that should hold the state of your input fields and initialize them with props.



                props: ['value'],

                data () {
                return {
                valueLocal: this.value
                }
                }


                Now, data properties can be used to reflect the value of your input fields again:



                <input v-model="valueLocal">


                Downside is, if the prop value changes after the component is mounted, those changes are ignored by your component.



                You can however, extend the component definition with watchers. This way valueLocal is always equal to whatever changed last. The prop or the user input.



                props: ['value'],

                data () {
                return {
                valueLocal: this.value
                }
                },

                watch: {
                value (newValue) {
                this.valueLocal = newValue
                }
                }


                Note, that v-model is basically just syntax sugar for binding the value attribute and listening for the input event. So v-model is just short for:



                <input :value="valueLocal" @input="valueLocal = $event.target.value">


                So you might as well keep your form component generic and let the parent component handle the state.



                Form component



                The template of your from component:



                <input :value="value" @input="$emit('input', $event.target.value)">
                <!-- ... --->
                <input type="submit" @submit="$emit('submit')">


                No data properties required, only props:



                props: ['value']


                Parent component



                In the parent component template:



                <form-component :value="value" @input="value = $event" @submit="...">


                Or use v-model again



                <form-component :v-model="value" @submit="...">


                Since you have multiple input elements in your from component this is less of an option though.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Nov 21 '18 at 0:10









                NiklasNiklas

                483




                483






























                    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%2f53402662%2fvue-is-there-a-way-to-scope-refs-on-a-form%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

                    Paul Cézanne

                    UIScrollView CustomStickyHeader Resize height generates problems when scroll is too fast

                    Angular material date-picker (MatDatepicker) auto completes the date on focus out