Free-Minded
Free-Minded

Reputation: 5420

Validation Error in Grails

I am completely new in Grails. I start learning from past couple of days. I am following this tutorial for creating a blog.

I have 3 domain Post, Comment and commentator. Where a Comment belongs to a Post, a Post has many Comments, a Comment has one Commentator and a Commentator belongs to a Comment. Look at my code ..

Domain Classes ---

Post Domain Class -

class Post {

static hasMany = [comments:Comment]

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

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)
}
}

Comment Domain Class -

class Comment implements Comparable {

 static belongsTo = Post

Post post
String comment
Commentator who = new Commentator()
Date dateCreated

public int compareTo(Object o) {
    return dateCreated.compareTo(o.dateCreated)
}

static constraints = {

}
}

Commentator Domain Class -

class Commentator {

static belongsTo = Comment

    String name
    String url
    String email
    Comment comment

    static constraints = {
    name(nullable:false, blank:false)
    url(nullable:true, blank:true, url:true)
    email(nullable:true, blank:true, email:true)        
}
}

Controller Classes --

PostController --

class PostController {

   def defaultAction = 'list'

   def edit = {
      def post = Post.get(params.id)
      if(!post) {
      post = new Post()
    } 
    render(view:'edit', model:[post:post])
   }

   def list = {
      render(
        view:'list',
        model:[posts:Post.list(
                sort:'lastUpdated',
                order:'desc')])
      }

      def save = {
     def post = loadPost(params.id)
     post.properties = params
     if(post.save()) {
    redirect(action:'list')
     } else {
     render(view:'edit', model:[post:post])
   }
     }

     private loadPost(id) {
 def post = new Post();
 if(id) {
    post = Post.get(id)
 }
 return post
    }

     def view = {
    render(view:'view', model:[post:Post.get(params.id)])
     }

     }

and CommentController Class --

class CommentController {

def edit = {
    render(view:'edit',
            model:[
                    comment:new Comment(),
                    postId:params.postId])
}

def save = {
    def comment = new Comment(params)
    comment.dateCreated = new Date();
    comment.post = Post.get(params.id)
    if(comment.save()) {
        redirect(
                controller:'post',
                action:'view',
                id:params.postId)
    } else {
        render(view:'edit',
                model:[comment:comment,
                        postId:params.postId])
    }
}
 }

View Part --

Post/view ---

<%@ page contentType="text/html;charset=UTF-8" %>
<html>
 <head>
  <title>${post.title}</title>
  <r:require modules="bootstrap"/>
<meta name="layout" content="main"/> 
 </head>
<body>
 <div class="well">
 <h1>${post.title}</h1>
 <p>${post.teaser}</p>
 <div>${post.content}</div>
 <g:link controller="comment" action="edit" id="${post.id}" class="btn btn-success">
    Add comment
 </g:link>
 <g:each in="${post.comments}" var="comment">
   <div class="comment">
   <p>${comment.comment}</p>
    <p>Made by: ${comment.who.name} on ${comment.dateCreated}</p>
    </div>
 </g:each>
</div>
</body>
</html>

When I click On Add Comment then Its called comment/edit.gsp which is here --

edit.gsp --

 <%@ page contentType="text/html;charset=UTF-8" %>
 <html>
 <head>
    <title>Create Comment</title>
  </head>
  <body>
   <h1>Create a comment</h1>
     <div id="validationerrors">
     <g:renderErrors bean="${comment}"/>
      </div>
     <g:form controller="comment" action="save">
     <g:hiddenField name="postId" value="${postId}"/>
     <dl>
      <dt>Your name:</dt>
      <dd>
      <g:textField name="who.name" value="${comment.who.name}"/>
      </dd>
      <dt>Your email:</dt>
      <dd>
      <g:textField name="who.email" value="${comment.who.email}"/>
      </dd>
      <dt>Your website/blog:</dt>
      <dd>
      <g:textField name="who.url" value="${comment.who.url}"/>
      </dd>
      <dt>Add your comment:</dt>
      <dd>
      <g:textArea name="comment" value="${comment.comment}" rows="20" cols="50"/>
      </dd>
     </dl>
     <g:submitButton name="submit" value="Save"/>
     </g:form>
     </body>
     </html>

When I click on Save Button then it showing validation Error

Property [post] of class [class groovypublish.Comment] cannot be null

The error is coming because postId is not getting by <g:hiddenField name="postId" value="${postId}"/>. Please help..

Upvotes: 0

Views: 829

Answers (1)

Saurabh Dixit
Saurabh Dixit

Reputation: 633

I think in your controller you are using params.postId, while from the view sending post.id in id parameter, so you should be getting post id in params.id instead of params.postId, I think if you change your edit function in the controller as:

  def edit = {
     if(params.id){
      render(view:'edit',
            model:[
                    comment:new Comment(),
                    postId:params.id])
    }else{
      render "No post Id available"
    }
  }

and also in your post controller you have calls:

render(view:'edit', model:[post:post])

now you are sending post object to view: edit, but in the edit gsp page you are using postId, I think you should choose any one of them, either send the object and use object.id in the edit.gsp, or if you are using postId then you should change your render as:

render(view:'edit', model:[postId:post.id])

and also change your save action to:

def save = {
    def comment = new Comment(params)
    comment.dateCreated = new Date();

Post postInstance = Post.get(params.postId)
if(postInstance){
comment.post = postInstance
    if(comment.save(failOnError:true)) {
        redirect(
                controller:'post',
                action:'view',
                id:params.postId)
    } else {
        render(view:'edit',
                model:[comment:comment,
                        postId:params.postId])
    }
}else{
render "No Post instance found" 
}
}

let me know if you still have any issue :)

Upvotes: 1

Related Questions