theflucs
theflucs

Reputation: 227

V-for with nested objects in array

I have a v-for in a vue-bootstrap Card that I need to populate with the properties of an array of objects I am getting through api.

In the template:

<Card
   v-for="option in travelOptions"
   :key="option.id"
   :cardHeader="option.type | type"
   mode="Ford Mustang"
   :seats="option.trip_instance.remaining_capacity | seats"
   :date="option.trip_instance.departure_time | date"
   :time="option.trip_instance.departure_time | time"
   btnText="Select"
   @btnClicked="select()"
/>

The structure of the array of objects I am receiving is kind of like this:

[
  {
    "type": "CARPOOL",
    "trip_instance": {
      "id": 23456,
      "departure_time": "2020-01-01 00:00:00",
      "remaining_capacity": 3,
      "trip": 138949,
      "vehicle": {
        "id": 1,
        "vehicle_type": {
          "category": "PERSONAL_CAR",
          "display_name": "Car Sharing"
        },
        "plate_number": "1234567890",
        "display_name": "Subaru",
        "color": "red",
        "capacity": 4
      }
    },
    "trip": {
      "id": 138949,
      "headsign": "hospital",
      "short_name": "C01",
      "direction": "0"
    },
    "pickup_point": {
      "stop": {
        "id": 36583,
        "lat": 45.1551513671875,
        "lon": 8.43579959869385,
        "stop_id": "id56757",
        "name": "il nome della fermata di pickup"
      },
      "arrival_time": "06:12:00",
      "departure_time": "06:12:00"
    },
    "dropoff_point": {
      "stop": {
        "id": 36583,
        "lat": 45.1551513671875,
        "lon": 8.43579959869385,
        "stop_id": "id909090",
        "name": "name dropOfff"
      },
      "arrival_time": "06:12:00",
      "departure_time": "06:12:00"
    },
    "reservation_type": {
      "mode": "CARPOOL"
    }
  }
]

option.type is displaying fine (it’s on the ‘first layer’ of the object) option.trip_instance.departure_time, option.trip_instance.remaining_capacity are not, they’re nested inside the trip_instance object. And I will have to display few more properties of the other nested objects.

I dealt with nested objects when looping through arrays before (using v-for), and it worked fine, I could access the properties as I did in the template above. I thought the problem could be the lack of a unique id in the first layer of the object, so i created one and added to the objects of the array right before committing the action. The new objects now have this outer structure:

[
    {
      id: 0
      type: 'CARPOOL',
      trip_instance: obj,
      trip: obj,
      pickup_point: obj,
      dropoff_point: obj,
      reservation_type: obj
    },
    {
      id: 1
      type: 'RENTAL',
      trip_instance: obj,
      trip: obj,
      pickup_point: obj,
      dropoff_point: obj,
      reservation_type: obj
    }
]

It didn’t solve the issue. I read about creating nested v-for but it doesn't work for me. Also I am dealing with just one component (the Card), not with ul and nested li, as most of the examples I found offering this solution. I tried though, I created divs wrapping the card, one for each nested object. Something like

<div
  v-for="option in travelOptions"
  :key="option.id"
>
  <div
    v-for="(trip, index) in travelOptions.trip_instance"
    :key="index"
  >
    <div
      v-for="(vehicle, index) in travelOptions.vehicle"
      :key="index"
    >
      <Card
        :type="option.type"
        :time="trip.departure_time"
        :seats="trip.remaining_capacity"
      />
    </div>
  </div>
</div>

It doesn't work, the whole Card doesn't show on the screen, and from the editor (VS Code) I can see the v-for is not 'taking' the dot notation. I saw many questions regarding this issue but none helped me. Can somebody help? Thanks x

Upvotes: 0

Views: 627

Answers (2)

jcoleau
jcoleau

Reputation: 1200

Vue does not allow dynamically adding new root-level reactive properties to an already created instance. However, it’s possible to add reactive properties to a nested object using the Vue.set(object, propertyName, value) method:

Vue.set(vm.someObject, 'b', 2)
// interchangeably 
this.$set(vm.someObject, 'b', 2)

More information here

Upvotes: 3

theflucs
theflucs

Reputation: 227

My bad. I thought I read the data carefully, but in fact I didn't.

I would say there's no issue in displaying properties of nested objects with v-for, just it's crucial we know exactly what we're trying to display in every loop.

In my case I didn't notice that the object properties were not always the same (for example trip_instance wasn't a property of all the objects in the array, this was breaking the loop).

So, hoping to help someone, if you run into issues with v-for or iteration in general, make sure you know exactly the data structure you're working with. Hope I got it too, once for all.

Thanks @djiss for your time and trying to help.

Upvotes: 0

Related Questions