Reputation: 76
i'm fairly new in vue.js and i'm trying to do an app where you can find books but i'm stuck at the moment to reuse components.
When i open the app, the bookList component is used to show the most viewed books.
What i want to do is:
Search books from the input field and fill the bookList component with the response and then render it in the same view.
Here is my code. Any suggestion are welcome
<div id="app">
<nav id="menu">
<input type="text" v-model="newSearch" />
</nav>
<main id="panel">
<header>
<button class="toggle-button">☰</button>
<!-- <books :books="books" :url="url"></books> -->
<router-view></router-view>
</header>
</main>
</div> <!-- end app -->
<template id="book-list-template">
<ul>
<li v-for="book in books">
<div class="content">
<a v-link="{ name: 'book', params: { bookId: book.ID } }">
<img :src="book.thumbnail" class="center-block">
<p>{{book.title}}</p>
</a>
</div>
</li>
</ul>
</template>
<template id="single-book-template">
<div class="content" v-for="book in book">
<img :src="book.cover" class="center-block prueba">
<p>{{book.title}}</p>
</div>
</template>
url = 'api_url'
//defining some components
var bookList = Vue.extend({
template: '#book-list-template',
data: function() {
return {
books: [],
}
},
ready: function() {
this.getBooks();
},
methods: {
getBooks: function() {
this.$http.jsonp(url+'criteria=most_viewed').then(function(response) {
this.$set('books', response.data);
}, function(response) {
alert(response.status);
});
}
}
});
var singleBook = Vue.extend({
template: '#single-book-template',
data: function() {
return {
book: ''
}
},
ready: function() {
this.getBookById();
},
methods: {
getBookById: function() {
this.$http.jsonp(url+'id='+this.$route.params.bookId).then(function(response) {
this.$set('book', response.data);
}, function(response) {
alert(response.status);
});
}
}
});
//creating a vue instance
new Vue({
el: '#app',
data: {
newSearch: ''
}
}) //end vue
var App = Vue.extend({})
var router = new VueRouter()
router.map({
'/': {
component: bookList
},
'book/:bookId': {
name: 'book',
component: singleBook
}
})
router.start(App, '#app')
Upvotes: 1
Views: 2422
Reputation: 25231
You've got a book list
template that handles the searching and filtering of the book list, and then a book
template that handles displaying an individual book. So it might look something like this:
<template id="book-list-template">
<input type="text" v-model="searchText">
<ul>
<li v-for="book in books | filterBy searchText">
<single-book :book="book"></single-book>
</li>
</ul>
</template>
<template id="single-book-template">
<div class="content">
<img :src="book.cover" class="center-block prueba">
<p>{{book.title}}</p>
</div>
</template>
So the list template just generates a bunch of single-book templates. The list handles the loading and filtering of the books (using a search bar or otherwise) and the book template handles any function of each individual book (ie. "add to my reading list" or an "order book" button. In your single book template, you'd need to add a prop
of book (instead of having that as a data
property) so it can accept a book from your list template.
var singleBook = Vue.extend({
template: '#single-book-template',
props: ['book']
}
});
var bookList = Vue.extend({
template: '#book-list-template',
data: function() {
return {
books: [],
searchText:""
}
},
ready: function() {
this.getBooks();
},
methods: {
getBooks: function() {
this.$http.jsonp(url+'criteria=most_viewed').then(function(response) {
this.$set('books', response.data);
}, function(response) {
alert(response.status);
});
}
},
components:{
"single-book":singleBook
}
});
Lastly, add an input to your book-list component that allows users to search for a book. You can model that to data called searchText
. Then you can use Vue's filterBy on your v-for="book in books | filterBy searchText"
Upvotes: 2
Reputation: 32941
You may be looking for the keep-alive
directive. If you Ctrl + F
and search "keep-alive" here you'll find it: http://vuejs.org/guide/components.html
Upvotes: -1