Im trying to upload several (one to many) images using grails and jquery. I’ve been following this post, but I couldn’t make it so far. The thing is that it seems that everything is ok, but when you try to save images (creating a building for instance) it doesn’t save any image.
I think, the key of the problem is in the gsp params for the file types(images). These are the params that arrive to my controller:
[name:1, type:1, create:Crear,
imagesList[0].data:org.springframework.web.multipart.commons.CommonsMultipartFile@d9278f,
imagesList[0]:data:org.springframework.web.multipart.commons.CommonsMultipartFile@d9278f], action:save, controller:building]
So, I think that these params are wrong for what I wanna do. Any ideas, or sample code to fix this?? Thanks!
My save() method in the building controller
def save() {
def buildingInstance = new Building(params)
if (!buildingInstance.save(flush: true)) {
render(view: "create", model: [buildingInstance: buildingInstance])
return
}
flash.message = message(code: 'default.created.message', args: [message(code: 'building.label', default: 'Building'), buildingInstance.id])
redirect(action: "show", id: buildingInstance.id)
}
My domains:
class Building {
def Integer type
def String name
List images = new ArrayList()
static hasMany = [images: Image]
static constraints = {
name()
type()
}
static mapping = {
images cascade:"all-delete-orphan"
}
def getImagesList() {
return LazyList.decorate(images,FactoryUtils.instantiateFactory(Image.class))
}
}
class Image {
def byte[] data
static belongsTo = [building: Building]
boolean deleted
static transients = [ 'deleted' ]
static constraints = { data(maxSize:10000000,required:true,blank:false) }
}
My JSP’s:
_Images.jsp
<script type="text/javascript">
function addChild() {
var childCount = ${buildingInstance?.images.size()} + 0;
var htmlId = "image" + childCount;
var deleteIcon = "${resource(dir:'images/skin', file:'icon_delete.png')}";
var templateHtml = "<div id='" + htmlId + "' name='" + htmlId + "'>\n";
templateHtml += "<input type='file' id='imagesList[" + childCount + "].data' name='imagesList[" + childCount + "].data' />\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="image" in="${buildingInstance.images}" status="i">
<!-- Render the image template (_image.gsp) here -->
<g:render template='image'
model="['image':image,'i':i,'hidden':false]" />
</g:each>
</div>
<input type="button" value="Add image" onclick="addChild();" />
_image.gsp
<div id="image${i}" class="image-div" <g:if test="${hidden}">style="display:none;"</g:if>>
<g:hiddenField name='imagesList[${i}].id' value='${image?.id}'/>
<g:hiddenField name='imagesList[${i}].deleted' value='false'/>
<input type="file" name="imagesList[${i}].data" value="${image?.data}" />
<span class="del-image">
<img src="${resource(dir:'images/skin', file:'icon_delete.png')}"
style="vertical-align:middle;"/>
</span>
</div>
I’ve already found where it was the mistake. Just changed the “imagesList” values in the gsp for “images” as the name in the domain and it works. The post I was following seems to be wrong.