I have a template that displays the entire hasMany property of a domain object (we will call them foos, although I regret foo), as well as the remaining number of those foos that are not included in the domain. From the template, you can add or remove foos from the relationship using the plus and minus buttons through ajax calls. However ... I get pretty weird behavior.
The first time you press one of the plus or minus buttons, the ajax call works fine, and the model is updated, as it should be ... but after that everything breaks. The template gets rendered again as it should, but the domain seems to be missing in action (along with its foos), and the buttons no longer work. Foos are really added / removed from the domain and saved correctly, but are not reflected in the template that has just been processed.
During debugging, I decided to simply display the toString () domain objects inside the template and found that after the first ajax call, it actually changes from Domain to org.apache.catalina.core.ApplicationContextFacade. WEIRD.
In addition, after clicking the plus or minus button again, a mysterious syntax error appears on the javascript console: "Uncaught SyntaxError: Unexpected token" (index): 1. Actually, the strange part is where it is ... .line of one of the document in the DOCTYPE declaration. I checked it, there is no ',' there, as SyntaxError says it is, but the element is still scary the red squiggly line below it.
Can someone help me point me in the right direction? I was stuck trying to figure this out for two days!
. , , , , , . , , , , ... .
Domain.groovy
class Domain {
static hasMany = [foos: Foo]
}
Foo.groovy
class Foo {
static hasMany = [domains: Domain]
static belongsTo = [Domain]
}
DomainController.groovy
def show(String id) {
Domain domain = domain.get(id)
if (!domain) {
response.sendError(404)
return
}
[domain: domain, foos: Foo.list() - domain.foos]
}
def fooToggle(String domainId, String fooId, String fooAction) {
Domain domain = Domain.get(domainId)
Foo foo = Foo.get(fooId)
if (!domain || !foo) {
response.sendError(404)
return
}
else {
if (fooAction == "add") {
domain.addToFoos(foo)
}
else if (fooAction == "remove") {
domain.removeFromFoos(foo)
}
domain.save()
}
render template: "foos", model: [domain: domain, foos: Foo.list() - domain.foos]
}
show.gsp
<html>
<head></head>
<body>
<div id="foos">
<g:render template="foos" model="${[domain: domain, foos: foos]}" />
</div>
</body>
</html>
_foos.gsp
<g:if test="${domain}">${domain}</g:if>
<g:if test="${domain.foos}">
<small>Click the minus button to remove a foo from this domain</small>
<g:each var="foo" in="${domain.foos}">
<div id="foo${foo.id}" class="fooItem">
<span>${foo.bar}</span>
<img onclick="fooToggle(${domain.id}, ${foo.id}, 'remove')" class="fooButton" src="${fam.icon(name: 'delete')}"/>
</div>
</g:each>
</g:if>
<g:else>
<p><small><em>This domain does not have any foos</em></small></p>
</g:else>
<g:if test="${foos}">
<hr>
<small>Click the plus button to add a foo to this domain</small>
<g:each var="foo" in="${foos}">
<div id="foo${foo.id}" class="fooItem">
<span>${foo.bar}</span>
<img onclick="fooToggle(${domain.id}, ${foo.id}, 'add')" class="fooButton" src='${fam.icon(name: 'add')}'/>
</div>
</g:each>
</g:if>
<script>
function fooToggle(domainId, fooId, fooAction) {
$.ajax({
url: '${g.createLink(controller: 'domain', action: 'fooToggle')}',
data: {
'domainId': domainId,
'fooId': fooId,
'fooAction': fooAction
},
success: function(resp) {
$("#foo" + fooId).fadeOut("fast", function() {
$("#foos").html(resp);
});
}
});
}
</script>