6

I'm struggling coming up with a solution to what seems to be a basic problem.

I have a template that uses a v-for loop to create some content, inside this content I need to run a function to check to see if the contentID matches an ID from a separate list. If it matches I need to take that data and show it in my loop . Currently the only way to get that data is to run the function that checks multiple times, i.e

methods: {
findClientName (clientId) {
  for (let name of this.clientList) {
    if (name.id == clientId) {
      return {
        name
      }
    }
  }
}

<v-card-text>
    {{ findClientName(item.client_id).name.f_name }}
    {{ findClientName(item.client_id).name.l_name }}
</v-card-text>

That seems like a pretty ineffective way of doing it because I need to call the method on every part of the data I want, isn't there a way to just assign it to a local variable inside the template, like..

{ clientData = findClientName(item.client_id) }
{{ clientData.f_name }}
{{ clientData.l_name }}

What am I missing or not thinking of?

2
  • 1
    could you provide the code that contains v-for loop? Commented Dec 10, 2018 at 23:08
  • 1
    The simplest way would be to encapsulate the markup inside v-card-text in a new component. Then you can use a computed propery or method to get the client name and use it as many times as you need it. Commented Dec 11, 2018 at 1:46

4 Answers 4

3

It's recommended to use a computed property in this case, and loop through that property via v-for, i provided an example to simulate your case :

new Vue({
  el: '#app',
  data: {
    a: ["aaa", "bbb", "ccc", "ddd", "eee", "fff"],
    b: ["bbb", "sss", "ccc", "eee"]
  },
  computed: {
    isInA() {
      return this.b.filter((item) => {
        return this.a.includes(item)
      })
    }
  }

})
<!DOCTYPE html>
<html>

<head>
  <meta name="description" content="Vue.delete">
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.1/vue.min.js"></script>
</head>

<body>
  <div id="app">
    <div v-for="item in isInA">
      {{item}}
    </div>
  </div>

If your arrays contain objects like in your case, you need something like :

computed:
 cpt_clients(){
return this.clientList.filter((cl)=>{
                          return this.otherList.findIndex(item=>{return item.id==cl.id;})!==-1;
                        });
         }
       }

and in your template do :

  <v-card-text v-for="cl in cpt_clients" >
       {{cl.name}}
        {{cl.id}}
   </v-card-text>
Sign up to request clarification or add additional context in comments.

Comments

1

You're going to have to do some sort of lookup if the data you need is in another list. Is it possible to normalize the client list before hand and use that in the template loop? Something along the lines of:

data () {
  return {
    mapped: [],
    clientList: [...]
  }
},
mounted () {
  this.mapped = this.clientList.map(({ id, f_name, l_name }) => {
    return { [id]: { f_name, l_name } }
  })
}

Then your template would be:

<template>
 ...
    <v-card-text v-if="mapped.hasOwnProperty(item.client_id)">
      {{ mapped[item.client_id].f_name }}
      {{ mapped[item.client_id].l_name }}
    </v-card-text>
 ...
</template>

Comments

1

This is the best workaround I found for this lacking of local variables, that is by wrapping the value as mono-element array, since VUE natively supports array iteration:

<template v-for="local_variable in [object.longComputationValueProducer().evenMoreCPUWork()]">
    <!-- body guaranteed to be executed exactly 1-->
    <div>{{ local_variable.read }}</div>
    <div>{{ local_variable.read_without_recompute }}</div>
    <div>{{ local_variable.read_again_without_recompute }}</div>
</template>

1 Comment

I like this approach. It doesn't fit with the Vue paradigm perfectly, but is legal in Vue. For example, in my code I use Array.map to add computed values to an object, and then destructure it for use: <div v-for="({year, monthlySavings}, index) in year_array_partition.map(year => ({ year, monthlySavings: refinanceByYearMonthlySavings(year) }))" :key="index">
0

I think computed is better than method because it is depend your localId

computed: {
   getClientsById (clientId) {
     return this.currentClientList.filter((ccl) => { return this.currentClientList.id === localId });
   }
} 


<v-card-text v-for="item in getClientById">
    {{ item.name }}
</v-card-text>


// Second way without methods and computed

<v-card-text v-for="item in currentClientList" v-if=item.id === localId>
    {{ item.name }}
</v-card-text>

Comments

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.