Wiki source code of Master Detail Tutorial

Version 12.1 by Vincent Massol on 2015/09/21

Show last authors
1 Explains how to implement a [[master-detail view>>https://en.wikipedia.org/wiki/Master%E2%80%93detail_interface]] in XWiki using [[Applications Within Minutes>>extensions:Extension.App Within Minutes Application]] (AWM) and some custom coding (while waiting for this be [[built in the XWiki product>>http://jira.xwiki.org/browse/XWIKI-12598]]). More specifically we'd like to have an HTML Form with 2 fields and when selecting a value in one field, the values available in the other field automatically update based on the first selection.
2
3 We'll take the example of States and Cities: one field will let the user pick a State and the other field a City.
4
5 {{toc/}}
6
7 = Step 1: Create a State Data Application =
8
9 The first step is to create an application with AWM that will allow to enter some states and cities and to link them. So create an app called "StateData" and when designing the form do as shown in the following screenshot:
10
11 {{image reference="statedata-form.png"/}}
12
13 = Step 2: Add Entries for the State Data Application =
14
15 Now that the State Data Application has been created fill it with 5 entries as shown in the screenshot:
16
17 {{image reference="statedata-entries.png"/}}
18
19 {{info}}
20 Note: XWiki [[currently forces us to give a name to each entry>>http://jira.xwiki.org/browse/XWIKI-7374]] so we have used ##entry1## till ##entry5##.
21 {{/info}}
22
23 = Step 3: Create a State Application =
24
25 Let's now use AWM again to create the State Application which is the application in which we wish to have the master-detail implemented.
26
27 In the design view, start by adding a ##State## field of type ##Database List##:
28
29 {{image reference="state-form1.png"/}}
30
31 Note that we link this field with the ##state## field of the first State Data Application we have created through its ##StateDataCode.StateDataClass##.
32
33 Then add a ##City## field of type ##Static List## with no entries:
34
35 {{image reference="state-form2.png"/}}
36
37 = Step 4: Modify the State Class Sheet =
38
39 Let's now modify ##StateCode.StateSheet## to implement dynamically displaying the City HTML Select. Modify the default content to be:
40
41 {{code}}
42 {{velocity}}
43 {{html wiki="true"}}
44 #set ($discard = $doc.use('StateCode.StateSheet'))
45 #set ($discard = $services.localization.use('document', 'StateCode.StateTranslations'))
46 (% class="xform" %)
47 (((
48 <dl>
49 <dt><label for="StateCode.StateClass_0_state">$escapetool.xml($doc.displayPrettyName('state', false, false))</label></dt>
50 <dd>$doc.display('state')</dd>
51 <dt><label for="StateCode.StateClass_0_city">$escapetool.xml($doc.displayPrettyName('city', false, false))</label></dt>
52 <dd>
53 #if ($xcontext.action == 'edit')
54 $xwiki.jsx.use('StateCode.StateClass')
55 <select id="StateCode.StateClass_0_city" name="StateCode.StateClass_0_city" size="1">
56 <option></option>
57 </select>
58 #else
59 $!doc.getValue('city')
60 #end
61 </dd>
62 </dl>
63 )))
64 {{/html}}
65 {{/velocity}}
66 {{/code}}
67
68 Note that we're using a [[Javascript Skin Extension>>platform:DevGuide.SkinExtensionsTutorial]] that we'll be creating in the current page (i.e. ##StateCode.StateSheet##): {{code}}#set ($discard = $doc.use('StateCode.StateSheet')){{/code}}
69
70 = Step 5: Add a Javascript Skin Extension =
71
72 Edit ##StateCode.StateSheet## in the Object editor and add a ##XWiki.JavaScriptExtension## Object:
73
74 {{image reference="state-jsx.png"/}}
75
76 You can copy-paste this code:
77
78 {{code}}
79 require(['jquery'], function ($) {
80 var stateSelect = $('#StateCode\\.StateClass_0_state');
81 var citySelect = $('#StateCode\\.StateClass_0_city');
82 var jsonDocument = new XWiki.Document('WebHome', 'StateCode.JSON');
83 stateSelect.change(function() {
84 $.get(jsonDocument.getURL('get', 'outputSyntax=plain&state=' + stateSelect.val()), function(json) {
85 var output = '';
86 $.each(json, function(index, value) {
87 output += '<option>' + value + '</option>';
88 });
89 citySelect.empty().append(output);
90 });
91 });
92 });
93 {{/code}}
94
95 Note that we expect an XWiki page named ##StateCode.JSON.WebHome## to return some JSON containing a list of City values for the passed State. We'll add it in the next step.
96
97 {{info}}
98 Instead of creating our own page that returns JSON we could also reuse the Livetable Results Page created by AWM for our State Application. This would avoid having to create a new page and thus skip Step 6. Here's an example URL of how you'd call it and filter on the ##State## field:
99
100 {{code}}
101 var jsonDocument = new XWiki.Document('StateDataLiveTableResults', 'StateDataCode');
102 var url = jsonDocument.getURL('get', 'outputSyntax=plain&classname=StateDataCode.StateDataClass&collist=state%2Ccity&state=' + stateSelect.val())
103 {{/code}}
104 {{/info}}
105
106 = Step 6: Create a JSON Service =
107
108 Create a page named ##StateCode.JSON.WebHome## (just add a page named ##JSON## in the ##StateCode## space in the Create Page UI):
109
110 {{image reference="state-json.png"/}}
111
112 You can copy paste the following as its content:
113
114 {{code}}
115 {{velocity}}
116 #if($xcontext.action == 'get' && "$!{request.outputSyntax}" == 'plain')
117 $response.setContentType('application/json')
118 #end
119 #set($list = [])
120 #set ($state = $request.state)
121 #if ("$!state" != '')
122 #set ($itemList = $services.query.xwql("where doc.object(StateDataCode.StateDataClass).state like :state").bindValue('state', $state).execute())
123 #foreach ($item in $itemList)
124 #set ($itemDoc = $xwiki.getDocument($item))
125 #set ($discard = $list.add($itemDoc.getValue('city')))
126 #end
127 $jsontool.serialize($list)
128 #end
129 {{/velocity}}
130 {{/code}}
131
132 You're all set! Let's now try it!
133
134 = Step 7: Create an entry in the State Application =
135
136 Create an entry and verify that when you change the State, the list of available Cities is updated :)
137
138 {{image reference="state-result1.png"/}}
139
140 And when viewing the page:
141
142 {{image reference="state-result2.png"/}}
143
144 = Step 8: Wrap it all! =
145
146 Here's in attachment a [[XAR file>>attach:state-1.0.xar]] that you can import in your wiki and that contains all the steps of this tutorial.

Get Connected