0

I need help in iterating through arrays in Vue.

The data structure - coming from the database - is a list of vegetables, with each case identified according to its genus and common name and an ID that is specific for the genus.

[{"genus":"Allium","name":"Garlic","id":19},
{"genus":"Allium","name":"Leek","id":19},
{"genus":"Allium","name":"Onions","id":19},
{"genus":"Allium","name":"Shallot","id":19},
{"genus":"Allium","name":"Spring onions","id":19},
{"genus":"Brassica","name":"Broccoli","id":20},
{"genus":"Brassica","name":"Cabbage","id":20},
{"genus":"Brassica","name":"Cauliflower","id":20},
{"genus":"Brassica","name":"Kale","id":20},
{"genus":"Cucurbit","name":"Bittermelon","id":13},
{"genus":"Cucurbit","name":"Cucumber","id":13},
{"genus":"Cucurbit","name":"Pumpkin","id":13},
{"genus":"Cucurbit","name":"Rockmelon","id":13},
{"genus":"Cucurbit","name":"Squash","id":13},
{"genus":"Cucurbit","name":"Zucchini","id":13},
{"genus":"Legume","name":"Beans","id":8},
{"genus":"Legume","name":"Broad beans","id":8},
{"genus":"Legume","name":"Peas","id":8}]

I identify the unique genus values in the data (see "uniqueGenera" below) and then loop through all the vegetables that belong to that genus and show their name.

I have two problems.

First, once I've identified the unique genus names, I can't seem to access the ID associated with that genus (in "navigateTo(item.id))

<v-card
        v-for="(item,i) in uniqueGenera(genus)"
        :key="i"
        ripple
        @click="navigateTo(item.id)" class="hand"
    >
        <v-layout fill-height>
            <v-flex xs12 align-end flexbox>
                <p v-text="item"></p>
                <span
                    v-for="(card, index) in cards"
                    v-if = "card.genus === item"
                    >
                    {{card.name + ', '}}
                </span>
            </v-flex>
        </v-layout>
    </v-card>

Second, I want to display the vegetable names within each genus as a comma-separated list, but I don't know how to work out when we've reached the last item of the current array for any given genus in order to stop the comma being added to that last name.

I'm identifying the unique genera as follows:

uniqueGenera: function () {
  var vm = this;
  return function (keyname) {
    var output = [];
    var keys = [];

    vm.cards.forEach(function (card) {
      var key = card[keyname];

      if (keys.indexOf(key) === -1) {
        keys.push(key);
        output.push(card[keyname]);
      }
    });
    return output;
  };
},
3
  • Please create a bare-minimum working demo. You will get answers faster. Commented Mar 1, 2019 at 5:30
  • "I can't seem to access the ID" 👈 how are you verifying this issue? Commented Mar 1, 2019 at 5:37
  • Is your data (from the top of your question) stored in the cards data property? What's up with <p v-text="item"></p>? Isn't item an object? Commented Mar 1, 2019 at 5:45

1 Answer 1

1

Sounds like you could benefit from a computed property that maps your data to a more usable format. For example, to produce something like

{
  "19": {
    name: "Allium",
    vegetables: ["Garlic", "Leek", "Onions", "Shallot", "Spring onions"]
  },
  "20": {
    name: "Brassica",
    vegetables: [...]
  },
  ...
}

Something like

computed: {
  genera () {
    return this.cards.reduce((genera, item) => {
      if (!Object.prototype.hasOwnProperty.call(genera, item.id)) {
        genera[item.id] = { id: item.id, name: item.genus, vegetables: [] }
      }
      genera[item.id].vegetables.push(item.name)
      return genera
    }, Object.create(null))
  }
}

now you can more easily iterate your data. For example

<v-card v-for="(genus, id) in genera" :key="id" ripple class="hand"
        @click="navigateTo(id)">
  <v-layout fill-height>
    <v-flex xs12 align-end flexbox>
      <p>{{ genus.name }}</p>
      <span>{{ genus.vegetables.join(', ') }}</span>
    </v-flex>
  </v-layout>
</v-card>
Sign up to request clarification or add additional context in comments.

1 Comment

Wow! That's beautiful. Thanks. I didn't know such an approach existed. So much to learn. Cheers, Tom.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.