Navigate the store - view, search, and filter products.

Show list of all categories

In the ShopController, first inject an instance of CategoryService, then get all categories bu calling categoryService#findAll

grails-app/controllers/ShopController.groovy


def categoryService

def index() {
    [ categories: categoryService.findAll() ]
}

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.

grails-app/views/layouts/layout.gsp


<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
    <ul class="nav navbar-nav" id="category_menu">
        <li><a href="/products">All</a></li>
        <g:each in="${categories}" var="cat">
            <g:if test="${cat.name != 'Uncategorized'}">
                <li>
                    <g:link controller="shop" action="categories" params="[category_id: cat.id]">${cat?.title}</g:link>
                </li>
            </g:if>
        </g:each>
        <li><a href="#" id="show_search_box"><span class="glyphicon glyphicon-search"></span></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. for example in the details action method:

grails-app/controllers/ShopController.groovy


def categoryService
def brandService

def details() {
        [
                brands: brandService.findAll(),
                categories: categoryService.findAll(),
        ]
}

Then display it in the sidebar

grails-app/views/layouts/products_layout.gsp


<div class="product-listy">
    <h2>Browse By Brand</h2>
    <ul class="product-list">
        <g:each in="${brands}" var="brand">
            <li><g:link controller="shop" action="brands"
                        params="[brand_id: brand.id]" >${brand.title}</g:link></li>
        </g:each>
    </ul>
</div>

Browse products

Likewise, We can obtain and show a list of all products.

grails-app/controllers/ShopController.groovy


def products() {
    [
            products: productService.findAll(),
            brands: brandService.findAll(),
            categories: categoryService.findAll(),
            featured: collectionService.findByName("featured"),
            cart: shoppingCartService.get()
    ]
}

To show the products, iterate over the product collection

grails-app/views/shop/products.gsp


<ul>
    <g:each in="${products}" var="p">
        <li>
            <div>
                <a class="cbp-vm-image" href="/products/${p.id}">
                    <div class="simpleCart_shelfItem">
                        <div class="view view-first">
                            <div class="inner_content clearfix">
                                <div class="product_image">
                                    <img 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">${p.title}</p>
                                        </div>
                                        <div class="pricey">
                                            <span class="item_price">$ ${p.price}</span>
                                        </div>
                                        <div class="clearfix"></div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </a>

                <div class="cbp-vm-details">${p.shortDescription}</div>
                <a class="cbp-vm-icon cbp-vm-add item_add add_to_cart_button" data-product_id="${p.id}" href="#">Add to cart</a>
            </div>
        </li>
    </g:each>
</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.

grails-app/controllers/ShopController.groovy


def categories() {
    render view: "products", model:[
            products: productService.search(category: params.category_id),
            brands: brandService.findAll(),
            categories: categoryService.findAll(),
            featured: collectionService.findByName("featured"),
            cart: shoppingCartService.get()
    ]
}

Filter products by brand

Likewise, You can filter products by brand, just use the findAllByBrand instead.

grails-app/controllers/ShopController.groovy


def brands() {
    render view: "products", model: [
            products: productService.search(brand: params.brand_id),
            brands: brandService.findAll(),
            categories: categoryService.findAll(),
            featured: collectionService.findByName("featured"),
            cart: shoppingCartService.get()
    ]
}

Viewing product details

You can get single product by its ID, just use productService#findById, the code is straightforward:

grails-app/controllers/ShopController.groovy


def details() {
    [
            product: productService.findById(params.product_id),
            brands: brandService.findAll(),
            categories: categoryService.findAll(),
            featured: collectionService.findByName("featured"),
            cart: shoppingCartService.get()
    ]
}

grails-app/views/shop/details.gsp


<div class="new-product">
    <div class="col-md-5 zoom-grid">
        <div class="flexslider">
            <ul class="slides">
                <g:each in="${product.photos}" var="ph">
                    <li data-thumb="${ph.url}">
                        <div class="thumb-image">
                           <img src="${ph.url}" data-imagezoom="true" class="img-responsive" alt="" />
                        </div>
                    </li>
                </g:each>
            </ul>
        </div>
    </div>
    <div class="col-md-7 dress-info">
        <div class="dress-name">
            <h3>${product.title}</h3>
            <span>$ ${product.price}</span>
            <div class="clearfix"></div>
            <p>${product.description}</p>

        </div>

        <div class="purchase">
            <a class="cbp-vm-icon cbp-vm-add item_add add_to_cart_button"
               href="#" data-product_id="${product.id}">Add To Cart</a>

            <div class="clearfix"></div>
        </div>

    </div>
    <div class="clearfix"></div>


</div>

Getting Collections

For the sake of completeness, we demonstrate how to get and display Collections, Also this is a good opportunity to show you how you can use Collections in your own projects.

grails-app/controllers/ShopController.groovy


def collectionService

def index() {
    [
            collections: collectionService.findAll()
    ]
}

In the home-page of the store, we use Collections 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.

grails-app/views/shop/index.gsp


<g:each in="${collections}" var="coll">
    <div class="container collections">
        <h3 class="like text-center" >${coll.title}</h3>
        <ul id="${coll.name}" class="flexiselDemo3">
            <g:each in="${coll.products}" var="p">
                <li>
                    <g:link controller="shop" action="details" params="[product_id: p.id]">
                        <img src="${p.mainPhoto.url}" class="img-responsive" alt="" />
                    </g:link>
                    <div class="product liked-product simpleCart_shelfItem">
                        <g:link  controller="shop" action="details"
                                 params="[product_id: p.id]" class="like_name" >${p.title}</g:link>
                        <p><a class="item_add add_to_cart_button" href="#"
                              data-product_id="${p.id}"><i></i>
                              <span class=" item_price">$ ${p.price}</span></a></p>
                    </div>
                </li>
            </g:each>
        </ul>
    </div>
</g:each>

You can get single collection by name, use collectionService#findByName

grails-app/controllers/ShopController.groovy


def details() {
    [
            product: productService.findById(params.product_id),
            brands: brandService.findAll(),
            categories: categoryService.findAll(),
            featured: collectionService.findByName("featured"),
            cart: shoppingCartService.get()
    ]
}

We use this in the product details shop/single.html to show featured products.

grails-app/views/layouts/products_layout.gsp


<div class="container">
    <h3 class="like text-center">${featured.title}</h3>
    <ul id="flexiselDemo3">
        <g:each in="${featured.products}" var="p">
        <li>
            <g:link  controller="shop" action="details" params="[product_id: p.id]">
                <img src="${p.mainPhoto.url}" style="width: 220px;" class="img-responsive"/>
            </g:link>
            <div class="product liked-product simpleCart_shelfItem">
                <g:link  controller="shop" action="details"
                         params="[product_id: p.id]" class="like_name" >${p.title}</g:link>
                <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>
        </g:each>
    </ul>
</div>