I have an API to get list of books, in each book I have author ID. I also want to get author name from that ID through another API (get author), so I use v-for to get items in list of book. Each item I call getAuthor(authorId) function but it repeats infinitely. Does anyone know what the reason is? My source code:
export default { name: 'GetBooks', data() { return { books: [], categories: [], author: [], }; }, created() { this.getBooks(); }, methods: { getBooks() { BookServices.getBooks().then(response => { this.books = response.data; console.log(response.data); }) .catch(e => { console.log(e); }); }, getAuthor(id) { BookServices.getAuthor(id).then(response => { this.author = response.data.name; console.log(response.data.name); }); return this.author; }, }
AND:
<tbody> <tr v-for="item in books" :key="item.id"> <td>{{ item.id }}</td> <td>{{ item.name }}</td> <td>{{ getAuthor(item.authorId) }}</td> <td>{{ item.price }}</td> <td>{{ item.year }}</td> <td><input class='myclass' type='button' value='Detail'/></td> </tr> </tbody>
Advertisement
Answer
The model-fetching methods should decide when and how to fetch authors, not the markup. (this is @IgorMoraru’s good second idea, corrected to properly handle the async fetch of authors).
This also fixes OP code error that assigned the book author to the view instance.
getBooks() { BookServices.getBooks().then(response => { this.books = response.data; console.log(response.data); this.getAuthors(); }) .catch(e => { console.log(e); }); }, getAuthors() { let promises = this.books.map(book => this.getAuthor(book)); return Promise.all(promises); }, getAuthor(book) { // note the change: pass the book here, not the id BookServices.getAuthor(book.id).then(response => { book.author = response.data.name; console.log(response.data.name); }); return this.author; },
Defend the markup for books that are (temporarily) missing authors…
<td>{{ item.id }}</td> <td>{{ item.name }}</td> <td v-if="item.author">{{ item.author }}</td> <td v-else>fetching...</td> <td>{{ item.price }}</td> <td>{{ item.year }}</td>