Reputation: 21
I have an application where I am constantly facing a need to dynamically add/remove group of fields from one to many relationship of domain objects in forms. The fields can be textfields, selects, radio buttons etc. I can't find any simple approach to do this.
For this the best solution according to me would have been to render a div using my grails tags into a javascript string and add remove divs on the form.
E.g. on clicking Add
var vector = $.parseHTML('<div><label>Vector:</label><g:select from="${..}" /><g:text......');
$("#vectorDiv").append(vector);
But approach doesn't work for a variety of reasons. One being javascript doesn't allow newlines in string(without a / at the end which i can't enforce with grails tags).
I don't want to start using React yet. Just jquery and grails tags.
I wanted to get some opinions on this "design pattern" if you will. render a div in my gsp.
<!--templates-->
<div id="templates" hidden>
<div id="templateAccessoryVector" class="form-group accessoryVector">
<div class="col-sm-4">
<g:select class="form-control" name="accessoryVectorsTemplate.vectorId"
from="${Vector.getAccessoryVectors()}" optionKey="id" optionValue="alias" />
</div>
<label class="control-label col-sm-2">Percentage:</label>
<div class="col-sm-2 input-group">
<g:textField class="form-control text-right" name="accessoryVectorsTemplate.percentage" />
<span class="input-group-addon">%</span>
</div>
</div>
</div>
and then in javascript
var templateAccessoryVectorDiv = $("#templateAccessoryVector").removeAttr('id');
function addAccessoryVector(){
var newAccessoryVectorDiv = templateAccessoryVectorDiv.clone();
$("[name^='accessoryVectorsTemplate']", newAccessoryVectorDiv).each (function(index, element) {
element.name = element.name.replace('accessoryVectorsTemplate', 'accessoryVectors[' + accessoryVectors + ']');
});
newAccessoryVectorDiv.appendTo($("#accessoryVectors"));
accessoryVectors++;
}
//add, remove functions
All such templates could live in the templates section, hidden and used when required.
Upvotes: 0
Views: 395
Reputation: 820
When you have to dynamically add/remove these fields? If it is after a request, you can do this request with Ajax and then, based on the response (e.g 200), you append these fields to your page on the Ajax callback. Or instead of creating HTML elements with JS, you can have a gsp template (e.g _fields) and then send along with the response from the controller, like: render template: "fields"
I hope it helps you :)
Good luck!
Upvotes: 1
Reputation: 1553
I think the best solution for this could be a tag lib. You can have a tag for each of your fields. From the controller you can just pass the tab to render and in the GSP you can use the tag accordingly.
In this way you can have support to the g:tag and the javascript if any.
See how to create custom tags: link1 and link2
Upvotes: 0