Version 10.1 by Andy Tripp on 2020/06/10

Hide last authors
Andy Tripp 4.1 1 {{box cssClass="floatinginfobox" title="**Contents**"}}
2 {{toc/}}
3 {{/box}}
Andy Tripp 1.1 4
Andy Tripp 9.1 5 This tutorial will show you how to build a Contact Manager application.  It's very similar to the [[Documentation.DevGuide.Tutorials.FAQTutorial.FAQTutorialManual]] tutorial. The only difference (so far) is that the FAQ tutorial involves a very trivial object: a FAQ object contains just two things: a "question" and an "answer", while this example uses a Person object that has more properties ("name", "age", "sex", etc.) .This is a very simple application that makes use of XWiki's [[classes, properties, and objects>>platform:DevGuide.DataModel||anchor="HXWikiClasses2CObjects2CandProperties"]]. It also uses a technique that you may frequently use as the basis for several different kinds of applications.
Andy Tripp 1.1 6
7 Also, this tutorial explains things a little differently than the FAQ tutorial. If something here doesn't make sense to you, try going through the FAQ tutorial and maybe it will make more sense.
8
Andy Tripp 4.1 9 = Prerequisites for following the tutorial =
Andy Tripp 1.1 10
Andy Tripp 4.1 11 You should have [[installed XWiki>>platform:AdminGuide.Installation]] and have a [[basic understanding of how to use it>>platform:Features.WebHome]].
Andy Tripp 1.1 12
Andy Tripp 4.1 13 All through this tutorial you should refer to the [[XWiki Data Model>>platform:DevGuide.DataModel]] for information on XWiki's data model. You might also use the [[XWiki Scripting Guide>>platform:DevGuide.Scripting]] to get you started with scripting in XWiki and manipulating XWiki objects. In addition, this tutorial will introduce the concepts of Authoring Templates and Page Design Sheets, patterns that you will find particularly useful in creating XWiki applications. Completing this tutorial is a recommended prerequisite for anyone who wants to build custom applications on the XWiki engine. And by "custom application", we mean a huge variety of web applications.
Andy Tripp 1.1 14
Andy Tripp 4.1 15 {{warning}}
16 Make sure that your user is an [[Advanced user>>platform:Features.PageEditing||anchor="HAdvancedMode"]] before following this tutorial since you'll need for example to use the wiki editor (##Wiki > Edit## menu).
17 {{/warning}}
Andy Tripp 1.1 18
Andy Tripp 4.1 19 = Application Overview =
Andy Tripp 1.1 20
Andy Tripp 9.1 21 The Person Manager application will allow users to create a "Person object" by entering data (name, age, sex, etc) into a simple form and then submitting the form. Let's sketch out what roughly what those two pages should look like on a "napkin", using [[Balsamiq>>https://balsamiq.com/]]:
Andy Tripp 1.1 22
Andy Tripp 4.1 23 image:personDialog.PNG
Andy Tripp 1.1 24
Andy Tripp 4.1 25 Our page won't look exactly like that, but the point is that a website user can create a Person by filling out a "form" page like this.
Andy Tripp 1.1 26
Andy Tripp 4.1 27 The Person then appears in a table with all other Person objects that have been previously created. Users can click on the Person in the table to see all the information about the Person. He may also edit that information or delete the Person. The table might look something like this:
Andy Tripp 1.1 28
Andy Tripp 4.1 29 image:personTable.PNG
Andy Tripp 1.1 30
Andy Tripp 4.1 31 When the user clicks on a row in the table, he will get a page that shows the information about the Person, which will look similar to the "Create Person" page, but without the ability to change anything.
Andy Tripp 1.1 32
Andy Tripp 4.1 33 == Objects Overview And Terminology ==
Andy Tripp 1.1 34
Andy Tripp 7.1 35 Next, let's summarize the terminology for "Objects". For full details, see [[Data Model>>https://www.xwiki.org/xwiki/bin/view/Documentation/DevGuide/DataModel/#HXWikiClasses2CObjects2CandProperties]]. There is nothing fancy happening here, but it's important to get our terminology straight.
Andy Tripp 1.1 36
Andy Tripp 9.1 37 A Person is an example of some "Object" or "class". We will use XWiki to define what "properties" are in a "Person" object. For example, we will say that there's a property called "name" of type "String". There's also a property called "age" of type "Number", and an "address" property that's type "TextArea" (a string that can be multiple lines).
Andy Tripp 7.1 38
Andy Tripp 4.1 39 When a user creates a new Person, we call that an "instance" of the "class". So we might say something like "I've created an instance of the Person class, with name 'Joe Smith'". And we would say that our table shows all the instances of the Person class. And instances can not only be created, but also edited or deleted.
Andy Tripp 1.1 40
Andy Tripp 7.1 41 We, the creators of the website, define the "Person" class. We define that once, and we're done. Our users use our website to create, edit, and delete instances of our Person class.
42
Andy Tripp 4.1 43 == Overview Of What We Will Do ==
Andy Tripp 7.1 44
Andy Tripp 4.1 45 In this tutorial, we'll do the following steps:
Andy Tripp 1.1 46
Andy Tripp 9.1 47 * Define our Person class, using the XWiki "Data Types" page.
48 * Specify the properties of our Person class, using the XWiki "Class Editor" page.
Andy Tripp 4.1 49 * Define how a Person instance should be displayed, by creating a "Person Sheet" page.
50 * Create a Template and a Template Provider (whatever they are) for our Person class.
Andy Tripp 7.1 51 * Create a web page that displays a table of people.
Andy Tripp 4.1 52 * Create a web page that displays a Person instance.
Andy Tripp 1.1 53
Andy Tripp 7.1 54 Note that we don't need to define a page for creating or editing a Person, just a page for *displaying* a Person. XWiki will automatically do that for us!
Andy Tripp 1.1 55
Andy Tripp 7.1 56 Once we are done with these steps, our application will be finished. A user of our website can see a page containing the table of Person objects, view the page for an existing person, add a new Person, edit an existing Person, or delete a Person.
Andy Tripp 1.1 57
Andy Tripp 7.1 58 = Go to the Special "Data Types" Page =
Andy Tripp 1.1 59
Andy Tripp 7.1 60 The "Data Types" page is a special XWiki page that lets us define classes like "Person". It'sactually hidden by default. To be "unhide" it, go to your profile page, select the Preferences tab, edit the page and choose to view Hidden Documents.
Andy Tripp 4.1 61
Andy Tripp 9.1 62 To find the "Data Types" page, enter a search query for the keyword "D". This should return a document titled "Data Types".
Andy Tripp 7.1 63
Andy Tripp 4.1 64 = Create the Person Class =
65
Andy Tripp 7.1 66 * On the "Data Types" page, under the heading "Create a new data type", in the "Title" field, enter ##Person## as the name of the page to create:(((
67 {{image reference="personClass.PNG"/}}
Andy Tripp 4.1 68 )))
Andy Tripp 7.1 69 * As you can see in the Breadcrumb below the new page will be created at location ##XWiki > Person##. In practice the "Data Types" page will automatically prefix the page name with ##Class## (you could also enter ##PersonClass## as the page name directly).
70 * Now it would be nice to have it created in a new location such as ##PersonSpace > Person Class##. Since the ##PersonSpace## parent doesn't exist we cannot use the Tree picker button. Thus click the Pencil button as shown in the following image and replace ##XWiki## by ##PersonSpace##.(((
71 {{image reference="personLocation.PNG"/}}
Andy Tripp 4.1 72 )))
Andy Tripp 7.1 73 * In technical terms you're creating a page named ##PersonClass## (with a title of "Person Class") located in a space also called ##PersonSpace## and thus the technical reference is ##PersonSpace.PersonClass##.
Andy Tripp 4.1 74 * Click the "Create this Class" button. You should then see a page with the following content:(((
75 {{code language="none"}}
76 {{velocity}}
77 ## Replace the default space with the space where you want your documents to be created.
78 ## Replace the default parent with the one of your choice and save the document.
79 ##
Andy Tripp 1.1 80 #set($defaultSpace = $doc.space)
81 #set($defaultParent = $doc.fullName)
Andy Tripp 4.1 82 {{/velocity}}
83 {{/code}}
84 )))
Andy Tripp 1.1 85
Andy Tripp 7.1 86 In the code, change the word "$doc.space" with the name of the space where you want your pages to be created: "PersonSpace".
Andy Tripp 1.1 87 The line of code should look like this:
88
Andy Tripp 4.1 89 {{code language="none"}}
Andy Tripp 7.1 90 #set($defaultSpace = 'PersonSpace')
Andy Tripp 4.1 91 {{/code}}
Andy Tripp 1.1 92
93 You can also change the default parent of the new FAQ documents that are going to be created. To do so, replace the "$defaultParent" variable with the name of your document.
94 The line of code should look like this:
95
Andy Tripp 4.1 96 {{code language="none"}}
Andy Tripp 7.1 97 #set($defaultParent = 'PersonSpace.WebHome')
Andy Tripp 4.1 98 {{/code}}
Andy Tripp 1.1 99
Andy Tripp 7.1 100 Click the "Save & View" button. The class is now created and you should be looking at a page titled "Class: Person" that looks like this:
Andy Tripp 1.1 101
Andy Tripp 9.1 102 {{image reference="newPersonClass.PNG"/}}
Andy Tripp 1.1 103
Andy Tripp 4.1 104 = Add Properties to the Class =
Andy Tripp 1.1 105
Andy Tripp 4.1 106 Under the page title, you should see the words "The class does not have any properties yet. You can use the //__class editor__// to define them." Let's just follow those instructions!
Andy Tripp 1.1 107
Andy Tripp 4.1 108 * Click on the 'class editor' link
Andy Tripp 9.1 109 * Note that the link trail in the header is something like "Wiki Home / PersonSpace / Person Class". This shows you that you are indeed on the Person class page in Class edit mode.
Andy Tripp 1.1 110
Andy Tripp 9.1 111 Now, we need to specify all the properties of a Person. Let's have the following properties:
112 |=Name|=Type
113 |name|String
114 |email|EMail
115 |address|TextArea
116 |phone|String
117 |sex|static list
118 |married|Boolean
119 |image|Image
120 |age|Number
121 |relatedPeople|List of Pages
Andy Tripp 1.1 122
Andy Tripp 9.1 123 * Enter the text //name// in the "name" field
124 * Choose a Stringtype for the property and then click on "Add". By using a String type, when a user goes to enter the //name// of a new Person, he will be prompted with a single-line text field.
125 (((
126 {{image reference="name.PNG"/}}
Andy Tripp 4.1 127 )))
128 * Click on the "+" icon to expand the options for the newly created property
Andy Tripp 9.1 129 * Change the value of the "Pretty Name" field to "Name"(capital N). With this done, the user sees the label "Name" rather than "name" when prompted for the name of a Person. This doesn't make a huge difference for this property, but when it comes to the proprty with the name "relatedPeople", it's nice to show the user something a little more friendy like "Related People". Also, you could later decide to change that label to "Similar People" without actually renaming the property (and thereby probably breaking something).
130 * Now repeat this to add each of the properties shown in the table above.
Andy Tripp 4.1 131 * When you are done adding and configuring the properties, click the "Save & View" button
Andy Tripp 1.1 132
Andy Tripp 4.1 133 = Create the Page Design Sheet =
Andy Tripp 1.1 134
Andy Tripp 4.1 135 * After the previous step you are now on the FAQClass page which should look like this:(((
136 {{image reference="FAQClass2.PNG"/}}
137 )))
138 * Click the first button ("Create the document sheet") to create the document sheet (the Page Design Sheet). This sheet determines how your page's objects will be rendered to the user. The document is automatically created.
139 * You should see a warning message with the text "The sheet is not bound to the class so it won't be applied automatically when a page that has an object of this class is displayed". Click the "Bind the sheet to the class" link that appears after the text. **What this does is important**:
140 ** It adds an object of type ##XWiki.ClassSheetBinding## to the ##FAQ.FAQClass" document. Basically it ties the FAQ Class to the Sheet.##
141 ** **It's because of this object that users will be sent to form edition mode when editing FAQ entries**
142 * Now click on "View the sheet document". This takes you to the ##FAQ.FAQSheet## page which you can edit in wiki mode and see its default content:(((
143 {{code language="none"}}
144 {{velocity}}
145 ## You can modify this page to customize the presentation of your object.
146 ## At first you should keep the default presentation and just save the document.
Andy Tripp 1.1 147
Andy Tripp 4.1 148 ## We have to use wiki=true because $doc.display() can produce wiki syntax.
149 {{html wiki="true" clean="false"}}
150 ## Load the JavaScript code required to make the object properties editable in-place.
Andy Tripp 1.1 151 #set ($discard = $xwiki.jsfx.use('uicomponents/edit/editableProperty.js', {
Andy Tripp 4.1 152   'forceSkinAction': true,
153   'language': $xcontext.locale
Andy Tripp 1.1 154 }))
155 #set ($editing = $xcontext.action == 'edit')
Andy Tripp 4.1 156 ## The object to display.
Andy Tripp 1.1 157 #set ($xobject = $doc.getObject('FAQ.FAQClass'))
Andy Tripp 4.1 158 ## The class that describes the object properties.
Andy Tripp 1.1 159 #set ($xclass = $xobject.xWikiClass)
Andy Tripp 4.1 160 ## Make sure the following display* method calls use the right object.
Andy Tripp 1.1 161 #set ($discard = $doc.use($xobject))
Andy Tripp 4.1 162 ## Using the xform vertical form layout.
Andy Tripp 1.1 163 <div class="xform">
Andy Tripp 4.1 164   <dl>
165   #foreach ($property in $xclass.properties)
166     <dt #if (!$editing && $hasEdit)
167         class="editableProperty"
168         #set ($xobjectPropertyReference = $xobject.getProperty($property.name).reference)
169         data-property="$escapetool.xml($services.model.serialize($xobjectPropertyReference))"
170         data-property-type="object"#end>
171       ## This must match the id generated by the $doc.display() method below.
172       #set ($propertyId = "${xclass.name}_${xobject.number}_$property.name")
173       <label#if ($editing) for="$escapetool.xml($propertyId)"#end>
174         $escapetool.xml($property.translatedPrettyName)
175       </label>
176       ## Support for specifying a translation key as hint in the property definition.
177       <span class="xHint">$!escapetool.xml($services.localization.render($property.hint))</span>
178     </dt>
179     <dd>$doc.display($property.name)</dd>
180   #end
181   #if (!$xclass.properties || $xclass.properties.size() == 0)
182     ## Keep the empty definition term in order to have valid HTML.
183     <dt></dt>
184     <dd>$escapetool.xml($services.localization.render('xclass.defaultObjectSheet.noProperties'))</dd>
185   #end
186   </dl>
Andy Tripp 1.1 187 </div>
Andy Tripp 4.1 188 {{/html}}
189 {{/velocity}}
190 {{/code}}
Andy Tripp 1.1 191
192 Let's take a moment now and analyze this code:
193
Andy Tripp 4.1 194 * first, it loads the JavaScript required for in-place editing
195 * then it retrieves the FAQ object from the current page and the FAQ class defintion
196 * then it iterates through all the FAQ class properties displaying:
197 ** the translated pretty name
198 ** the translated hint
199 ** the value from the FAQ object in view mode, or the form field used to input or modify the value in edit mode
200 * it uses a definition list to display the FAQ object, following the [[Vertical Form>>xwiki:Documentation.DevGuide.FrontendResources.VerticalForms.WebHome]] layout
Andy Tripp 1.1 201
Andy Tripp 4.1 202 As we mentioned, XWiki provides a mechanism that helps us create sheets used for both view and edit mode. This is the ##display## function used in the line:
Andy Tripp 1.1 203
Andy Tripp 4.1 204 {{code language="none"}}
Andy Tripp 1.1 205 <dd>$doc.display($property.name)</dd>
Andy Tripp 4.1 206 {{/code}}
Andy Tripp 1.1 207
208 It detects the current mode (edit or view) and displays the property referenced by its argument as the mode dictates:
209
Andy Tripp 4.1 210 * in view mode it will display the value of the property
211 * in edit mode it will display a form field that will allow the user to edit it
Andy Tripp 1.1 212
Andy Tripp 4.1 213 This way we can use a single Design Sheet to both display and edit our FAQ entries. See the [[XWiki API reference>>platform:DevGuide.API]] and [[XWiki Scripting>>platform:DevGuide.Scripting]] pages for more details about this.
214 )))
215 * Click "Save & View"
Andy Tripp 1.1 216
Andy Tripp 4.1 217 = Create the Authoring Template =
Andy Tripp 1.1 218
Andy Tripp 4.1 219 * Navigate back to the ##FAQ.FAQClass## document (you can use the arrows in the breadcrumb to do so). The document should look like this:(((
220 {{image reference="FAQClass3.PNG"/}}
221 )))
222 * Click on the "Create the document template" button. The Authoring Template will be automatically created.
Andy Tripp 1.1 223
Andy Tripp 4.1 224 Note that earlier, we changed the space name preceding the page name because we wanted all of our FAQ pages to reside in a space named FAQ. Remember that all our documents will be copies of the Authoring Template used as a prototype so the content will be copied in all our FAQs documents and will execute the Design Sheet code in the context of the current document. See the [[dedicated page>>platform:DevGuide.IncludeInVelocity]] for more information regarding this technique.
Andy Tripp 1.1 225
226 Now we need to associate the prototype object with this document to turn it into a true authoring template:
227
Andy Tripp 4.1 228 * If you're on the template page, navigate back to the ##FAQ.FAQClass## document.
229 * At the bottom of the page, look for the following warning message: "The template does not contain an object of type FAQClass. Add a FAQ object to the template »."
230 * Click on "Add a FAQ object to the template »":(((
231 {{image reference="FAQObject.png"/}}
232 )))
Andy Tripp 1.1 233
234 Next, we want to remove the title for the newly created template:
235
Andy Tripp 4.1 236 * Navigate to the ##FAQ.FAQTemplate## document (you can click on the "View the template page (FAQ / FAQ Template)" link for doing that for example.
237 * Edit this document in Wiki mode
238 * Inside the Title field you have "FAQ Template" written -> delete this text
239 * Save & View
Andy Tripp 1.1 240
241 This step is needed so that all of our future entries don't have "FAQ Template" as their title.
242
243 Congratulations: you just created an Authoring Template! You're almost done now.
244
Andy Tripp 4.1 245 {{image reference="FAQClass4.PNG"/}}
Andy Tripp 1.1 246
Andy Tripp 4.1 247 = Create the Template Provider =
Andy Tripp 1.1 248
249 After the template was created and the object was added, a new section appears with a button to create a template provider to use the existing template.
250 The template provider is created with some default values, but those can be updated to match the needs.
251
Andy Tripp 4.1 252 {{gallery}}
253 image:3-missingTemplateProvider.png
254 image:4-addedTemplateProvider.png
255 image:5-templateProviderView.png
256 {{/gallery}}
Andy Tripp 1.1 257
258
259
Andy Tripp 4.1 260 = Create a home page for the FAQ application =
261
Andy Tripp 1.1 262 You want your users to be able to see a list of all existing questions and answers and to add new questions. The best way to do this is to put the FAQ application in its own space and to use that space's homepage to display existing questions.
263
Andy Tripp 4.1 264 Thus we now need to create the ##FAQ.WebHome## page
Andy Tripp 1.1 265
Andy Tripp 4.1 266 * Click on "FAQ" in the breadcrumb to navigate to ##FAQ.WebHome## and notice that the page doesn't exist.
267 * Edit it in wiki mode
268 * Type in the title "FAQs"
Andy Tripp 1.1 269
Andy Tripp 4.1 270 == Displaying existing FAQ entries ==
Andy Tripp 1.1 271
272 You have 2 options when it comes to displaying existing FAQ entries:
273
Andy Tripp 4.1 274 1. Use the livetable component
275 1. Write custom code in order to display them
Andy Tripp 1.1 276
Andy Tripp 4.1 277 === Using the Livetable component ===
Andy Tripp 1.1 278
Andy Tripp 4.1 279 In this section, we will show how to use the [[Livetable Macro>>extensions:Extension.Livetable Macro]] to display the existing questions and answers.
Andy Tripp 1.1 280
281 The livetable component will give users the ability to easily list and filter through existing FAQ documents. The macro is made of 3 parts:
282
Andy Tripp 4.1 283 * The list of columns: for each entry, we will display the question, the date when it was created and a special column that lets users quickly modify entries
284 * The properties of each column: for each column, we will define how it should be displayed, whether it should link to the entry and whether it should be filterable
285 * The livetable options: those are options related to the display of the livetable (in this case we will to display a tag cloud and 10 rows by default)
Andy Tripp 1.1 286
287 Here is the resulting code:
288
Andy Tripp 4.1 289 {{code language="none"}}
290 {{velocity}}
Andy Tripp 1.1 291 #set($columns = ["question", "doc.creationDate", "_actions"])
292 #set($columnsProperties = {
Andy Tripp 4.1 293     "question" : { "type" : "text", "link" : "view", "html" : "true", "sortable":true },
294     "_actions" : {"actions": ["edit","delete"]}
Andy Tripp 1.1 295 })
296 #set($options = {
Andy Tripp 4.1 297    "className":"FAQ.FAQClass",
298    "translationPrefix" : "faq.",
299    "tagCloud" : true,
300    "rowCount": 10
Andy Tripp 1.1 301 })
302 #livetable("faq" $columns $columnsProperties $options)
Andy Tripp 4.1 303 {{/velocity}}
304 {{/code}}
Andy Tripp 1.1 305
Andy Tripp 4.1 306 * Copy this code and paste it as Wiki content (inside ##FAQ.WebHome##)
307 * Click "Save and View"
308 * New FAQ entries will now be displayed on the page once you create them
Andy Tripp 1.1 309
Andy Tripp 4.1 310 The ##FAQ.WebHome## page should look similar to this:
Andy Tripp 1.1 311
Andy Tripp 4.1 312 {{image reference="FAQsLivetable.png"/}}
Andy Tripp 1.1 313
314 Notice how there are some translation keys displayed inside the livetable. Let's create a translations document and change those keys to actual text:
315
Andy Tripp 4.1 316 * Create a new page inside the FAQ space called Translations, i.e. at ##FAQ.Translations## (using the "+" button)
317 * Edit it in Wiki mode and paste this content inside:(((
318 {{code language="none"}}
Andy Tripp 1.1 319 faq.question=Question
320 faq.doc.creationDate=Creation Date
321 faq._actions=Actions
Andy Tripp 4.1 322 {{/code}}
323 )))
324 * Click "Save & View"
325 * Edit it again in Object mode and add a new ##XWiki.TranslationDocumentClass## object to mark the page as a page containing translations. Make sure to select the right scope. Using "Global" means the translations would be visible to all wikis (and it requires having Programming Rights!) and "Wiki" means it's visible to the current wiki only. Choose "Wiki" as the scope.
326 * Click "Save & View" again
Andy Tripp 1.1 327
Andy Tripp 4.1 328 Now the ##FAQ.WebHome## page should look like this (notice the translations instead of the keys):
Andy Tripp 1.1 329
Andy Tripp 4.1 330 {{image reference="FAQsLivetableWithTranslations.png"/}}
Andy Tripp 1.1 331
Andy Tripp 4.1 332 === Using custom code ===
Andy Tripp 1.1 333
334 You will need to write the following code:
335
Andy Tripp 4.1 336 * A XWQL query that will find all your FAQ documents. Check the [[Query API documentation>>extensions:Extension.Query Module]] to know more about it.
337 ** The XWQL query looks for all documents that have a ##FAQ.FAQClass## object other than the template
338 ** If no document has been created yet, a warning message is displayed
339 * A piece of velocity code to display all those documents
340 ** The velocity code loops in that list
341 ** For each item, the full document is loaded in memory so that values can be retrieved from it
342 ** For each document, the question is retrieved and displayed as a link towards the FAQ entry
Andy Tripp 1.1 343
344 Here is the resulting code:
345
Andy Tripp 4.1 346 {{code language="none"}}
347 = Existing FAQ entries =
Andy Tripp 1.1 348
Andy Tripp 4.1 349 {{velocity}}
Andy Tripp 1.1 350 #set($xwql = "from doc.object(FAQ.FAQClass) as faq where doc.fullName <> 'FAQ.FAQTemplate'")
351 #set($results = $services.query.xwql($xwql).execute())
352 #if($results.empty)
Andy Tripp 4.1 353   No FAQ has been created yet!
Andy Tripp 1.1 354 #else
Andy Tripp 4.1 355   #foreach ($item in $results)
356     #set($faq = $xwiki.getDocument($item))
357     * [[${faq.display("question").replace("<p>", "").replace("</p>", "")}>>${item}]]
358   #end
Andy Tripp 1.1 359 #end
Andy Tripp 4.1 360 {{/velocity}}
361 {{/code}}
Andy Tripp 1.1 362
Andy Tripp 4.1 363 * Copy this code and paste it as Wiki content inside ##FAQ.WebHome##
364 * Click "Save and View"
365 * New FAQ entries will now be displayed on the page once you create them
Andy Tripp 1.1 366
Andy Tripp 4.1 367 The ##FAQ.WebHome## page should look similar to this:
Andy Tripp 1.1 368
Andy Tripp 4.1 369 {{image reference="FAQsCustomCode.png"/}}
Andy Tripp 1.1 370
Andy Tripp 4.1 371 == Creating new FAQ entries ==
Andy Tripp 1.1 372
373 There are 2 ways for you to let your users create new FAQ entries:
374
Andy Tripp 4.1 375 1. Declare the FAQ as a template
376 1. Add a custom creation form
Andy Tripp 1.1 377
Andy Tripp 4.1 378 === Using a Template ===
Andy Tripp 1.1 379
Andy Tripp 4.1 380 You will have to define a template provider [[as explained on this page>>extensions:Extension.Administration Application||anchor="HCreatethetemplateprovider"]]
Andy Tripp 1.1 381
382 Go to your wiki's administration interface, in the "Templates" section (Administration -> Content -> Templates). Create a new template provider in the
Andy Tripp 4.1 383 ##FAQ## space and name it ##FAQTemplateProvider##
Andy Tripp 1.1 384
385 You can then use the following values:
386
Andy Tripp 4.1 387 * Provider name: ##FAQ Template Provider##
388 * Template name: ##New FAQ entry##
389 * Template to use: ##FAQ.FAQTemplate##
Andy Tripp 1.1 390
Andy Tripp 4.1 391 If you'd like, you can restrict FAQ entries so that they're created only in the ##FAQ## space. Once you're done, click "Save & View". Your template is now ready to be used! Users who click on the "Add >> Page" button will now have the option to create a new page using the FAQ template.
Andy Tripp 1.1 392
Andy Tripp 4.1 393 === Custom creation form ===
Andy Tripp 1.1 394
395 If you choose this option, you will need to write some code to let your users create new FAQ entries. To do this, you will have to create a form in which the user can enter the name of the questions she wants to create. Once typed in, the form calls the same page to trigger the new document creation based on the parameters entered by the user:
396
Andy Tripp 4.1 397 * The first part of the code checks whether the page has a parameter. If so:
398 ** The name of the document that will be created is computed
399 ** A check is done to verify the document doesn't exist yet
400 ** If everything's ok, the user is sent to the new document in inline edition mode
401 * The second part of the code is the actual FAQ creation form
402 ** It builds the name of the document to create it in the ##FAQ## space
403 ** It sets the document parent as being the current document
404 ** It defines the template to use to create the new document
Andy Tripp 1.1 405
Andy Tripp 4.1 406 {{code language="none"}}
407 {{velocity}}
Andy Tripp 1.1 408 #if("$!request.docName" != '')
Andy Tripp 4.1 409   ## Request for creating a new instance
410   #set($docName = ${request.docName})
411   #set($targetDocName = "${request.spaceName}.${docName}")
412   #if(!$xwiki.exists($targetDocName) && $xwiki.hasAccessLevel('edit', $xcontext.user, $targetDocName))
413     $response.sendRedirect($xwiki.getURL($targetDocName, 'inline', "template=${escapetool.url($request.template)}&parent=${escapetool.url($request.parent)}"))
414     ## Stop processing, since we already sent a redirect.
415     #stop
416   #end
Andy Tripp 1.1 417 #end
418
Andy Tripp 4.1 419 = Add a new question =
Andy Tripp 1.1 420
421 #if("$!targetDocName" != '' && $xwiki.exists($targetDocName))
Andy Tripp 4.1 422   {{warning}}The target document already exists. Please choose a different name, or [[view the existing document>>$targetDocName]]{{/warning}}
Andy Tripp 1.1 423 #elseif("$!targetDocName" != '')
Andy Tripp 4.1 424   {{warning}}You don't have permission to create that document{{/warning}}
Andy Tripp 1.1 425 #end
426
Andy Tripp 4.1 427 {{html}}
428   <form action="" id="newdoc" method="post">
429     <div>
430       <input type="hidden" name="parent" value="${doc.fullName}"/>
431       <input type="hidden" name="template" value="FAQ.FAQTemplate"/>
432       <input type="hidden" name="sheet" value="1"/>
433       <input type="hidden" name="spaceName" value="FAQ"/>
434       Document: <input type="text" name="docName" value="Enter your question here" class="withTip" size="50"/>
435       <span class="buttonwrapper"><input type="submit" value="Create this FAQ" class="button"/></span>
436     </div>
437   </form>
438 {{/html}}
439 {{/velocity}}
440 {{/code}}
Andy Tripp 1.1 441
Andy Tripp 4.1 442 * Copy this code and paste it as Wiki content inside ##FAQ.WebHome##, below the code that's already there
443 * Click "Save and View"
444 * A form to create new FAQ entries is now available on the page:(((
445 {{image reference="FAQsWithForm.png"/}}
446 )))
Andy Tripp 1.1 447
Andy Tripp 4.1 448 = Test the Application =
Andy Tripp 1.1 449
450 Now let's just create a new document in our application to test it out.
451
452 If you previously chose to use a "Custom creation form" for creating new FAQ entries, follow these steps:
453
Andy Tripp 4.1 454 * Go to ##FAQ.WebHome##
455 * Below the "Add a new question" header, enter a question (which will also be used as the document title) in the //Document// field
456 * Click //Create this FAQ//
457 * You can then enter your question in longer form using the //Question// field on the template, like this:(((
458 {{image reference="FAQSheetEdit.PNG"/}}
459 )))
460 * Click //Save & View// and then you will see the newly created document, like this:(((
461 {{image reference="FAQSheetView.PNG"/}}
462 )))
463 * Go back to the ##FAQ.WebHome## page (you can use the breadcrumbs) to see the list of existing questions(((
464 {{image reference="FAQsWithEntry.png"/}}
465 )))
Andy Tripp 1.1 466
Andy Tripp 4.1 467 = Conclusion =
Andy Tripp 1.1 468
469 This tutorial has taught you how to use the Class Wizard app and it has detailed the concepts of classes, objects and properties and introduced the authoring templates and page design sheets.
470
471 You may also have learned a little bit about Velocity scripting in documents. You can use these basic concepts to build custom applications at the document or presentation layer of XWiki without having to compile or deploy code.
472
473 As always, please take the time to make this document better for other users if you find ways that it can be improved as you read it for the first time.

Get Connected