1

I'm working in a routes project in Vue2. I won't explain the details to make this question as simple as possible.

I'm using a v-for to iterate through an array.

Each iterated object needs to be added to an array which I'm going to send to another component in my template.

It's a complex JSON. I'm on a leaflet map.

I need to join each point's coordinate with a polyline. The <l-polyline> component is expecting an array of coordinates (each coordinate is an array of 2 values).

So, my take is to put each object.coordinate into an array as I iterate over the first list. Then that array is going to be passed as a parameter to the polyline component in the template. How do I do that?

<div :key="i" v-for="(route, i) in jsonResult.routesList">
    <div :key="j" v-for="(stop, j) in route.stopsList">
        <l-marker :lat-lng="latLng(stop.lat, stop.long)" />
        // the problem is here because I'm only getting one object (stop) and I need the whole list of stops to get their coordinates
        <l-polyline :lat-lngs="latLng(stop.lat, stop.long)"></l-polyline>
    </div>
</div>

My JSON looks more or less like this:

The <l-polyline> object expects an array like this to draw the lines:

    [
      [20.567934, -103.366844],
      [19.54006, -99.1879349],
      [25.54193, -100.947906],
      [25.7970467, -100.59623]
    ] 

The routes list (jsonResult.routesList in the code)

"routesList": [
    {
      "stopsList": [
        {
          "id": 1,
          "seq": 1,
          "start": "2019-09-10T09:32:23",
          "end": "2019-09-10T10:17:23",
          "lat": 20.567934,
          "long": -103.366844,
        },
        {
          "id": 2,
          "seq": 2,
          "start": "2019-09-10T09:32:23",
          "end": "2019-09-10T10:17:23",
          "lat": 20.587934,
          "long": -104.386844,
        }
      ],

    },
    //another route
    {
      "stopsList": [
        {
          "id": 1,
          "seq": 1,
          "start": "2019-09-10T09:32:23",
          "end": "2019-09-10T10:17:23",
          "lat": 20.567934,
          "long": -103.366844,
        },
        {
          "id": 2,
          "seq": 2,
          "start": "2019-09-10T09:32:23",
          "end": "2019-09-10T10:17:23",
          "lat": 20.587934,
          "long": -104.386844,
        }
      ],
    },
4
  • Well, I'm not sure if I understood the question, but bear in mind that you still have the route.stopsList available even in the loop. Which (based on your question) is the array you need, right? Commented Jan 6, 2020 at 10:37
  • Yes , but the stops list is super big. That was a simplified version. I need to obtain latitude and longitude from each stop and pass it to the component . I mean, I need to send an array of arrays of all latitudes and longitudes. Commented Jan 6, 2020 at 10:41
  • stopsList is actually an array of objects Commented Jan 6, 2020 at 10:44
  • This is something a computed property is for. You don't do it in template. Please, provide a better example of stopsList and I think I will be able to help you. Commented Jan 6, 2020 at 10:45

2 Answers 2

3

I think the problem is in the way that your using your <div>, when you say:

<div :key="j" v-for="(stop, j) in route.stopsList">
        <l-marker :lat-lng="latLng(stop.lat, stop.long)" />
        // the problem is here because I'm only getting one object (stop) and I need the whole list of stops to get their coordinates
        <l-polyline :lat-lngs="latLng(stop.lat, stop.long)"></l-polyline>
</div>

In the v-for you were passing each individual element from the stopList to the <l-polyline> component. I think the correct approach would be to pass the whole stopList to the component, and then format it accordingly (iterating over the stopList array is done inside the <l-polylist> component.

<div :key="i" v-for="(route, i) in jsonResult.routesList">
      <div :key="j" v-for="(stop, j) in route.stopsList">
        <l-marker :lat-lng="latLng(stop.lat, stop.long)" />


      <l-polyline :lat-lngs="route.stopsList.map(x=>[x.lat,x.long])"></l-polyline>
</div>
</div>

Of course this is not an optimal approach, but it will solve your problem, a better way would be using something based on the idea of Dawid Zbiński and use a computed property. I hope this helps

Sign up to request clarification or add additional context in comments.

Comments

2

You should use a method in order to compute the array of coordinates you want to pass to the other component.

// Vue component file
methods: {

  /*
   * Converts the stopsList array to an array of coordinates.
   * Example of returned value:
   *   [
   *     [ 23.1234, 21.2322 ],
   *     [ 21.1242, 24.2333 ],
   *   ]
   */
  getStopsCoordinates(stops) {
    return stops.map(stop => [ stop.lat, stop.long ]);
  }
}

You can then use the getStopsCoordinates method when you're passing the stops coordinates of all stops, like so:

<div :key="i" v-for="(route, i) in jsonResult.routesList">
    <div :key="j" v-for="(stop, j) in route.stopsList">
        <l-marker :lat-lng="latLng(stop.lat, stop.long)" />
        // the problem is here because I'm only getting one object (stop) and I need the whole list of stops to get their coordinates
        <l-polyline :lat-lngs="getStopsCoordinates(route.stopsList)"></l-polyline>
    </div>
</div>

Although it should work, it's not an optimal solution, as the list is converted each time in the second v-for and it's probably not needed. There's multiple ways on how this can be optimised, but without the measurements etc. I'd probably go with a getter for routesList.

// Vue component file
getters: {

  /* Returns routesList where each route has property stopsCoordinates */
  routesListWithStopsCoordinates() {
    return this.jsonResult.routesList.map(route => {
      route.stopsCoordinates = this.getStopsCoordinates(route.stopsList);
      return route;
    })
  }
},

methods: {

  /* Already explained above */
  getStopsCoordinates(stops) {
    return stops.map(stop => [ stop.lat, stop.long ]);
  }
}

Then in your template you can do something like this:

<div :key="i" v-for="(route, i) in jsonResult.routesList">
    <div :key="j" v-for="(stop, j) in route.stopsList">
        <l-marker :lat-lng="latLng(stop.lat, stop.long)" />
        // the problem is here because I'm only getting one object (stop) and I need the whole list of stops to get their coordinates
        <l-polyline :lat-lngs="route.stopsCoordinates"></l-polyline>
    </div>
</div>

Hope it works.

3 Comments

David, it didn't work. Although I see what you want to do. That was smart. But it doesn't show anything. Even when I debug to see the output, the output is nothing. And actually I get a weird error that my polyline component is undefined, which doesn't appear if I use a satic array, for example. I didn't answer before because I needed to rest. It was 8:30am in my country and I needed to sleep. I was coding for like 10 hours without resting ;)
@manuel.menendez I just realised I had used Array.reduce instead of Array.map and this is probably why it didn't work for you. I updated the code, so If I were you I'd give a second approach another chance now, it can optimise your code significantly.
Your code is great, David. It works too. I appreciate you taking the time to answer

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.