Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialTest Test
21,581 PointsHere are the answers for Implementing the Favorites Page and the Search Page
Hi! If you want to check how Favorite Page and Search Page can be implemented here's one way to do it:
Favorites Page:
1) Method in GifRepository:
You can use for-each loop or use a stream (for the latter you need Java version 1.8):
//for-each loop
public List<Gif> findByFavoriteMark() {
List<Gif> gifs = new ArrayList<>();
for(Gif gif : ALL_GIFS) {
if(gif.isFavorite()) {
gifs.add(gif);
}
}
return gifs;
}
//stream
public List<Gif> findByFavoriteMark() {
return ALL_GIFS
.stream()
.filter(Gif::isFavorite)
.collect(Collectors.toList());
}
2) Method in GifController (make sure you name List as below (so it can correspond with favorites.html, which was included in the project)). After that you can run your app.
@RequestMapping("/favorites")
public String listFavorites(ModelMap modelMap) {
List<Gif> gifs = gifRepository.findByFavoriteMark();
modelMap.put("gifs", gifs);
return "favorites";
}
II. Search Page
1) Method in GifRepository:
//for-each loop
public List<Gif> findBySearch(String search) {
List<Gif> gifs = new ArrayList<>();
for(Gif gif : ALL_GIFS) {
if(gif.getName().toLowerCase().contains(search)) {
gifs.add(gif);
}
}
return gifs;
}
//or stream
public List<Gif> findBySearch(String search) {
return ALL_GIFS
.stream()
.filter(e-> e.getName().toLowerCase().contains(search))
.collect(Collectors.toList());
}
2) Method in GifController
@RequestMapping(value="/", params="q")
public String listSearch(@RequestParam ("q") String q, ModelMap modelMap) {
List<Gif> gifs= gifRepository.findBySearch(q);
modelMap.put("gifs", gifs);
return "search";
}
3) Make sure to create html file (you can write it yourself or just copy "favorites.html" and rename it to "search.html":
Then if you type, for exampe, "and" in the search bar, you will see 3 gifs (android-explosion, ben-and-mike, infinite-andrew) PS: Hope it helps:)
8 Answers
Kirill Babkin
19,940 Points@muhammadammaraamir
In the form tag you can come up with any URI that you later will catch in your controller.
<form th:action="@{/search}" method="get">
<div class="input-field">
<input name="q" type="search" placeholder="Search all gifs..." required="required" autocomplete="off"/>
<i class="material-icons">search</i>
</div>
</form>
and in your controller you can request mapping to /search and i returned favorite.html just because you don't need to do anything in there to display list of gifs and as @Lukasz Wozniak stated you can return a home page -> "home.html" the idea is the same.
@RequestMapping("/search")
public String listSearch(@RequestParam String q, ModelMap modelMap){
List<Gif> allGifs = gifRepository.findIfContains(q);
modelMap.put("gifs", allGifs);
return "favorites";
}
and in you GifRepository you can create new method to find a set of gifs.
public List<Gif> findIfContains(String query){
List<Gif> gifs = new ArrayList<>();
for (Gif gif : ALL_GIFS){
if(gif.getName().toLowerCase().contains(query.trim().toLowerCase())){
gifs.add(gif);
}
}
return gifs;
}
and of course you can use stream if you wish so.
Thomas Salai
4,964 Points@Konstantin Kochetov Thanks for posting your solutions.
@Lukasz Wozniak, would you like to share us also your solutions ?
cheers
Julia Grill
21,690 PointsHi,
What Lukasz meant was that, when casting the gif name to all lower cases, one should also call search.toLowerCase(), in order to enable proper searching; to his second point, he made the right point, that one doesn't have to create a separate html file in order to make the search function work, instead, you can simply return "home" in list search, hope that clears things up!
Cheers
Bruno Aldo Lunardi
15,795 Pointsi tried a similar solution as provided above by Kiril but i'm getting an error, page not found
@RequestMapping("/search")
public String findBySearch(@PathVariable String q, ModelMap modelMap) {
List<Gif> gifs = repository.findByName(q);
modelMap.put("gif",gifs);
return "favorites";
}
i'm getting this: http://localhost:8080/@%7B/search%7D?q=compiler-robot
Bear in mind that i changed the <form> to <form action="@{search}" located in my home.html
Agung Insani Alam
15,131 PointsI think you should change "gif" to "gifs" in your modelMap and add "th:" before "action" in your form tag.
Boban Talevski
24,793 PointsIs there a specific reason we need to add "th:" before action in the search form tag? The way I see this, is that we should use "th:" if there's anything dynamic that we need to put there.
But I don't think we need to, since we'll be using a fixed URI for the search request, like simply "/search" for example. I mean I didn't even think of adding "th:" before action and everything works as expected. Or am I missing something?
Lukasz Wozniak
7,383 PointsYes, that's exactly what i meant :)
Thomas Salai
4,964 PointsThanks you very much to you all for your explanations.
muhammadammaraamir
8,392 PointsWhat are you supposed to write in the action attribute of the form? How will our a URI with the format /search?q=compiler be generated?
Nelson Fleig
25,764 PointsGood work every one. Would have been nice to learn how to do "includes" a-la-PHP to avoid copying and repasting the navigation and footer on every html page. I'm so spoiled by these awesome Team Treehouse videos xD
Did anyone figure out how to make the search appear on the current page? Could you please post your code?
Varun Upadhyay
2,007 PointsI coded a new search controller and added the logic mentioned above of searching the query by iterating the GifRepository and storing them in a new list and sending the list in the model map. I created a new html page (search.html) . I am getting an error of
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title><!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<link rel="icon" th:href="@{/favicon.png}" />
<link rel="stylesheet" th:href="@{/vendor/materialize/css/materialize.css}" />
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
<link rel="stylesheet" th:href="@{/app.css}" />
<title>giflib | Favorites</title>
</head>
<body>
<div class="navbar-fixed">
<nav>
<div class="container">
<a th:href="@{/}" class="brand-logo">gif<span>.</span>lib</a>
<a href="#" data-activates="mobile-nav" class="button-collapse right"><i class="material-icons">menu</i></a>
<ul class="right hide-on-med-and-down">
<li><a th:href="@{/}">Explore</a></li>
<li><a th:href="@{/categories}">Categories</a></li>
<li class="active"><a th:href="@{/favorites}">Favorites</a></li>
</ul>
<ul id="mobile-nav" class="side-nav">
<li><a th:href="@{/}">Explore</a></li>
<li><a th:href="@{/categories}">Categories</a></li>
<li class="active"><a th:href="@{/favorites}">Favorites</a></li>
</ul>
</div>
</nav>
</div>
<div class="gifs container">
<div class="row">
<div th:each="gif : ${matchedGifs}" class="col s12 l4">
<a th:href="@{'/gif/' + ${gif.name}}">
<img th:src="@{'/gifs/' + ${gif.name} + '.gif'}" />
<a href="#" th:class="(${gif.favorite} ? 'un' : '') + 'mark favorite'"></a>
</a>
</div>
</div>
</div>
<script th:src="@{/vendor/jquery/jquery-1.11.3.js}"></script>
<script th:src="@{/vendor/materialize/js/materialize.js}"></script>
<script th:src="@{/app.js}"></script>
</body>
</html></title>
</head>
<body>
</body>
</html>
Error: This application has no explicit mapping for /error, so you are seeing this as a fallback.
Boban Talevski
24,793 PointsI think it's best to create a new post/question for this and provide some more code.
For example, are you sure you are reaching this search.html page at all? What's the action on your form tag? What's your implementation of the method in GifControler for handling a search request? What's your implementation of the search method in GifRepository?
Lukasz Wozniak
7,383 PointsLukasz Wozniak
7,383 PointsYou don't have to make specific template for search result page. Use "home.html"
You should also make search parameter in findBySearch method to lowercase.