Show list of all categories
@Autowired
CategoryService categoryService;
@RequestMapping({"", "/"})
public String index(Model model){
model.addAttribute("categories", categoryService.findAll());
return "shop/index";
}
Now, the model contains a list all the categories in the camera store, this list encapsulated in Page
object.
Page
object is a container which wrap a collection of objects,
it implements Iterable
so you can iterate over its content using the standard for
loop, and can be easily used within thymeleaf view templates.
We will use this collection of Category
objects to populate the top navigation menu of the store.
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li th:each="cat : ${categories}"
th:unless="${#strings.equalsIgnoreCase(cat.name, 'uncategorized')}">
<a th:href="@{/categories/{cat_id}/products(cat_id=${cat.getId()})}"
th:text="${cat.title}">Home</a>
</li>
</ul>
</div>
Display list of all brands
Using the same technique, We can get a list of the available brands, and display them in the sidebar navigation.
@Autowired
BrandService brandService;
@RequestMapping({"", "/"})
public String index(Model model){
model.addAttribute("categories", categoryService.findAll());
model.addAttribute("brands", brandService.findAll());
return "shop/index";
}
Then display it in the sidebar
<div class="brand-list">
<h2>Browse By Brand</h2>
<ul class="product-list">
<li th:each="brand : ${brands}">
<a th:href="@{/brands/{id}/products(id=${brand.id})}"
th:text="${brand.title}">Canon</a>
</li>
</ul>
</div>
Browse products
Likewise, We can obtain and show a list of all products.
@RequestMapping("/products")
public String allProducts(Model model){
model.addAttribute("products", productService.findAll());
return "shop/products";
}
<ul>
<li th:each="p : ${products}">
<div>
<a class="cbp-vm-image" th:href="@{/products/{id}(id=${p.id})}" href="single.html">
<div class="simpleCart_shelfItem">
<div class="view view-first">
<div class="inner_content clearfix">
<div class="product_image">
<img th:src="${p.mainPhoto.url}" class="img-responsive" alt=""/>
<div class="mask">
<div class="info">Quick View</div>
</div>
<div class="product_container">
<div class="cart-left">
<p class="title" th:text="${p.title}">perspiciatis</p>
</div>
<div class="pricey">
<span class="item_price" th:text="${p.price}">$259.00</span>
</div>
<div class="clearfix"></div>
</div>
</div>
</div>
</div>
</div>
</a>
<div class="cbp-vm-details" th:text="${p.shortDescription}">
Silver beet shallot wakame tomatillo salsify mung bean beetroot groundnut.
</div>
<a class="cbp-vm-icon cbp-vm-add item_add add_to_cart_button"
th:attr="data-product_id=${p.id}" href="#">Add to cart</a>
</div>
</li>
</ul>
This may looks very boring and repetitive, but we want to make a point out of that: the Java SDK has a very consistent, once you learned a small subset you ‘ll find the rest of it very familiar and predectable.
Filter products by category
Now, Let’s see how to filter this list of products by category
there is search
method in the ProductService
, but because filtering products by category and brand are a frequently used operations,
there is a dedicated methods for these operations: findAllByCategory
and findAllByBrand
respectively.
All search methods return Page
object wrapping the result set, so it is possible to use the same view template to display the search results.
@RequestMapping("/categories/{cat_id}/products")
public String productsByCategory(@PathVariable("cat_id") String id, Model model){
Category category = categoryService.findById(id);
model.addAttribute("category", category);
model.addAttribute("products", productService.findAllByCategory(category));
return "shop/products";
}
Filter products by brand
Likewise, You can filter products by brand, just use the findAllByBrand
instead.
@RequestMapping("/brands/{brand_id}/products")
public String productsByBrand(@PathVariable("brand_id")String id, Model model){
Brand brand = brandService.findById(id);
model.addAttribute("breadcrumbName", brand.getTitle());
model.addAttribute("brand", brand);
model.addAttribute("products", productService.findAllByBrand(brand));
return "shop/products";
}
Viewing product details
You can get single product using its ID
, the code is straightforward:
@RequestMapping("/products/{id}")
public String product(@PathVariable("id")String id, Model model){
model.addAttribute("featured", collectionService.findByName("featured"));
model.addAttribute("product", productService.findById(id));
return "shop/single";
}
In shop/single.html
<div class="new-product">
<div class="col-md-5 zoom-grid">
<div class="flexslider">
<ul class="slides">
<li th:each="ph : ${product.photos}" th:attr="data-thumb=${ph.url}">
<div class="thumb-image">
<img th:src="${ph.url}" data-imagezoom="true" class="img-responsive" alt="" />
</div>
</li>
</ul>
</div>
</div>
<div class="col-md-7 dress-info">
<div class="dress-name">
<h3 th:text="${product.title}">Product title</h3>
<span>$</span><span th:text="${product.price}">$459.00</span>
<div class="clearfix"></div>
<p th:text="${product.description}">Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo</p>
</div>
<div class="purchase">
<a class="cbp-vm-icon cbp-vm-add item_add add_to_cart_button" href="#"
th:attr="data-product_id=${product.id}">Add To Cart</a>
<div class="clearfix"></div>
</div>
</div>
</div>
Getting Collections
For the sake of completeness, we demonstrate how to get and display Collection
s,
Also this is a good opportunity to show you how you can use Collection
s in your own projects.
@RequestMapping({"", "/"})
public String index(Model model){
model.addAttribute("collections", collectionService.findAll());
return "shop/index";
}
In the home-page of the store, we use Collection
s to show customers selected collections of our products.
We use collection for the available deals, another for the featured products, and one for the newly added products.
In shop/index.html
:
<div class="container collections" th:each="coll : ${collections}">
<h3 class="like text-center" th:text="${coll.title}">Featured Collection</h3>
<ul th:id="${coll.name}" class="flexiselDemo3">
<li th:each="p : ${coll.products}">
<a th:href="@{'/products/{id}'(id=${p.id})}" href="single.html">
<img src="/images/l1.jpg" th:src="${p.mainPhoto.url}" class="img-responsive" alt="" />
</a>
<div class="product liked-product simpleCart_shelfItem">
<a class="like_name" th:href="@{'/products/{id}'(id=${p.id})}" th:text="${p.title}" href="single.html">perfectly simple</a>
<p><a class="item_add add_to_cart_button" href="#" th:attr="data-product_id=${p.id}"><i></i> <span class=" item_price" th:text="${p.price}">$759</span></a></p>
</div>
</li>
</ul>
</div>
Of course you can get single collection by name
@RequestMapping("/products/{id}")
public String product(@PathVariable("id")String id, Model model){
model.addAttribute("featured", collectionService.findByName("featured"));
model.addAttribute("product", productService.findById(id));
return "shop/single";
}
We use this in the product details shop/single.html
to show featured products. See layouts/products_layout.html
<div class="container">
<h3 class="like text-center" th:text="${featured.title}">Featured Collection</h3>
<ul id="flexiselDemo3">
<li th:each="p : ${featured.products}">
<a href="single.html" th:href="@{/products/{id}(id=${p.id})}">
<img src="/images/l1.jpg" th:src="${p.mainPhoto.url}" class="img-responsive"/>
</a>
<div class="product liked-product simpleCart_shelfItem">
<a class="like_name" th:href="@{/products/{id}(id=${p.id})}"
th:text="${p.title}">Perfectly simple</a>
<p>
<a class="item_add add_to_cart_button" th:attr="data-product_id=${p.id}">
<span class=" item_price" th:text="${p.price}">$759</span>
</a>
</p>
</div>
</li>
</ul>
</div>