1 | |
---|
2 | /** |
---|
3 | * General use custom tags. |
---|
4 | * Some are taken from http://www.grails.org/Contribute+a+Tag#checkBoxList |
---|
5 | */ |
---|
6 | class CustomTagLib { |
---|
7 | static namespace = 'custom' |
---|
8 | |
---|
9 | def resources = { attrs -> |
---|
10 | ///@todo: should include our javascript and do setup here. |
---|
11 | } |
---|
12 | |
---|
13 | /** |
---|
14 | * Checkbox list that can be used as a more user-friendly alternative to a multiselect list box. |
---|
15 | * Usage: |
---|
16 | * To map the selected ids to corresponding domain objects, |
---|
17 | * an additional set method is required in the containing domain class: |
---|
18 | * // This additional setter is used to convert the checkBoxList string or string array |
---|
19 | * // of ids selected to the corresponding domain objects. |
---|
20 | * public void setAssetSubItemsFromCheckBoxList(ids) { |
---|
21 | * def idList = [] |
---|
22 | * if(ids instanceof String) { |
---|
23 | * if(ids.isInteger()) |
---|
24 | * idList << ids.toInteger() |
---|
25 | * } |
---|
26 | * else { |
---|
27 | * ids.each() { |
---|
28 | * if(it.isInteger()) |
---|
29 | * idList << it.toInteger() |
---|
30 | * } |
---|
31 | * } |
---|
32 | * this.assetSubItems = idList.collect { AssetSubItem.get( it ) } |
---|
33 | * } |
---|
34 | * |
---|
35 | * Then a line in the controller: |
---|
36 | * assetInstance.setAssetSubItemsFromCheckBoxList(params.assetSubItems) |
---|
37 | * |
---|
38 | * Fields: |
---|
39 | * name - the property name. |
---|
40 | * from - the list to select from. |
---|
41 | * value - the current value. |
---|
42 | * optionKey - the key to use. |
---|
43 | * sortBy - (optional) the attribute to sort the from list by. |
---|
44 | * displayFields - (optional) defaults to the objects toString() |
---|
45 | * displayFieldsSeparator - (optional) defaults to a space. |
---|
46 | * linkController - (optional, requires linkAction.) the controller to use for a link to the objects in the checkBoxList. |
---|
47 | * linkAction - (optional, requires linkController.) the action to use for a link to the objects in the checkBoxList. |
---|
48 | * |
---|
49 | * Example: |
---|
50 | * <!-- |
---|
51 | * <custom:checkBoxList name="assetSubItems" |
---|
52 | * from="${AssetSubItem.list()}" |
---|
53 | * value="${assetInstance?.assetSubItems.collect{it.id}}" |
---|
54 | * optionKey="id" |
---|
55 | * sortBy="description" |
---|
56 | * displayFields="['id', 'name']" |
---|
57 | * displayFieldsSeparator=', ' |
---|
58 | * linkController="assetSubItemDetailed" |
---|
59 | * linkAction="show"/> |
---|
60 | * --> |
---|
61 | * |
---|
62 | */ |
---|
63 | |
---|
64 | def checkBoxList = {attrs, body -> |
---|
65 | |
---|
66 | def from = attrs.from |
---|
67 | def value = attrs.value |
---|
68 | def cname = attrs.name |
---|
69 | def isChecked, ht, wd, style, html |
---|
70 | |
---|
71 | def sortBy = attrs.sortBy |
---|
72 | def displayFields = attrs.displayFields |
---|
73 | def displayFieldsSeparator = attrs.displayFieldsSeparator ?: ' ' |
---|
74 | def linkController = attrs.linkController |
---|
75 | def linkAction = attrs.linkAction |
---|
76 | |
---|
77 | def displayValue = " " |
---|
78 | |
---|
79 | // sets the style to override height and/or width if either of them |
---|
80 | // is specified, else the default from the CSS is taken |
---|
81 | style = "style='" |
---|
82 | if(attrs.height) |
---|
83 | style += "height:${attrs.height};" |
---|
84 | if(attrs.width) |
---|
85 | style += "width:${attrs.width};" |
---|
86 | if(style.length() == "style='".length()) |
---|
87 | style = "" |
---|
88 | else |
---|
89 | style += "'" // closing single quote |
---|
90 | |
---|
91 | html = "<ul class='CheckBoxList' " + style + ">" |
---|
92 | |
---|
93 | out << html |
---|
94 | |
---|
95 | if(sortBy) |
---|
96 | from.sort { p1, p2 -> p1[sortBy].compareToIgnoreCase(p2[sortBy]) } |
---|
97 | |
---|
98 | from.each { obj -> |
---|
99 | |
---|
100 | displayValue = " " |
---|
101 | |
---|
102 | if(linkController && linkAction) |
---|
103 | displayValue += "<a href=\"${createLink(controller: linkController, action: linkAction, id: obj.id).encodeAsHTML()}\">" |
---|
104 | |
---|
105 | if(displayFields) { |
---|
106 | displayValue += displayFields.collect { obj[it] }.join(displayFieldsSeparator) |
---|
107 | } |
---|
108 | else displayValue += obj // use the obj's default toString() |
---|
109 | |
---|
110 | if(linkController && linkAction) |
---|
111 | displayValue += "</a>" |
---|
112 | |
---|
113 | // if we wanted to select the checkbox using a click anywhere on the label (also hover effect) |
---|
114 | // but grails does not recognize index suffix in the name as an array: |
---|
115 | // cname = "${attrs.name}[${idx++}]" |
---|
116 | // and put this inside the li: <label for='$cname'>...</label> |
---|
117 | |
---|
118 | isChecked = (value?.contains(obj."${attrs.optionKey}"))? true: false |
---|
119 | |
---|
120 | out << "<li>" << checkBox(name:cname, value:obj."${attrs.optionKey}", checked: isChecked) << displayValue << "</li>" |
---|
121 | } |
---|
122 | |
---|
123 | out << "</ul>" |
---|
124 | |
---|
125 | } // checkBoxList |
---|
126 | |
---|
127 | } // end class |
---|