Toggle navigation
Log-in
Register
Wiki Index
Page Index
User Index
Application Index
Home
About
XWiki's Concept
News & Blog
Roadmap
Releases Notes
References
License
Projects
XWiki
Extensions
Code Snippets
All projects
Documentation
Contribute
Get Involved
Development
Translations
Feedback
Support
FAQs
Community Support
Professional Support
Download
Try
Download
Try now
Home
Projects
XWiki Enterprise
Extensions
All projects
Documentation
Download
Try
Documentation
…
Tutorials & Guides
FAQ Tutorial
Creating a FAQ Application (Manual)
Wiki source code of
Creating a FAQ Application (Manual)
Last modified by
Alex Cotiugă
on 2019/09/20
Copy
Export
Print preview
View Source
Siblings
Content
Attachments (39)
History
Information
×
Export
Office Formats
Export as PDF
Other Formats
Export as HTML
Hide line numbers
1: {{box cssClass="floatinginfobox" title="**Contents**"}} 2: {{toc/}} 3: {{/box}} 4: 5: This tutorial will show you how to build a Frequently Asked Questions (FAQs) [[Application>>platform:Features.Applications]] much like the one you can find on the [[FAQ page>>FAQ.WebHome]]. 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. 6: 7: {{info}} 8: It's also possible to follow this tutorial as a [[video tutorial on Youtube>>https://youtu.be/upQWknV06D4]]. 9: {{/info}} 10: 11: = Prerequisites for following the tutorial = 12: 13: {{warning}} 14: If you've already followed the [[AWM FAQ Tutorial>>Documentation.DevGuide.FAQTutorial.FAQTutorialAWM]] or installed the [[FAQ Application>>extensions:Extension.FAQ Application]] you'll need to do one of 2 things before you can take this tutorial: 15: * Delete the ##FAQ## space (if you've followed the AWM FAQ Tutorial) or uninstall the FAQ Application (if you've installed the FAQ Application) 16: * or simply follow the tutorial below but replace the space ##FAQ## with another value everywhere it's used. For example use ##MyFAQ## as the space name instead. 17: {{/warning}} 18: 19: You should have [[installed XWiki>>platform:AdminGuide.Installation]] and have a [[basic understanding of how to use it>>platform:Features.WebHome]]. 20: 21: 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. 22: 23: {{warning}} 24: 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). 25: {{/warning}} 26: 27: = Application Overview = 28: 29: The FAQ application allows users to post a question by entering the question into a simple form field and then submitting the form. The question then appears in a list along with all other questions that have been previously posted. Users can click on the questions to view both the question and answer in a consistently styled view. If the question has not yet been answered, any user can post an answer to the question by editing the page. In edit mode, the page will display a web form that is the same for every FAQ page. 30: 31: Let us begin by taking a look at what we are going to build. The new application will have the following views: 32: 33: * The FAQ [[Class>>FAQ.WhatIsAClass]] 34: {{image reference="FAQsSummary.png"/}} 35: * An FAQ entry in View mode 36: {{image reference="FAQSheetView.PNG"/}} 37: * An FAQ entry in Edit mode 38: {{image reference="FAQSheetEdit.PNG"/}} 39: 40: = Authoring Templates and Page Design Sheets = 41: 42: An Authoring Template is a template for creating documents of a specific type. Unlike a regular content page in edit mode with one field for freeform editing, an Authoring Template presents a custom set of form fields for creating a document with specific type of data. These form elements are defined by the properties of a class. 43: 44: In object oriented programming, remember that a //class// is a template for an object. Using the analogy of a cookie cutter, the //class// is the //cookie cutter// and the //objects// are the actual //cookies//. An Authoring Template provides one way to represent a class visually so that users can fill out a form to set unique properties (values in form fields). When the user submits the form, they are creating a unique //object// of the //class// type. 45: 46: Precisely, an Authoring Template is a prototype document used to create other specific instances of documents of the same type, along with a method of exposing the creation process to the user: the properties edit form. Remember that a XWiki Document can contain objects and this is the case of an authoring template: it is a XWiki Document with an empty object of a specific class, which is duplicated to create more and more documents based on that model, using the data inserted by the user in the editing form as specific values for the particular object instance in the current copy. 47: 48: The Page Design Sheet is like a style sheet that defines what each document will look like when rendered. Even though the unique object instances will have different values for their properties, they will always have a consistent presentation display because they will be rendered through the Page Design Sheet. The XWiki API available in scripting languages provides a mechanism that will help us use the same sheet for both editing and view modes. We will see how we can achieve this once we get to the FAQ Design Sheet section. 49: 50: = Go to the Class Editor Wizard = 51: 52: Five pages, which collectively make up a [[XClass application>>extensions:Extension.XClass Application]] (a.k.a Class Wizard or Class Editor Wizard), have been developed to assist you in this process. Those page are technical pages hidden by default. To navigate to the wizard home page, go to your profile page, select the Preferences tab, edit the page and choose to view Hidden Documents. Enter a search query for the keyword "XWikiClasses". This should return a document called ##XWikiClasses## in the ##XWiki## space (i.e. ##XWiki.XWikiClasses##). (Note that the //title// of this document is "Data types".) This is the homepage of the class wizard creator: you are now ready to start building your FAQs application. 53: 54: = Create the FAQ Class = 55: 56: * On the Class Editor wizard entry page (XWiki.XWikiClasses), under the heading "Create a new data type", in the "Title" field, enter ##FAQ## as the name of the page to create:((( 57: {{image reference="CreateANewClass1.png"/}} 58: ))) 59: * As you can see in the Breadcrumb below the new page will be created at location ##XWiki > FAQ##. In practice the Class Wizard will automatically prefix the page name with ##Class## (you could also enter ##FAQClass## as the page name directly). 60: * Now it would be nice to have it created in a new location such as ##FAQ > FAQ Class##. Since the ##FAQ## 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 ##FAQ##.((( 61: {{image reference="CreateANewClass2.png"/}} 62: ))) 63: * In technical terms you're creating a page named ##FAQClass## (with a title of "FAQ Class") located in a space also called ##FAQ## and thus the technical reference is ##FAQ.FAQClass##. 64: * Click the "Create this Class" button. You should then see a page with the following content:((( 65: {{code language="none"}} 66: {{velocity}} 67: ## Replace the default space with the space where you want your documents to be created. 68: ## Replace the default parent with the one of your choice and save the document. 69: ## 70: #set($defaultSpace = $doc.space) 71: #set($defaultParent = $doc.fullName) 72: {{/velocity}} 73: {{/code}} 74: ))) 75: 76: In the code, change the word "$doc.space" with the name of the space where you want you FAQ pages to be created as the commented instructions in the page code suggest. 77: The line of code should look like this: 78: 79: {{code language="none"}} 80: #set($defaultSpace = 'FAQ') 81: {{/code}} 82: 83: 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. 84: The line of code should look like this: 85: 86: {{code language="none"}} 87: #set($defaultParent = 'FAQ.WebHome') 88: {{/code}} 89: 90: Click the "Save & View" button. The class is now created and you should be looking at a page titled "Class: FAQ" that looks like this: 91: 92: {{image reference="FAQClass1.PNG"/}} 93: 94: = Add Properties to the Class = 95: 96: 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! 97: 98: * Click on the 'class editor' link 99: * Note that the link trail in the header is something like "Wiki Home / FAQ / FAQ Class". This shows you that you are indeed on the FAQ class page in Class edit mode. 100: 101: In our document, we'll store both a //question// and an //answer//. So we need to create a property for each of them. 102: 103: * Enter the text //question// in the "name" field 104: * Choose a TextArea type for the property and then click on "Add". The TextArea will ultimately give us a multi-line text field in our authoring template.((( 105: {{image reference="AddQuestionProperty.PNG"/}} 106: ))) 107: * Click on the "+" icon to expand the options for the newly created property 108: * Change the value of the "Pretty Name" field to "Question"(capital Q):((( 109: {{image reference="QuestionProperty.PNG"/}} 110: ))) 111: * Now create another property called //answer// the same way that you did for the previous "question" property (choose TextArea for the property type) 112: * Expand it from the property list and change the value of the "Pretty Name" field to "Answer" 113: * When you are done adding and configuring the properties, click the "Save & View" button 114: 115: = Create the Page Design Sheet = 116: 117: * After the previous step you are now on the FAQClass page which should look like this:((( 118: {{image reference="FAQClass2.PNG"/}} 119: ))) 120: * 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. 121: * 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**: 122: ** It adds an object of type ##XWiki.ClassSheetBinding## to the ##FAQ.FAQClass" document. Basically it ties the FAQ Class to the Sheet.## 123: ** **It's because of this object that users will be sent to form edition mode when editing FAQ entries** 124: * 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:((( 125: {{code language="none"}} 126: {{velocity}} 127: ## You can modify this page to customize the presentation of your object. 128: ## At first you should keep the default presentation and just save the document. 129: 130: #set($class = $doc.getObject('FAQ.FAQClass').xWikiClass) 131: #foreach($prop in $class.properties) 132: ; $prop.prettyName 133: : $doc.display($prop.getName()) 134: #end 135: {{/velocity}} 136: {{/code}} 137: )))Let's take a moment now and analyze this code:((( 138: * The first line retrieves the ##FAQ.FAQClass## from the wiki 139: * Then we iterate through all its properties and display their values for the current document in a definition list. 140: 141: As we mentioned, XWiki provides a mechanism that helps us create sheets used for both View and Edit mode. 142: This is the display function used in the line: 143: 144: {{code language="none"}} 145: : $doc.display($prop.getName()) 146: {{/code}} 147: 148: It detects the current mode (Edit or View) and displays the property referenced by its argument as the mode dictates: 149: 150: * In view mode it will display the value of the property 151: * In edit mode it will display a form field that will allow the user to edit it 152: 153: 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. 154: 155: * Click "Save & View" 156: ))) 157: 158: = Create the Authoring Template = 159: 160: * Navigate back to the ##FAQ.FAQClass## document (you can use the arrows in the breadcrumb to do so). The document should look like this:((( 161: {{image reference="FAQClass3.PNG"/}} 162: ))) 163: * Click on the "Create the document template" button. The Authoring Template will be automatically created. 164: 165: 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. 166: 167: Now we need to associate the prototype object with this document to turn it into a true authoring template: 168: 169: * If you're on the template page, navigate back to the ##FAQ.FAQClass## document. 170: * 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 »." 171: * Click on "Add a FAQ object to the template »":((( 172: {{image reference="FAQObject.png"/}} 173: ))) 174: 175: Next, we want to remove the title for the newly created template: 176: 177: * Navigate to the ##FAQ.FAQTemplate## document (you can click on the "View the template page (FAQ / FAQ Template)" link for doing that for example. 178: * Edit this document in Wiki mode 179: * Inside the Title field you have "FAQ Template" written -> delete this text 180: * Save & View 181: 182: This step is needed so that all of our future entries don't have "FAQ Template" as their title. 183: 184: Congratulations: you just created an Authoring Template! You're almost done now. 185: 186: {{image reference="FAQClass4.PNG"/}} 187: 188: = Create the Template Provider = 189: 190: 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. 191: The template provider is created with some default values, but those can be updated to match the needs. 192: 193: {{gallery}} 194: image:3-missingTemplateProvider.png 195: image:4-addedTemplateProvider.png 196: image:5-templateProviderView.png 197: {{/gallery}} 198: 199: 200: = Create a home page for the FAQ application = 201: 202: 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. 203: 204: Thus we now need to create the ##FAQ.WebHome## page 205: 206: * Click on "FAQ" in the breadcrumb to navigate to ##FAQ.WebHome## and notice that the page doesn't exist. 207: * Edit it in wiki mode 208: * Type in the title "FAQs" 209: 210: == Displaying existing FAQ entries == 211: 212: You have 2 options when it comes to displaying existing FAQ entries: 213: 214: 1. Use the livetable component 215: 1. Write custom code in order to display them 216: 217: === Using the Livetable component === 218: 219: In this section, we will show how to use the [[Livetable Macro>>extensions:Extension.Livetable Macro]] to display the existing questions and answers. 220: 221: The livetable component will give users the ability to easily list and filter through existing FAQ documents. The macro is made of 3 parts: 222: 223: * 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 224: * 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 225: * 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) 226: 227: Here is the resulting code: 228: 229: {{code language="none"}} 230: {{velocity}} 231: #set($columns = ["question", "doc.creationDate", "_actions"]) 232: #set($columnsProperties = { 233: "question" : { "type" : "text", "link" : "view", "html" : "true", "sortable":true }, 234: "_actions" : {"actions": ["edit","delete"]} 235: }) 236: #set($options = { 237: "className":"FAQ.FAQClass", 238: "translationPrefix" : "faq.", 239: "tagCloud" : true, 240: "rowCount": 10 241: }) 242: #livetable("faq" $columns $columnsProperties $options) 243: {{/velocity}} 244: {{/code}} 245: 246: * Copy this code and paste it as Wiki content (inside ##FAQ.WebHome##) 247: * Click "Save and View" 248: * New FAQ entries will now be displayed on the page once you create them 249: 250: The ##FAQ.WebHome## page should look similar to this: 251: 252: {{image reference="FAQsLivetable.png"/}} 253: 254: Notice how there are some translation keys displayed inside the livetable. Let's create a translations document and change those keys to actual text: 255: 256: * Create a new page inside the FAQ space called Translations, i.e. at ##FAQ.Translations## (using the "+" button) 257: * Edit it in Wiki mode and paste this content inside:((( 258: {{code language="none"}} 259: faq.question=Question 260: faq.doc.creationDate=Creation Date 261: faq._actions=Actions 262: {{/code}} 263: ))) 264: * Click "Save & View" 265: * 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. 266: * Click "Save & View" again 267: 268: Now the ##FAQ.WebHome## page should look like this (notice the translations instead of the keys): 269: 270: {{image reference="FAQsLivetableWithTranslations.png"/}} 271: 272: === Using custom code === 273: 274: You will need to write the following code: 275: 276: * A XWQL query that will find all your FAQ documents. Check the [[Query API documentation>>extensions:Extension.Query Module]] to know more about it. 277: ** The XWQL query looks for all documents that have a ##FAQ.FAQClass## object other than the template 278: ** If no document has been created yet, a warning message is displayed 279: * A piece of velocity code to display all those documents 280: ** The velocity code loops in that list 281: ** For each item, the full document is loaded in memory so that values can be retrieved from it 282: ** For each document, the question is retrieved and displayed as a link towards the FAQ entry 283: 284: Here is the resulting code: 285: 286: {{code language="none"}} 287: = Existing FAQ entries = 288: 289: {{velocity}} 290: #set($xwql = "from doc.object(FAQ.FAQClass) as faq where doc.fullName <> 'FAQ.FAQTemplate'") 291: #set($results = $services.query.xwql($xwql).execute()) 292: #if($results.empty) 293: No FAQ has been created yet! 294: #else 295: #foreach ($item in $results) 296: #set($faq = $xwiki.getDocument($item)) 297: * [[${faq.display("question").replace("<p>", "").replace("</p>", "")}>>${item}]] 298: #end 299: #end 300: {{/velocity}} 301: {{/code}} 302: 303: * Copy this code and paste it as Wiki content inside ##FAQ.WebHome## 304: * Click "Save and View" 305: * New FAQ entries will now be displayed on the page once you create them 306: 307: The ##FAQ.WebHome## page should look similar to this: 308: 309: {{image reference="FAQsCustomCode.png"/}} 310: 311: == Creating new FAQ entries == 312: 313: There are 2 ways for you to let your users create new FAQ entries: 314: 315: 1. Declare the FAQ as a template 316: 1. Add a custom creation form 317: 318: === Using a Template === 319: 320: You will have to define a template provider [[as explained on this page>>extensions:Extension.Administration Application||anchor="HCreatethetemplateprovider"]] 321: 322: Go to your wiki's administration interface, in the "Templates" section (Administration -> Content -> Templates). Create a new template provider in the 323: ##FAQ## space and name it ##FAQTemplateProvider## 324: 325: You can then use the following values: 326: 327: * Provider name: ##FAQ Template Provider## 328: * Template name: ##New FAQ entry## 329: * Template to use: ##FAQ.FAQTemplate## 330: 331: 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. 332: 333: === Custom creation form === 334: 335: 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: 336: 337: * The first part of the code checks whether the page has a parameter. If so: 338: ** The name of the document that will be created is computed 339: ** A check is done to verify the document doesn't exist yet 340: ** If everything's ok, the user is sent to the new document in inline edition mode 341: * The second part of the code is the actual FAQ creation form 342: ** It builds the name of the document to create it in the ##FAQ## space 343: ** It sets the document parent as being the current document 344: ** It defines the template to use to create the new document 345: 346: {{code language="none"}} 347: {{velocity}} 348: #if("$!request.docName" != '') 349: ## Request for creating a new instance 350: #set($docName = ${request.docName}) 351: #set($targetDocName = "${request.spaceName}.${docName}") 352: #if(!$xwiki.exists($targetDocName) && $xwiki.hasAccessLevel('edit', $xcontext.user, $targetDocName)) 353: $response.sendRedirect($xwiki.getURL($targetDocName, 'inline', "template=${escapetool.url($request.template)}&parent=${escapetool.url($request.parent)}")) 354: ## Stop processing, since we already sent a redirect. 355: #stop 356: #end 357: #end 358: 359: = Add a new question = 360: 361: #if("$!targetDocName" != '' && $xwiki.exists($targetDocName)) 362: {{warning}}The target document already exists. Please choose a different name, or [[view the existing document>>$targetDocName]]{{/warning}} 363: #elseif("$!targetDocName" != '') 364: {{warning}}You don't have permission to create that document{{/warning}} 365: #end 366: 367: {{html}} 368: <form action="" id="newdoc" method="post"> 369: <div> 370: <input type="hidden" name="parent" value="${doc.fullName}"/> 371: <input type="hidden" name="template" value="FAQ.FAQTemplate"/> 372: <input type="hidden" name="sheet" value="1"/> 373: <input type="hidden" name="spaceName" value="FAQ"/> 374: Document: <input type="text" name="docName" value="Enter your question here" class="withTip" size="50"/> 375: <span class="buttonwrapper"><input type="submit" value="Create this FAQ" class="button"/></span> 376: </div> 377: </form> 378: {{/html}} 379: {{/velocity}} 380: {{/code}} 381: 382: * Copy this code and paste it as Wiki content inside ##FAQ.WebHome##, below the code that's already there 383: * Click "Save and View" 384: * A form to create new FAQ entries is now available on the page:((( 385: {{image reference="FAQsWithForm.png"/}} 386: ))) 387: 388: = Test the Application = 389: 390: Now let's just create a new document in our application to test it out. 391: 392: If you previously chose to use a "Custom creation form" for creating new FAQ entries, follow these steps: 393: 394: * Go to ##FAQ.WebHome## 395: * Below the "Add a new question" header, enter a question (which will also be used as the document title) in the //Document// field 396: * Click //Create this FAQ// 397: * You can then enter your question in longer form using the //Question// field on the template, like this:((( 398: {{image reference="FAQSheetEdit.PNG"/}} 399: ))) 400: * Click //Save & View// and then you will see the newly created document, like this:((( 401: {{image reference="FAQSheetView.PNG"/}} 402: ))) 403: * Go back to the ##FAQ.WebHome## page (you can use the breadcrumbs) to see the list of existing questions((( 404: {{image reference="FAQsWithEntry.png"/}} 405: ))) 406: 407: = Conclusion = 408: 409: 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. 410: 411: 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. 412: 413: 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.
Quick Links
User Guide
Administration Guide
Developer Guide
Navigation