Search code examples
javascriptarraysvue.jsjavascript-objects

How can I get access to the data entered by the user in these v-text-fields in VueJS?


I have an array called reducedGroups.
In response to Javas commetn below I have restructured this array so that it is now an Array of Objects, the number of Objects contained will always differ.

It may look something like this:

[ 
{ "0": { "value": "ccc" }, "1": { "value": "aaa" }, "2": { "value": "ddd" }, "3": { "value": "bbb" } }, 
{ "0": { "value": "eeee" } }, 
{ "0": { "value": "fff" } }, 
{ "0": { "value": "ggg" } } 
]

The code below arranges the internal arrays into groups and a Vuetify Text Field is shown above which allows the user to name each group.

<div v-for="(group, index) in reducedGroups" :key="index">
    <v-flex>
      <v-text-field label="Group Name" />
      <div
        v-for="item in group"
        :key="item.value"
      >{{ item.value}}</div>
      <div>
      <v-btn icon color="error" @click="removeGroup(index)">
        <v-icon>mdi-trash-can</v-icon>
      </v-btn>
      </div>
   </v-flex>
</div>

The output of this is shown below.

enter image description here

I have 2 questions:

1) How can I know when the user has given each group a name? - this will be used to trigger the trash cans to appear on screen

2) How can I then get access to the names of the groups that have been given by the user? - Once the user has removed the least relevant groups and just 3 remain, I want to print to screen the names of the remaining groups.

UPDATE: Restructured the data in response to Javas


Solution

  • I'm not sure your data structure is appropriate for the model, even after refactoring into objects. It seems like what you really have is an array of groups. And each group has (a) a name (initially empty), and (b) an array of values. If that's the case, a natural structure for your data would be something like

    [ 
      { name: "", values: ["ccc", "aaa", "ddd", "bbb"] }, 
      { name: "", values: ["eeee"] }, 
      { name: "", values: ["fff"] }, 
      { name: "", values: ["ggg"] } 
    ]
    

    With that structure, the template becomes more straightforward. (I don't know the details of <v-text-field /> but assuming it's the same as a standard <textarea />:

    <div v-for="(group, index) in reducedGroups" :key="index">
        <v-flex>
          <v-text-field label="Group Name" v-model="group.name"/>
          <div
            v-for="value in group.values"
            :key="value"
          >{{value}}</div>
          <div>
          <v-btn icon color="error" @click="removeGroup(index)">
            <v-icon>mdi-trash-can</v-icon>
          </v-btn>
          </div>
       </v-flex>
    </div>
    

    Edited to Add

    In response to the comments, use computed properties to extract the names and to check for any empty

    computed: {
        groupNames() {
            return reducedGroups.map(group => group.name);
        },
        allNamesPresent() {
            return reducedGroups.every(group => group.name);
        }
    }
    

    I might also suggest that working through a basic online Vue tutorial might be helpful to you.