0

I am completely new in Grails, start learning grails from past couple of days. I am trying to add search feature by using searchable plugin in my demo grails application. I successfully added searchable plugins on user search where user can search other users and follow them. I am doing like this ..

grails install-plugin searchable

Domain Person.groovy --

package org.grails.twitter

  class Person {

transient springSecurityService

String realName
String username
String password
boolean enabled
boolean accountExpired
boolean accountLocked
boolean passwordExpired
static hasMany = [followed:Person, status:Status]
static searchable = [only: 'realName']

static constraints = {
    username blank: false, unique: true
    password blank: false
}

static mapping = {
    password column: '`password`'
}

Set<Authority> getAuthorities() {
    PersonAuthority.findAllByPerson(this).collect { it.authority } as Set
}

def beforeInsert() {
    encodePassword()
}

def beforeUpdate() {
    if (isDirty('password')) {
        encodePassword()
    }
}

protected void encodePassword() {
    password = springSecurityService.encodePassword(password)
}
   }

view/searchable/index.gsp ---

<html>
 <head>
  <meta name="layout" content="main" />
  <title>What Are You Doing?</title>
  <g:javascript library="jquery" plugin="jquery" />
  </head>
  <body>
<h1>Search For People To Follow</h1>
<div class="searchForm">
    <g:form controller="searchable">
        <g:textField name="q" value=""/>
    </g:form>
</div>

    <h1>What Are You Doing?</h1>
    <div class="updateStatusForm">
    <g:formRemote onSuccess="document.getElementById('messageArea').value='';" url="[action: 'updateStatus']" update="messageLists" name="updateStatusForm">
        <g:textArea name="message" value="" id="messageArea" /><br/>
        <g:submitButton name="Update Status" />
    </g:formRemote>
     </div>
    <div id="messageLists">
    <g:render template="messages" collection="${messages}" var="message"/>
</div>
   </body>
   </html>

It works fine. Now My problem starts. Now I want to add this searchable in my Post domain also where user can search post items. I am doing like this ...

Domain Post.groovy --

package groovypublish

class Post {

static hasMany = [comments:Comment]

String title
String teaser
String content
Date lastUpdated
Boolean published = false
SortedSet comments

static searchable = [only: 'title']

static constraints = {
    title(nullable:false, blank:false, length:1..50)
    teaser(length:0..100)
    content(nullable:false, blank:false)
    lastUpdated(nullable:true)
    published(nullable:false)
}
}

and here is form view

view/post/list.gsp --

  ------ some code -----
 <g:form controller="searchable" class="navbar-search pull-left">
   <g:textField name="q" value="" class="search-query" placeholder="Search Posts"/>
 </g:form>

 ------ some code ------

Now when I try to search post by post title then it showing error. It overrides searchable action. How to solve this problem ?

tim_yates
  • 167,322
  • 27
  • 342
  • 338
Free-Minded
  • 5,322
  • 6
  • 50
  • 93
  • Anyone can help me?? If you don't understand question then let me know. I will improve it... – Free-Minded Jul 08 '13 at 11:34
  • What is the error you are getting on search, as searchable looks fine in it, what is the code in your controller? – Saurabh Dixit Jul 08 '13 at 13:18
  • Ya Searchable is not showing any error. I works fine but only one search perform by both search textfield. As in my person domain, I am using searchable to search other user. Now Same searchable I am using for Post domain also and instead of showing post item it works as a people search that is not correct. How I can differentiate both searchable so that I can perform different action on different domain. – Free-Minded Jul 08 '13 at 17:49
  • And I am using same index.gsp page for both search to show the search result. As you can see in view/searchable/index.gsp. How to render post search result on different view.. – Free-Minded Jul 08 '13 at 17:50
  • see the answer below, you can have different-2 search functions in the controller, and render search views accordingly – Saurabh Dixit Jul 08 '13 at 18:29

2 Answers2

1

You can implement your own search method using searchable, call a controller function from your search form and perform search in that:

Let say you have two search forms:

<g:form controller="postsController" action="postAction" class="navbar-search pull-left">
   <g:textField name="q" value="" class="search-query" placeholder="Search Posts"/>
 </g:form>

and

 <g:form controller="searchable">
        <g:textField name="q" value=""/>
    </g:form>

then in the PostCOntroller you can have postAction method to perform search:

def postAction (Integer max) {
        params.max = Math.min(params.max ? params.int('max') : 10, 100)
        params.sort = "id"
        params.order = "desc"

        if(params?.q){


            def result = Post .search(params.q , order:"desc" )

            return [searchResults: result.results, searchResultsCount: result.total, popup : params.popup?.toBoolean()]
        }else{
            [searchResults: Post .list(params), searchResultsCount: Post .count(), popup : params.popup?.toBoolean()]
        }

and same you can have a different function for another search, if you use remote form then you need to have two different div's on the search page, and you can render the result page out there.

let say you have:

<g:formRemote name="postSearchForm" update="postSearchResultsDiv" url="[controller: 'post', action:'postAction' , params: [popup: false]]">
                        <label for="searchText">Search Post:</label>
                        <input name="q" type="text" id="searchText" class="input-medium search-query"/>
                        <input id="searchButton" type="submit" class="btn-info" value="Search"/>
                    </g:formRemote>

<div id="postSearchResultsDiv">--Your search result for the form will display here--</div>

This remote form will call postAction method in your controller, you can have postAction.gsp page on the controller's view folder and print the result out there.

and on your search page, postSearchResultsDiv will have the search result(postAction GSP page output)

Saurabh Dixit
  • 633
  • 4
  • 16
0

I solved my own problem... I have done like this ..

PostController ---

import org.compass.core.engine.SearchEngineQueryParseException
class PostController 
{
   def searchableService

   def searchpost = {
    if (!params.q?.trim()) {
        return [:]
    }
    try {
        return [searchResult: searchableService.search(params.q, params)]
    } catch (SearchEngineQueryParseException ex) {
        return [parseException: true]
    }
    render(view:'searchpost')
   }

  .......
}   

Search form ---

<g:form controller="post" action="searchpost" class="navbar-search pull-left">
   <g:textField name="q" value="" class="search-query" placeholder="Search Posts"/>
 </g:form>

searchpost.gsp //for showing result

<html>
   <head>
    <r:require modules="bootstrap"/>
    <meta name="layout" content="main"/>        
   </head>
   <body>
     <g:render template="/layouts/header" />    
     <div class="well"> 
        <g:each var="post" in="${searchResult?.results}">
          <div>
           <h2>${post.title}</h2>
           <p>${post.teaser}</p>
           <p>Last Updated: ${post.lastUpdated}</p>
           <g:link controller="post" action="view" id="${post.id}" class="btn btn-success">
         View this post
          </g:link>
          <g:if test="${post.author == currentLoggedInUser }">
         <g:link controller="post" action="edit" id="${post.id}" class="btn btn-danger">
             Edit this post
         </g:link>
         <g:actionSubmit action="delete" value="${message(code: 'default.button.delete.label', default: 'Delete')}" onclick="return confirm('${message(code: 'default.button.delete.confirm.message', default: 'Are you sure?')}');" class="btn btn-inverse" />
        </g:if>
        <g:form>
     <g:hiddenField name="id" value="${post?.id}" />            
        </g:form>
   </div>

   </g:each>
  </div>        
 </body>
 </html>

And it works :)

Free-Minded
  • 5,322
  • 6
  • 50
  • 93