Show last authors
1 {{box cssClass="floatinginfobox" title="**Contents**"}}
2 {{toc/}}
3 {{/box}}
4
5 Explains how to implement adding and removing objects in XWiki when editing application entries.
6
7 We are going to create a simple application built with [[Application Within Minutes>>extensions:Extension.App Within Minutes Application]], called 'Stores'. Since a store can have many headquarters, what we want is to allow the user to add / remove headquarters when editing a Stores entry.
8
9 = Step 1. Create the Stores Application =
10
11 The first step is to create the application with AWM. So, create an app called "Stores" and when designing the form use one Short Text field and one Long Text field, as shown in the following screenshot:
12
13 {{image reference="stores-form.png"/}}
14
15 = Step 2: Modify the Stores Class Sheet =
16
17 Let's now modify ##Stores.Code.StoresSheet## to implement dynamically adding / removing headquarters. Modify the default content to be:
18
19 {{code}}
20 {{velocity}}
21 {{html wiki="true"}}
22 #set($class = 'Stores.Code.StoresClass')
23 #set ($discard = $doc.use($class))
24 (% class="xform" %)
25 (((
26 #foreach($obj in $doc.getObjects($class))
27 #set($objNumber = $obj.number)
28 #set($index = $foreach.index + 1)
29 (% id="xwikiobjects" class="xclass" %)(((
30 (% class="xobject" %)(((
31 #if($xcontext.action == 'edit')
32 (% class="xobject-title" %)(((
33 <h3>Headquarter $index
34 <a href="$doc.getURL('objectremove', "form_token=$!{services.csrf.getToken()}&amp;classname=${escapetool.url($class)}&amp;classid=${objNumber}&amp;xredirect=${escapetool.url($doc.getURL('edit'))}")" class="xobject-action delete" title="$services.localization.render('core.editors.object.removeObject.tooltip')">$services.localization.render('core.editors.object.removeObject')</a>
35 </h3>
36 )))
37 #end
38 (% class="xobject-content" %)(((
39 ; <label#if ($xcontext.action == 'edit') for="${class}_${objNumber}_0_name"#end>$escapetool.xml($doc.displayPrettyName('name', false, false))</label>
40 : $doc.display('name', $obj)
41 ; <label#if ($xcontext.action == 'edit') for="${class}_${objNumber}_0_address"#end>$escapetool.xml($doc.displayPrettyName('address', false, false))</label>
42 : $doc.display('address', $obj)
43 )))
44 )))
45 )))
46 #end
47
48 #if($xcontext.action == 'edit')
49 (% id="add_xobject_${escapetool.xml($class)}" class="add_xobject" style="display: block;" %)(((
50 (% id="add_xobject_${escapetool.xml($class)}_title" class="add_xobject-title" style="display: block;" %)((( ## Have to overwrite a CSS rule from dataeditors.css
51 <a href="$doc.getURL('edit', "xpage=editobject&amp;xaction=addObject&amp;className=$escapetool.url(${class})&amp;xredirect=$escapetool.url(${doc.getURL('edit')})")" class="xobject-add-control" title="$services.localization.render('core.editors.object.add.label')">$services.localization.render('core.editors.object.add.label')</a>
52 )))
53 )))
54 $xwiki.jsfx.use('js/xwiki/editors/dataeditors.js', true)##
55 $xwiki.ssfx.use('js/xwiki/editors/dataeditors.css', true)##
56 #end
57 )))
58 {{/html}}
59 {{/velocity}}
60 {{/code}}
61
62 {{warning}}
63 Note that if you edit the Stores Application after making the changes in ##Stores.Code.StoresSheet##, these changes will be lost. You will have to redo the steps above if you want to set back the add / remove objects feature in the application.
64 {{/warning}}
65
66 You're all set! Let's now try it!
67
68 = Step 3: Create an entry in the Stores Application =
69
70 Navigate back to the Stores Application and Create an entry. You should now have the options to expand the object that was added by default, to remove this object and to add a new object. When loading the edit form, the objects are collapsed because this is the default behavior of the dataeditors application that we reused to make our feature work.
71
72 {{image reference="stores-results1.png"/}}
73
74 This is what the form looks like when you add a new object :
75
76 {{image reference="stores-results2.png"/}}
77
78 And when viewing the page:
79
80 {{image reference="stores-results3.png"/}}
81
82 = A simplified version of edit form =
83
84 You can personalize even more your application by updating translations, by changing the styles, by removing the elements that don't suit your use case (like the expand / collapse feature, for example).
85
86 == The AWM version ==
87
88 This is a simplified UI of an application built with AWM, that doesn't contain icons or the expand/collapse feature, but contains the basic elements that are needed in order to make it possible to add / remove objects in the application entries. This code is meant to be put in the Stores Class Sheet (##Stores.Code.StoresSheet## document).
89
90 {{code}}
91 {{velocity}}
92 {{html wiki="true"}}
93 #set($class = 'Stores.Code.StoresClass')
94 (% class="xform" %)
95 (((
96 #foreach($obj in $doc.getObjects($class))
97 #set($objNumber = $obj.number)
98 (% id="xwikiobjects" class="xclass" %)(((
99 (% class="xobject" %)(((
100 <span class="xobject-title"></span> ## We need this line, because we base our code on dataeditors.js and for now, this class is mandatory
101
102 ; <label#if ($xcontext.action == 'edit') for="${class}_${objNumber}_0_name"#end>$escapetool.xml($doc.displayPrettyName('name', false, false))</label>
103 : $doc.display('name', $obj)
104 ; <label#if ($xcontext.action == 'edit') for="${class}_${objNumber}_0_address"#end>$escapetool.xml($doc.displayPrettyName('address', false, false))</label>
105 : $doc.display('address', $obj)
106
107 #if($xcontext.action == 'edit')
108 <a href="$doc.getURL('objectremove', "form_token=$!{services.csrf.getToken()}&amp;classname=${escapetool.url($class)}&amp;classid=${objNumber}&amp;xredirect=${escapetool.url($doc.getURL('edit'))}")" class="xobject-action delete" title="$services.localization.render('core.editors.object.removeObject.tooltip')">$services.localization.render('core.editors.object.removeObject')</a>
109 #end
110 )))
111 )))
112 #end
113
114 #if($xcontext.action == 'edit')
115 $xwiki.jsfx.use('js/xwiki/editors/dataeditors.js', true)##
116 <a href="$doc.getURL('edit', "xpage=editobject&amp;xaction=addObject&amp;className=$escapetool.url(${class})&amp;xredirect=$escapetool.url(${doc.getURL('edit')})")" class="xobject-add-control button" title="$services.localization.render('core.editors.object.add.label')">$services.localization.render('core.editors.object.add.label')</a>
117 #end
118 )))
119 {{/html}}
120 {{/velocity}}
121 {{/code}}
122
123 == The non-AWM version ==
124
125 Now, let's move outside AWM.
126 If you have an application that was not built with AWM, these are the elements that you need to add in your sheet if you want to enable the option to add / remove objects :
127
128 {{code}}
129 {{velocity}}
130 ## Defining a variable that stores the name of the XClass that is part of MyApp
131 #set($class = 'MyApp.MyClass')
132
133 ## Iterating over all objects of this class
134 #foreach($obj in $doc.getObjects($class))
135
136 ## Container used for detecting objects of a certain class
137 (% id="xwikiobjects" class="xclass" %)(((
138
139 ## Container used for detecting individual objects
140 (% class="xobject" %)(((
141
142 ## We need this element, for now, because it is used by dataeditors.js and you would get JS errors without it
143 (% class="xobject-title" %)
144
145 ## Displaying the properties of the current object
146 $doc.display('my_prop_name', $obj)
147 ...
148
149 ## The DELETE object button, displayed in edit mode
150 #if($xcontext.action == 'edit')
151 {{html}}
152 <a href="$doc.getURL('objectremove', "form_token=$!{services.csrf.getToken()}&amp;classname=${escapetool.url($class)}&amp;classid=${obj.number}&amp;xredirect=${escapetool.url($doc.getURL('edit'))}")" class="xobject-action delete" title="$services.localization.render('core.editors.object.removeObject.tooltip')">$services.localization.render('core.editors.object.removeObject')</a>
153 {{/html}}
154 #end
155 )))
156 )))
157 #end
158
159 #if($xcontext.action == 'edit')
160 ## Adding dataeditors.js to the page
161 $xwiki.jsfx.use('js/xwiki/editors/dataeditors.js', true)##
162
163 ## The ADD object button
164 {{html}}
165 <a href="$doc.getURL('edit', "xpage=editobject&amp;xaction=addObject&amp;className=$escapetool.url(${class})&amp;xredirect=$escapetool.url(${doc.getURL('edit')})")" class="xobject-add-control" title="$services.localization.render('core.editors.object.add.label')">$services.localization.render('core.editors.object.add.label')</a>
166 {{/html}}
167 #end
168 {{/velocity}}
169 {{/code}}

Get Connected