At times you would want process a part of the form and refresh the page with the results obtained from the partial form submission. Given below is a screen shot of the typical use case. It is a form used in a sales application.
Take a look at the section "Particulars" in the screen. The fields - Item, Unit Price, Quantity, Discount%, Tax% are editable and fields - Total Discount, Total Tax and Grand Total are calculated as the result of clicking "Calculate" link in this section.
There is on option to add multiple rows to this table by selecting "Add" in the first cell of this table. The section of the code used for the table "Particulars" is given below.
The following Jquery library and the plugin jquery.form is used. Add the scripts to the gsp page. (create.gsp or edit.gsp)
Note the following key links between the html section and the script section
1. The name of the form is "myform" and the declaration of the variable queryString
queryString = $('#myform .sp1').fieldSerialize();
2. Form fields unitPrice, item, qty, discount, tax etc are defined with css class "sp1". eg: <td><input style="width:80px;" class="sp1" name="unitPrice" type="text"/></td>
and the queryString in the script has reference to sp1 as given below.
queryString = $('#myform .sp1').fieldSerialize();
3. The link between the "Calculate" link and the javascript used to invoke the jquery function.
$('#calcP').click( function() { ...
<tr>
<td></td>
<td></td>
<th><a href="#" id="calcP">Caculate</a></th>
...
</tr>
4. Note the link between the gsp page and the Grails controller viz salesBill.
$.post("${createLinkTo(dir:'/salesBill/calculate')}"
A "calculate" closure has to be defined in the controller class the returns output as JSON.
5. "calculate" closure in the controller class.
6. Note the use of groovy util class used as value object that is converted to json object in the grails "calculate" closure.
class CalcResult {
String item
double unitPrice
double quantity
double tax
double discount
double amount
}
7. Finally calc(json) function used in the javascript that is used to update the calculated fields.
Take a look at the section "Particulars" in the screen. The fields - Item, Unit Price, Quantity, Discount%, Tax% are editable and fields - Total Discount, Total Tax and Grand Total are calculated as the result of clicking "Calculate" link in this section.
There is on option to add multiple rows to this table by selecting "Add" in the first cell of this table. The section of the code used for the table "Particulars" is given below.
<g:form name="myform" action="save" method="post" >
...
...
...
<table id="pList" border="1px" style="width:650px;">
<thead>
<tr>
<td><a href="#" id="addR">Add</a></td>
<th>Item</th>
<th>Unit Price</th>
<th>Quantity</th>
<th>Discount%</th>
<th>Tax%</th>
<th>Amount</th>
</tr>
</thead>
<tbody>
<g:if test="${salesBillInstance.lineItems?.size()>0}">
<g:each var="l" in="${salesBillInstance.lineItems}">
<tr>
<td><a href="#" class="delete">Del</a></td>
<td><input type="text" class="sp1" name="item" value="${l.itemName}"/></td>
<td><input style="width:80px;" class="sp1" name="unitPrice" value="${l.unitPrice}" type="text"/></td>
<td><input style="width:80px;" class="sp1" name="qty" value="${l.quantity}" type="text"/></td>
<td><input style="width:80px;" class="sp1" name="discount" value="${l.discount}" type="text"/></td>
<td><input style="width:80px;" class="sp1" name="tax" value="${l.tax}" type="text"/></td>
<td><input style="width:80px;" class="sp1" name="amount" readonly="readonly" value="${l.totalPrice}" type="text"/></td>
</tr>
</g:each>
</g:if>
<g:else>
<tr>
<td><a href="#" class="delete">Del</a></td>
<td><input type="text" class="sp1" name="item"/></td>
<td><input style="width:80px;" class="sp1" name="unitPrice" type="text"/></td>
<td><input style="width:80px;" class="sp1" name="qty" value="1" type="text"/></td>
<td><input style="width:80px;" class="sp1" name="discount" value="0" type="text"/></td>
<td><input style="width:80px;" class="sp1" name="tax" value="0" type="text"/></td>
<td><input style="width:80px;" class="sp1" name="amount" readonly="readonly" type="text"/></td>
</tr>
</g:else>
</tbody>
<tfoot>
<tr>
<td></td>
<td></td>
<td></td>
<th>Special Disc</th>
<th>Total Disc</th>
<th>Total Tax </th>
<th>Grand Total</th>
</tr>
<tr>
<td></td>
<td></td>
<th><a href="#" id="calcP">Caculate</a></th>
<td><input style="width:80px;" id="totalSD" class="sp1" value="${salesBillInstance.specialDiscountValue}" name="specialDiscountValue" type="text"/></td>
<td><input style="width:80px;" id="totalD" value="${salesBillInstance.discount}" readonly="readonly" type="text"/></td>
<td><input style="width:80px;" id="totalT" value="${salesBillInstance.vat}" readonly="readonly" type="text"/></td>
<td><input style="width:80px;" id="totalA" value="${salesBillInstance.billAmount}" readonly="readonly" type="text"/></td>
</tr>
</tfoot>
</table>
...
...
</g:form>
The following Jquery library and the plugin jquery.form is used. Add the scripts to the gsp page. (create.gsp or edit.gsp)
Note the following key links between the html section and the script section
1. The name of the form is "myform" and the declaration of the variable queryString
queryString = $('#myform .sp1').fieldSerialize();
2. Form fields unitPrice, item, qty, discount, tax etc are defined with css class "sp1". eg: <td><input style="width:80px;" class="sp1" name="unitPrice" type="text"/></td>
and the queryString in the script has reference to sp1 as given below.
queryString = $('#myform .sp1').fieldSerialize();
3. The link between the "Calculate" link and the javascript used to invoke the jquery function.
$('#calcP').click( function() { ...
<tr>
<td></td>
<td></td>
<th><a href="#" id="calcP">Caculate</a></th>
...
</tr>
4. Note the link between the gsp page and the Grails controller viz salesBill.
$.post("${createLinkTo(dir:'/salesBill/calculate')}"
A "calculate" closure has to be defined in the controller class the returns output as JSON.
5. "calculate" closure in the controller class.
def calculate ={
println (params)
def errMsg = null
def items = params.item
def quantities = params.qty
def unitPrice = params.unitPrice
def discount = params.discount
def tax = params.tax
def output = new ArrayList()
if(items == null){
errMsg = '{error:"No data. Add Items for calculation"}'
}
else if (items instanceof String)
{
CalcResult calc = new CalcResult()
try{
int quant = Integer.parseInt(quantities)
double up = Double.parseDouble(unitPrice)
println ("Disc = " + discount)
double disc = Double.parseDouble(discount)
println ("Tax = " + tax)
double tx = Double.parseDouble (tax)
double amt = quant * up
double itemDisc = (disc/100) * amt
double itemTax = (amt - itemDisc) * (tx/100)
amt = (amt - itemDisc + itemTax)
calc.amount = amt.round(2)
calc.discount = itemDisc.round(2)
calc.tax = itemTax.round(2)
}
catch(Exception e)
{
e.printStackTrace()
errMsg = '{error:"data error in row ' + 1 + '"}'
}
if (errMsg == null)
{
if (items == "")
errMsg = "No item added to row 1"
else
output.add(calc)
}
}
else{
for(int i=0;i < items.length;i++ )
{
println ("item = " + items[i])
println ("quantities = " + quantities[i])
println ("unitPrice = " + unitPrice[i])
if (items[i].trim() =="" || quantities[i].trim() == "" ||
unitPrice[i].trim() == "")
{
println ("error ...")
errMsg = '{error:"data error in row ' + (i+1) + '"}'
break
}
CalcResult calc = new CalcResult()
try{
int quant = Integer.parseInt(quantities[i])
double up = Double.parseDouble(unitPrice[i])
double disc = Double.parseDouble(discount[i])
double tx = Double.parseDouble (tax[i])
double amt = quant * up
double itemDisc = (disc/100) * amt
double itemTax = (amt - itemDisc) * (tx/100)
amt = (amt - itemDisc + itemTax)
calc.amount = amt.round(2)
calc.discount = itemDisc.round(2)
calc.tax = itemTax.round(2)
}
catch(Exception e)
{
e.printStackTrace()
errMsg = '{error:"data error in row ' + (i+1) + '"}'
break
}
output.add (calc)
}
}
if (errMsg != null)
render errMsg
else{
println ("output size = " + output.size())
render output as JSON
}
}
6. Note the use of groovy util class used as value object that is converted to json object in the grails "calculate" closure.
class CalcResult {
String item
double unitPrice
double quantity
double tax
double discount
double amount
}
7. Finally calc(json) function used in the javascript that is used to update the calculated fields.
function calc(json){
var i =0;
var grandTotal = 0;
var grandDisc = 0;
var grandTax = 0;
$.each (json, function(){
//alert (this.amount);
var amt = this.amount;
var discount = this.discount;
var tax = this.tax;
var k =0;
$("input[name='amount']").each(function()
{
if (k == i){
$(this).val(amt);
grandTotal = grandTotal + amt;
grandDisc = grandDisc + discount;
grandTax = grandTax + tax;
}
k++;
});
i++;
});
grandTotal = grandTotal - ($('#totalSD').val());
$('#totalA').val(Math.round(grandTotal));
$('#totalD').val(Math.round(grandDisc));
$('#totalT').val(Math.round(grandTax));
// alert (json);
}
hi sir !
ReplyDeletei had a problem with gsp like
how can i show the different fields for different peoples?
You need to follow these steps.
ReplyDelete1)Integrate security plugins like acegi or shiro.
2)Create application roles.
3)Create users for the application and assign them roles.
4) use the following gsp tags as shown in the example below.
<g:ifAnyGranted role="ROLE_ADMIN">
<a href="${createLink(controller: 'secUser', action:'list')}" >User Admin </a> </g:ifAnyGranted>
Likewise you can create as many roles as you need and give access accordingly. Note that this is advised only if you want to disable access to certain portions of the within a gsp page.
If you want to completely disable Page or a URL for a user you can create access control rules using the security plugins listed in step 1.
Hi sir! thanks for previous reply.......
ReplyDeletei had an exception in comparison using inList.
my code is like this.
def students = Student.list()
def lnames= students.collect{it.lastName}
if(Student.lastName(inList:[lnames]))
& exception like :groovy.lang.MissingMethodException: No signature of method: com.symfore.student.Student.lastName() is applicable for argument types: (java.util.LinkedHashMap) values: [[inList:[[rani]]]] Possible solutions: getLastName(), setLastName(java.lang.String).....
how can i resolve it sir..