In my grails view the ordering applied on the domain class constraints are not picked when i use f:display with each individual property. I heard that domain class property comparator can be used to order the property display as per the constraints applied on the domain class.
Can some body help me on how to use DomainClassPropertyComparator to sort properties on my view?
You can install the scaffolding templates, edit _form.gsp and change the comparator it is using to DomainClassPropertyComparator e.g. my _form.gsp
<%=packageName%>
<% import grails.persistence.Event %>
<% import org.codehaus.groovy.grails.scaffolding.DomainClassPropertyComparator %>
<% excludedProps = Event.allEvents.toList() << 'version' << 'dateCreated' << 'lastUpdated'
persistentPropNames = domainClass.persistentProperties*.name
boolean hasHibernate = pluginManager?.hasGrailsPlugin('hibernate')
if (hasHibernate && org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainBinder.getMapping(domainClass)?.identity?.generator == 'assigned') {
persistentPropNames << domainClass.identifier.name
}
DomainClassPropertyComparator mattsComparator = new DomainClassPropertyComparator(domainClass)
comparator = mattsComparator
props = domainClass.properties.findAll { persistentPropNames.contains(it.name) && !excludedProps.contains(it.name) }
Collections.sort(props, comparator)
for (p in props) {
if (p.embedded) {
def embeddedPropNames = p.component.persistentProperties*.name
def embeddedProps = p.component.properties.findAll { embeddedPropNames.contains(it.name) && !excludedProps.contains(it.name) }
Collections.sort(embeddedProps, comparator)
%><fieldset class="embedded"><legend><g:message code="${domainClass.propertyName}.${p.name}.label" default="${p.naturalName}" /></legend><%
for (ep in p.component.properties) {
renderFieldForProperty(ep, p.component, "${p.name}.")
}
%></fieldset><%
} else {
renderFieldForProperty(p, domainClass)
}
}
private renderFieldForProperty(p, owningClass, prefix = "") {
boolean hasHibernate = pluginManager?.hasGrailsPlugin('hibernate')
boolean display = true
boolean required = false
if (hasHibernate) {
cp = owningClass.constrainedProperties[p.name]
display = (cp ? cp.display : true)
required = (cp ? !(cp.propertyType in [boolean, Boolean]) && !cp.nullable && (cp.propertyType != String || !cp.blank) : false)
}
if (display) { %>
<div class="fieldcontain \${hasErrors(bean: ${propertyName}, field: '${prefix}${p.name}', 'error')} ${required ? 'required' : ''}">
<label for="${prefix}${p.name}">
<g:message code="${domainClass.propertyName}.${prefix}${p.name}.label" default="${p.naturalName}" />
<% if (required) { %><span class="required-indicator">*</span><% } %>
</label>
${renderEditor(p)}
</div>
<% } } %>
Related
Formatted the form_input_field, but the number displays and stores in the db differently. Please let me know if you need further details.
<div class="my-5" data-controller="phoneinput">
<%= form.label :Phone %>
<%= form.text_field :phone, class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full", data: { 'phoneinput-target': 'input'}, :maxlength=>"12", placeholder: "555-111-5555" %>
</div>
to perform 555555 to 555-111-5555 using a stimulus controller
import { Controller } from "#hotwired/stimulus"
export default class extends Controller {
static targets = [ "input" ]
connect() {
const input = this.inputTarget;
// console.log("hellow");
input.addEventListener("keydown", (e) => {
if (e.key === "Backspace" || e.key === "Delete") return
if (e.target.value.length === 3) {
input.value = input.value + "-"
}
if (e.target.value.length === 7) {
input.value = input.value + "-"
}
if(e.target.value.length === 14) {
input.value = input.value + "-";
}
}
)
}
}
we use using mail-ext and robot frame work to try to format all test suits detail in jenkins, and send out the report.
here is the groovy email-template we used now, its downloaded from github, https://github.com/JMcn/jenkins-email-ext-templates/blob/master/robot.groovy.
but this template reported following exception as below, i did not get similar error via googling, anything we missed for this template, thanks for any hint on this error.
<%
import java.text.DateFormat
import java.text.SimpleDateFormat
%>
........
<!-- System Test Result -->
<%
def robotResults = false
def actions = build.actions // List<hudson.model.Action>
def robotTestResultAction = it.getAction("hudson.plugins.robot.RobotBuildAction")
actions.each() { action ->
if( robotTestResultAction != null ) {
//if( action && (action.class.simpleName.equals("RobotBuildAction") ) ) {
robotResults = true
%>
<TABLE width="100%">
<TR><TD class="bg1" colspan="4"><B>test results</B></TD></TR>
<TR style="border:1px solid #000;height:25px">
<TD>total</TD>
<TD>passed</TD>
<TD>failure</TD>
<TD>passrate</TD></TR>
<TR style="border:1px solid #000;height:25px">
<TD>${robotTestResultAction.getTotalCount()}</TD>
<TD style="color:green"><%=robotTestResultAction.getTotalCount() - robotTestResultAction.getFailCount()%></TD>
<TD style="color:red"><a style="color:red" href="${rooturl}${build.url}/${robotTestResultAction.urlName}">${robotTestResultAction.getFailCount()}</a></TD>
<TD>${robotTestResultAction.overallPassPercentage}%</TD></TR>
</TABLE>
<TABLE cellspacing="0" cellpadding="4" border="1" align="center">
<thead>
<tr bgcolor="#F3F3F3">
<td><b>test case name </b></td>
<td><b>state</b></td>
<td><b>execute duration</b></td>
</tr>
</thead>
<tbody>
<% def suites = action.result.allSuites
suites.each() { suite ->
def currSuite = suite
def suiteName = currSuite.displayName
// ignore top 2 elements in the structure as they are placeholders
while (currSuite.parent != null && currSuite.parent.parent != null) {
currSuite = currSuite.parent
suiteName = currSuite.displayName + "." + suiteName
} %>
<tr><td colspan="3"><b><%= suiteName %></b></td></tr>
<% DateFormat format = new SimpleDateFormat("yyyyMMdd HH:mm:ss.SS")
def execDateTcPairs = []
suite.caseResults.each() { tc ->
Date execDate = format.parse(tc.starttime)
execDateTcPairs << [execDate, tc]
}
// primary sort execDate, secondary displayName
execDateTcPairs = execDateTcPairs.sort{ a,b -> a[1].displayName <=> b[1].displayName }
execDateTcPairs = execDateTcPairs.sort{ a,b -> a[0] <=> b[0] }
execDateTcPairs.each() {
def execDate = it[0]
def tc = it[1] %>
<tr>
<td><%= tc.displayName %></td>
<td style="color: <%= tc.isPassed() ? "#66CC00" : "#FF3333" %>"><%= tc.isPassed() ? "PASS" : "FAIL" %></td>
<td><%= execDate %></td>
</tr>
<% } // tests
} // suites %>
</tbody>
</TABLE>
<%
} // robot results
}
if (!robotResults) {
%>
<TABLE width="100%">
<TR><TD class="bg1" colspan="2"><B>接口测试结果</B></TD></TR>
<TR><TD colspan="2">robotTestResultAction is null</TD></TR>
</TABLE>
<%
}
%>
<BR/>
Exception raised during template rendering: No such property: result for class: hudson.model.CauseAction groovy.lang.MissingPropertyException: No such property: result for class: hudson.model.CauseAction at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:53) at org.codehaus.groovy.runtime.callsite.GetEffectivePojoPropertySite.getProperty(GetEffectivePojoPropertySite.java:66) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:296) at
after adjust script using Krzysztof Błażełek's suggestion, we got following error.
<!-- System Test Result -->
<%
def robotResults = false
def actions = build.actions // List<hudson.model.Action>
//def robotTestResultAction = it.getAction("hudson.plugins.robot.RobotBuildAction")
actions.each() { action ->
//if( robotTestResultAction != null ) {
if( action && (action.class.simpleName.equals("RobotBuildAction") ) ) {
robotResults = true
Exception raised during template rendering: Cannot get property 'simpleName' on null object java.lang.NullPointerException: Cannot get property 'simpleName' on null object at org.codehaus.groovy.runtime.NullObject.getProperty(NullObject.java:60) at org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:174) at org.codehaus.groovy.runtime.callsite.NullCallSite.getProperty(NullCallSite.java:47) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:296) at SimpleTemplateScript211$_run_closure6.doCall(SimpleTemplateScript211.groovy:403) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ....
You have modified the template you have provided and that causes the problem. I believe you are iterating over all actions (not only hudson.plugins.robot.RobotBuildAction) and that is causing the exception. Try changing this part:
<!-- System Test Result -->
<%
def robotResults = false
def actions = build.actions // List<hudson.model.Action>
def robotTestResultAction = it.getAction("hudson.plugins.robot.RobotBuildAction")
actions.each() { action ->
if( robotTestResultAction != null ) {
//if( action && (action.class.simpleName.equals("RobotBuildAction") ) ) {
robotResults = true
%>
into
<!-- System Test Result -->
<%
def robotResults = false
def actions = build.actions // List<hudson.model.Action>
actions.each() { action ->
if( action && (action.class.simpleName.equals("RobotBuildAction") ) ) {
robotResults = true
def robotTestResultAction = action
%>
Your code needs refactoring, but that's the quickest way to test if it works.
Revise as below,which solved my problem.
if( action.class && (action.class.simpleName.equals("RobotBuildAction") ) )
I am sending the employee object from the Project_level controller to the _add_members view and then from there I am sending the employee object to the Project_permission controller. while saving the id the following error is coming: No such property: id for class: java.lang.String in the line :proj_permission.setId_of_employee(emp.id)
class Project_levelController {
def auth_after_create_level(){
//creating a level under the above level
def res=Project_level.findByLevel_nameAndLevel_no(params.level_name,params.level_no)
// def res=null
if(res)
{
flash.message='level name has already been taken'
redirect(action:'_right')
}
else{
if(params.enter=="NEXT")
{
def proj_lev_right = new Project_level_right(params["project_level_right"])
proj_lev_right.save()
proj_lev_right.errors.allErrors.each { println it }
session.proj_lev_right = proj_lev_right
def proj_lev = new Project_level(params["project_level"])
proj_lev.setProj_lev_right_id("${proj_lev_right.id}")
proj_lev.id_of_project=session.id_of_project
proj_lev.mem_added = 0
proj_lev.save()
proj_lev.errors.allErrors.each { println it }
session.proj_lev = proj_lev
def emp = Employee.findAllByLevel(proj_lev.level_no)
render(view: "add_members", model: [proj_lev:proj_lev , proj_lev_right:proj_lev_right , employee:emp])
}
}
}
def _right(){
}
}
/*****************************************************************************/
class Project_permissionController {
def add_employee_to_project()
{
def emp = params.employee
def proj_permission=new Project_permission()
proj_permission.id_of_project=session.id_of_project
proj_permission.setId_of_employee(emp.id)
proj_permission.id_of_poject_level=session.proj_lev.id
/* def employee_proj_level= Project_level.get(proj_permission.id_of_project_level)//making a empty project_project and saving the project level field that belong to id_of_project_level
def employee_proj_level_right= new Project_level_right()//making a empty project_level_right
employee_proj_level_right= Project_level_right.get(employee_proj_level.proj_lev_right_id)//empty project_level_right is used to store the default right for that particular level that is given by "proj_lev_right_id"
proj_permission.setId_of_project_level_right("${employee_proj_level_right.id}")//saving employee project_level_right in id_of_proj_level_right
*/
proj_permission.id_of_project_level_right=session.proj_lev_right.id
render "Hari"
}
/**********************************************************/
<g:each var="emp" in="${employee}">
<g:link controller="project_permission" action="add_employee_to_project" params="[employee:emp]">
<button class="btn btn-block btn-info btn-sm">Add to Project</button>
</g:link></td>
</a>
</div>
</div>
</div>
</g:each>
</ul>
</div>
</div>
</div><!-- /.box-body -->
</div><!-- /.box -->
The problem is on this code:
def emp = params.employee
....
proj_permission.setId_of_employee(emp.id)
You get emp from params which is a string ( probably employee id) then you are trying to access id field from it, id field from string object? that is the problem.
Possible solution:
replace def emp = params.employee with def emp = Employee.get(params.employee)
I'm using Grails to set properties on a domain class if the property is not null. Currently, the code looks something like this:
def product = Product.getById(5);
if (!product.Name) {
product.Name = "Default Product"
}
if (!product.Price) {
product.Price = 5;
}
if (!product.Type) {
product.Type = "Shampoo"
}
What is a better way of implementing this code block in Groovy? I managed to simplify it to:
product.Name = product.Name ?: "Default Product"
product.Price = product.Price ?: 5
product.Type = product.Type = "Shampoo"
But I'd like to be able to do something like this (not valid code):
product {
Name = product.Name ?: "Default Product",
Price = product.Price ?: 5,
Type = product.Type ?: "Shampoo"
}
What would you guys recommend I do?
Use the with method call on your last example:
product.with {
Name = Name ?: "Default Produce"
Price = Price ?: 5
Type = Type ?: "Shampoo"
}
Not sure if simpler, but maybe more re-usable:
def setDefaults(obj, Map defaults) {
defaults.each { k, v -> obj[k] = obj[k] ?: v }
}
setDefaults(product, [Name: 'Default Product', Price: 5, Type: 'Shampoo'])
I am trying to check if a value from database table is equal to Char, in the view I tried
the following:
<% if (Model.MethodOfPayment.ToString().Equals("W") == true)
{
%>
Wire
<%} %>
<%else
{ %>
<% if (Model.MethodOfPayment.ToString().Equals("C") == true)
{
%>
Cheque
<%} %>
<%} %>
Did not work!
In the controller to send the output to PDF Form: I tried the following:
string MyString = order.MethodOfPayment.ToString();
if (MyString == "W")
{
pdfFormFields.SetField("MethodOfPayment", "W");
}
else
{
if (MyString == "W")
{
pdfFormFields.SetField("MethodOfPayment", "C");
}
}
Did not work either.
Thanks in advance.
How about:
if (Model.MethodOfPayment == 'W')
If this doesn't work it simply means that the MethodOfPayment property doesn't equal to the W character. Try debugging your code to see exactly to which value it equals.