Grails Parent Child Form not saving child data -


i trying create parent child form author , book domain classes. view works fine , lets me enter books when creating new author. however, when add new author , books , check database (dbconsole), see new record in author table no records added book table. can please let me know missing or doing wrong here?

here domain classes:

author:

package bookauthor1tomany  import org.apache.common.collections.list.* import org.apache.commons.collections.listutils.*  class author {      static constraints = {     }      string name     string category      list<book> books = new arraylist<>()     static hasmany = [ books:book ]      static mapping = {         books cascade:"all-delete-orphan"     }      def getexpandablebooklist() {         return lazylist.decorate(books, factoryutils.instantiatefactory(book.class))     }      string tostring(){         return "${name}" - "${category}"     }  } 

book

package bookauthor1tomany  class book {      static constraints = {     }      string title     boolean _deleted      static transients = [ '_deleted' ]      static belongsto = [ author:author ]      def string tostring() {         return title     }  } 

authorcontroller

i haven't changed controller. default generated save method author controller.

@transactional def save(author authorinstance) {     if (authorinstance == null) {         notfound()         return     }      if (authorinstance.haserrors()) {         respond authorinstance.errors, view:'create'         return     }      authorinstance.save flush:true      request.withformat {         form multipartform {             flash.message = message(code: 'default.created.message', args: [message(code: 'author.label', default: 'author'), authorinstance.id])             redirect authorinstance         }         '*' { respond authorinstance, [status: created] }     } } 

gsps

create.gsp

<!doctype html> <html>     <head>         <meta name="layout" content="main">         <g:set var="entityname" value="${message(code: 'author.label', default: 'author')}" />         <title><g:message code="default.create.label" args="[entityname]" /></title>     </head>     <body>         <a href="#create-author" class="skip" tabindex="-1"><g:message code="default.link.skip.label" default="skip content&hellip;"/></a>         <div class="nav" role="navigation">             <ul>                 <li><a class="home" href="${createlink(uri: '/')}"><g:message code="default.home.label"/></a></li>                 <li><g:link class="list" action="index"><g:message code="default.list.label" args="[entityname]" /></g:link></li>             </ul>         </div>         <div id="create-author" class="content scaffold-create" role="main">             <h1><g:message code="default.create.label" args="[entityname]" /></h1>             <g:if test="${flash.message}">             <div class="message" role="status">${flash.message}</div>             </g:if>             <g:haserrors bean="${authorinstance}">             <ul class="errors" role="alert">                 <g:eacherror bean="${authorinstance}" var="error">                 <li <g:if test="${error in org.springframework.validation.fielderror}">data-field-id="${error.field}"</g:if>><g:message error="${error}"/></li>                 </g:eacherror>             </ul>             </g:haserrors>             <g:form url="[resource:authorinstance, action:'save']" >                 <fieldset class="form">                     <g:render template="authortemp"/>                 </fieldset>                 <fieldset class="buttons">                     <g:submitbutton name="create" class="save" value="${message(code: 'default.button.create.label', default: 'create')}" />                 </fieldset>             </g:form>         </div>     </body> </html> 

_form.gsp

<%@ page import="bookauthor1tomany" %>    <div class="fieldcontain ${haserrors(bean: authorinstance, field: 'books', 'error')} ">     <label for="books">         <g:message code="author.books.label" default="books" />      </label>  <ul class="one-to-many"> <g:each in="${authorinstance?.books?}" var="b">     <li><g:link controller="book" action="show" id="${b.id}">${b?.encodeashtml()}</g:link></li> </g:each> <li class="add"> <g:link controller="book" action="create" params="['author.id': authorinstance?.id]">${message(code: 'default.add.label', args: [message(code: 'book.label', default: 'book')])}</g:link> </li> </ul>   </div>  <div class="fieldcontain ${haserrors(bean: authorinstance, field: 'name', 'error')} required">     <label for="name">         <g:message code="author.name.label" default="name" />         <span class="required-indicator">*</span>     </label>     <g:textfield name="name" required="" value="${authorinstance?.name}"/>  </div> 

_authortemp.gsp

<div class="dialog">     <table>         <tbody>             <tr class="prop">                 <td valign="top" class="name"><label for="name">name:</label></td>                 <td valign="top" class="value ${haserrors(bean:authorinstance,field:'name','errors')}">                     <input type="text" id="name" name="name" value="${fieldvalue(bean:authorinstance,field:'name')}"/>                 </td>             </tr>                         <tr class="prop">                 <td valign="top" class="name"><label for="category">category:</label></td>                 <td valign="top" class="value ${haserrors(bean:authorinstance,field:'category','errors')}">                     <input type="text" id="category" name="category" value="${fieldvalue(bean:authorinstance,field:'category')}"/>                 </td>             </tr>             <tr class="prop">                 <td valign="top" class="name"><label for="books">books:</label></td>                 <td valign="top" class="value ${haserrors(bean:authorinstance,field:'books','errors')}">                     <g:render template="books" model="['authorinstance':authorinstance]" />                 </td>             </tr>         </tbody>     </table> </div> 

_books.gsp

<script type="text/javascript">     var childcount = ${authorinstance?.books.size()} + 0;      function addchild() {         var htmlid = "book" + childcount;         var deleteicon = "${resource(dir:'images/skin', file:'database_delete.png')}";         var templatehtml = "<div id='" + htmlid + "' name='" + htmlid + "'>\n";         templatehtml += "<input type='text' id='expandablebooklist[" + childcount + "].title' name='expandablebooklist[" + childcount + "].title' />\n";         templatehtml += "<span onclick='$(\"#" + htmlid + "\").remove();'><img src='" + deleteicon + "' /></span>\n";         templatehtml += "</div>\n";         $("#childlist").append(templatehtml);         childcount++;     } </script>  <div id="childlist">     <g:each var="book" in="${authorinstance.books}" status="i">         <g:render template='book' model="['book':book,'i':i]"/>     </g:each> </div> <input type="button" value="add book" onclick="addchild();" /> 

_book.gsp

<div id="book${i}">     <g:hiddenfield name='expandablebooklist[${i}].id' value='${book.id}'/>     <g:textfield name='expandablebooklist[${i}].title' value='${book.title}'/>     <input type="hidden" name='expandablebooklist[${i}]._deleted' id='expandablebooklist[${i}]._deleted' value='false'/>     <span onclick="$('#expandablebooklist\\[${i}\\]\\._deleted').val('true'); $('#expandablebooklist${i}').hide()">delete</span> </div> 

you don't need

list<book> books = new arraylist<>() 

in domain. hasmany give books collection default. might causing issues. also, have debugged in controller make sure books collection populated when save occurs.


Comments

Popular posts from this blog

java - How to specify maven bin in eclipse maven plugin? -

single sign on - Logging into Plone site with credentials passed through HTTP -

php - Why does AJAX not process login form? -