Dialogs are Groovy templates that generate forms by mixing static HTML fragments and Groovy calls to the components responsible for building the UI at runtime. The result is a simple but powerful syntax.

h1. Common parameters {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.CommonParameters}

These following parameters are common and can be used for all input fields.
||*Parameter*||*Type*||*Required*||*Example*||*Description*||
|*jcrPath*|{{string}}|!images/check.gif!|{{jcrPath=/node/exo:title}}|The relative path inside the current node.|
|*mixintype*|{{string}} with the commas (,) character.|!images/error.gif!|{example}{{mixintype=mix:i18n}}{example} {example}{{mixintype=mix:votable,mix:commentable,mix:i18n}}{example}|The list of mixin types you want to initialize when creating the content.|
|*validate*|{{string}} with the comma (,) character|!images/error.gif!|{{validate=empty}}{example} {example}{{validate=empty,name}}{example}{example}{{validate=org.exoplatform.webui.form.validator.StringLengthValidator}}|The list of validators you want to apply to the input. Possible values are: _name, email, number, empty, null, datetime, length_ OR validator classes. To know how to pass parameters to validators, refer [here|#CONTref.InsideWCMTemplates.ContentTypes.How_to_pass_parameters_to_validators]|
|*editable*|{{string}}|!images/error.gif!|{{editable=if-null}}|The input will be editable only if the value of this parameter is {{if-null}} and the value of this input is null or blank.|
|*multiValues*|{{boolean}}|!images/error.gif!|{{multiValues=true}}|Show a multi-valued component if true and must be used only with corresponding multi-valued properties. The default value of this parameter is false.|
|*visible*|{{boolean}}|!images/error.gif!|{{visible=true}}|The input is visible if this value is true.|
|*options*|{{String}} separated by the commas (,) character.}}|!images/error.gif!|A list of parameters which are input while the content templates are initialized.|{{"options=toolbar:CompleteWCM,height:'410px',noSanitization"}} |

{docbook}
<citetitle>
<para xml:id="CONTref.InsideWCMTemplates.ContentTypes.How_to_pass_parameters_to_validators">
<emphasis role="bold">
Pass parameters to validators
</emphasis>
</para>
</citetitle>
{docbook}


* "name" validator:

{code:java}
String[] webContentFieldTitle = ["jcrPath=/node/exo:title", "validate=name", "editable=if-null"];

uicomponent.addTextField("title", webContentFieldTitle) ;
{code}

* "email" validator:

{code:java}
String[] webContentFieldTitle = ["jcrPath=/node/exo:title", "validate=email", "editable=if-null"];

uicomponent.addTextField("title", webContentFieldTitle) ;
{code}

* "number" validator:

{code:java}
String[] webContentFieldTitle = ["jcrPath=/node/exo:title", "validate=number", "editable=if-null"];

uicomponent.addTextField("title", webContentFieldTitle) ;
{code}

* "empty" validator:

{code:java}
String[] webContentFieldTitle = ["jcrPath=/node/exo:title", "validate=empty", "editable=if-null"];

uicomponent.addTextField("title", webContentFieldTitle) ;
{code}

* "null" validator:

{code:java}
String[] webContentFieldTitle = ["jcrPath=/node/exo:title", "validate=null", "editable=if-null"];

uicomponent.addTextField("title", webContentFieldTitle) ;
{code}

* "datetime" validator:

{code:java}
String[] webContentFieldTitle = ["jcrPath=/node/exo:title", "validate=datetime", "editable=if-null"];

uicomponent.addTextField("title", webContentFieldTitle) ;
{code}

* "length" validator:

For a maximum length of 50 characters:

{code:java}
String[] webContentFieldTitle = ["jcrPath=/node/exo:title", "validate=empty,length(50;int)", "editable=if-null"];

uicomponent.addTextField("title", webContentFieldTitle) ;
{code}

For a minimum length of 6 characters and maximum length of 50 characters:

{code:java}
String[] webContentFieldTitle = ["jcrPath=/node/exo:title", "validate=empty,length(6;50;int)", "editable=if-null"];

uicomponent.addTextField("title", webContentFieldTitle) ;
{code}

{docbook}
<para>
<prompt>
    <emphasis role="bold">See also</emphasis>
</prompt>
</para>
{docbook}

* [Text Field|#CONTref.InsideWCMTemplates.ContentTypes.Dialog.TextField]
* [Hidden Field|#CONTref.InsideWCMTemplates.ContentTypes.Dialog.HiddenField]
* [Text Area Field|#CONTref.InsideWCMTemplates.ContentTypes.Dialog.TextAreaField]
* [Rich Text Field|#CONTref.InsideWCMTemplates.ContentTypes.Dialog.RichTextField]
* [Calendar Field|#CONTref.InsideWCMTemplates.ContentTypes.Dialog.CalendarField]
* [Upload Field|#CONTref.InsideWCMTemplates.ContentTypes.Dialog.UploadField]
* [Radio Field|#CONTref.InsideWCMTemplates.ContentTypes.Dialog.RadioField]
* [Select Box Field|#CONTref.InsideWCMTemplates.ContentTypes.Dialog.SelectBoxField]
* [Checkbox Field|#CONTref.InsideWCMTemplates.ContentTypes.Dialog.CheckBoxField]
* [Mixin Field|#CONTref.InsideWCMTemplates.ContentTypes.Dialog.MixinField]
* [Action Field|#CONTref.InsideWCMTemplates.ContentTypes.Dialog.ActionField]

{note}
The _mixintype_ can be used only in the root node field (commonly known as the name field).
{note}

h1. Text Field {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.TextField}
* *Additional parameters* {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.TextField.AdditionParameters}
See also: [Common parameters|#CONTref.InsideWCMTemplates.ContentTypes.Dialog.CommonParameters]
* *Example* {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.TextField.Example}

{code:groovy}
<%
  String[] fieldTitle = ["jcrPath=/node/exo:title", "validate=empty"] ;
  uicomponent.addTextField("title", fieldTitle) ;
%>
{code}

h1. Hidden Field {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.HiddenField}

* *Additional parameters* {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.HiddenField.AdditionParameters}

See also: [Common parameters|#CONTref.InsideWCMTemplates.ContentTypes.Dialog.CommonParameters]

* *Example* {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.HiddenField.Example}

{code:java}
String[] hiddenField5 = ["jcrPath=/node/jcr:content/dc:date", "visible=false"];
  uicomponent.addCalendarField("hiddenInput5", hiddenField5);
{code}
h1. Text Area Field {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.TextAreaField}

* *Additional parameters* {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.TextAreaField.AdditionParameters}

|| *Parameter* || *Type* || *Required* || *Description* || *Example* ||
| *rows* | {{Number}} | !images/error.gif! | The initial text area's number of rows. The value is {{10}} by default. | {{rows=20}} |
| *cols* | {{Number}} | !images/error.gif! | The initial text area's number of cols. The value is {{30}} by default .| {{cols=50}} |

See also: [Common parameters|#CONTref.InsideWCMTemplates.ContentTypes.Dialog.CommonParameters]

* *Example* {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.TextAreaField.Example}

{code:groovy}
<%
  String[] fieldDescription = ["jcrPath=/node/exo:description", "validate=empty"] ;
  uicomponent.addTextAreaField("description", fieldDescription) ;
%>
{code}

h1. Rich Text Field {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.RichTextField}

* *Additional parameters* {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.RichTextField.AdditionParameters}

||*Parameter*||*Type*||*Required*||*Description*||*Example*||
|*options*|{{string}} with the semicolon (;) character|!images/error.gif!|Some options for CKEditor field: toolbar, width and height.|{{options=CompleteWCM;width:'100%';height:'200px';}}|
|*toolbar*|{{string}}|!images/error.gif!|The predefined toolbar for CKEditor. The value can be: {{Default}}, {{Basic}}, {{CompleteWCM}}, {{BasicWCM}}, {{SuperBasicWCM}}.|{{options=CompleteWCM}}|
|*width*|{{string}}|!images/error.gif!|The width of CKEditor. Its value can be the percent of pixel.|{{options=width:'100%'}}|
|*height*|{{string}}|!images/error.gif!|The height of CKEditor. Its value can be the percent of pixel.|{{options=height:'200px'}}|
See also: [Common parameters|#CONTref.InsideWCMTemplates.ContentTypes.Dialog.CommonParameters]

* *Example* {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.RichTextField.Example}

{code:groovy}
<%
  String[] fieldSummary = ["jcrPath=/node/exo:summary", "options=toolbar:CompleteWCM,width:'100%',height:'200px'", "validate=empty"] ;
  uicomponent.addRichtextField("summary", fieldSummary) ;
%>
{code}

h1. Calendar Field {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.CalendarField}

* *Additional parameters* {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.CalendarField.AdditionParameters}
|| *Parameter* || *Type* || *Required* || *Description* || *Example* ||
| *options* | {{string}} | !images/error.gif! | An option for the calendar field: Display time. | {{options=displaytime}} |

See also: [Common parameters|#CONTref.InsideWCMTemplates.ContentTypes.Dialog.CommonParameters]

* *Example* {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.CalendarField.Example}

{code:groovy}
<%
  String[] fieldPublishedDate = ["jcrPath=/node/exo:publishedDate", "options=displaytime", "validate=datetime", "visible=true"] ;
  uicomponent.addCalendarField("publishedDate", fieldPublishedDate) ;
%>
{code}

h1. Upload Field {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.UploadField}

* *Additional parameters* {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.UploadField.AdditionParameters}

See also: [Common parameters|#CONTref.InsideWCMTemplates.ContentTypes.Dialog.CommonParameters]

* *Example* {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.UploadField.Example}

When you create an upload form, you can store an image by two main ways:

* If you want to store the image as a property, use the following code:

{code:groovy}
<%
  String[] fieldMedia = ["jcrPath=/node/exo:image"] ;
  uicomponent.addUploadField("media", fieldMedia) ;
%>
{code}

* If you want to store the image as a node, use the following code:

{code:groovy}
<%
  String[] hiddenField1 = ["jcrPath=/node/exo:image", "nodetype=nt:resource", "visible=false"] ;
  String[] hiddenField2 = ["jcrPath=/node/exo:image/jcr:encoding", "visible=false", "UTF-8"] ;
  String[] hiddenField3 = ["jcrPath=/node/exo:image/jcr:lastModified", "visible=false"] ;
  uicomponent.addHiddenField("hiddenInput1", hiddenField1) ;
  uicomponent.addHiddenField("hiddenInput2", hiddenField2) ;
  uicomponent.addHiddenField("hiddenInput3", hiddenField3) ;

  String[] fieldMedia = ["jcrPath=/node/exo:image"] ;
  uicomponent.addUploadField("media", fieldMedia) ;
%>
{code}

* But, this code is not complete. If you want to display the *upload* field, the image must be blank, otherwise you can display the image and an action enables you to remove it. You can do as follows:

{code:groovy}
<%
	def image = "image";
	// If you're trying to edit the document
	if(uicomponent.isEditing()) {
		def curNode = uicomponent.getNode();
		// If the image existed
		if (curNode.hasNode("exo:image")) {
			def imageNode = curNode.getNode("exo:image") ;
			// If the image existed and available
			if (imageNode.getProperty("jcr:data").getStream().available() > 0 && (uicomponent.findComponentById(image) == null)) {
				def imgSrc = uicomponent.getImage(curNode, "exo:image");
				def actionLink = uicomponent.event("RemoveData", "/exo:image");
				%>
					<div>
						<img src="$imgSrc" width="100px" height="80px"/>
						<a href="$actionLink">
							<img src="/eXoResources/skin/DefaultSkin/background/Blank.gif" alt="" class="ActionIcon Remove16x16Icon"/>
						</a>
					</div>
				<%
			} else {
				String[] fieldImage = ["jcrPath=/node/exo:image/jcr:data"] ;
				uicomponent.addUploadField(image, fieldImage) ;
			}
		} else {
				String[] fieldImage = ["jcrPath=/node/exo:image/jcr:data"] ;
				uicomponent.addUploadField(image, fieldImage) ;
		}
	}  else if(uicomponent.dataRemoved()) {
		String[] fieldImage = ["jcrPath=/node/exo:image/jcr:data"] ;
		uicomponent.addUploadField(image, fieldImage) ;
	} else {
		String[] fieldImage = ["jcrPath=/node/exo:image/jcr:data"] ;
		uicomponent.addUploadField(image, fieldImage) ;
	}
%>
{code}

* To have multiple upload fields, you just add the *multiValues=true* parameter to *fieldProperty* in _dialog1.gtmpl_:
{code:java}
# Multi upload
fieldProperty = ["jcrPath=/node/exo:value", "multiValues=true"];
uicomponent.addUploadField("/node/exo_value", fieldProperty);
{code}
{note}
In this case, you must be sure that the node type definition of the document you are currently editing should allow the document
to have a child node named '_exo\:value_' whose node type is '_nt\:unstructured_'. All uploaded files of this upload component are stored
 in this '_exo\:value_' child node.
{note}

h1. Radio Field {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.RadioField}

* *Additional parameters* {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.RadioField.AdditionParameters}
|| *Parameter* || *Type* || *Required* || *Description* || *Example* ||
| *options* | {{string}} with the comma (,) characters | !images/error.gif! | Some radio values. | {{options=radio1,radio2,radio3}} |
See also: [Common parameters|#CONTref.InsideWCMTemplates.ContentTypes.Dialog.CommonParameters]

* *Example* {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.RadioField.Example}

{code:groovy}
<%
  String[] fieldDeep = ["jcrPath=/node/exo:isDeep", "defaultValues=true", "options=radio1,radio2,radio3"];
  uicomponent.addRadioBoxField("isDeep", fieldDeep);
%>
{code}

h1. Select box Field {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.SelectBoxField}
|| *Parameter* || *Type* || *Required* || *Description* || *Example* ||
| *options* | {{string}} with the comma (,) characters | !images/error.gif! | Some option values. | {{options=option1,option2,option3}} |
See also: [Common parameters|#CONTref.InsideWCMTemplates.ContentTypes.Dialog.CommonParameters]

* *Example* {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.SelectBoxField.Example}

{code:groovy}
<%
  String[] fieldDeep = ["jcrPath=/node/exo:isDeep", "defaultValues=true", "options=checkbox1,checkbox2,checkbox3"];
  uicomponent.addCheckBoxField("isDeep", fieldDeep);
%>
{code}

h1. Checkbox Field {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.CheckBoxField}

* *Additional parameters* {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.CheckBoxField.AdditionParameters}
|| *Parameter* || *Type* || *Required* || *Description* || *Example* ||
| *options* | {{string}} with the comma (,) characters | !images/error.gif! | Some checkbox values. | {{options=checkbox1,checkbox2,checkbox3}} |
See also: [Common parameters|#CONTref.InsideWCMTemplates.ContentTypes.Dialog.CommonParameters]

* *Example* {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.CheckBoxField.Example}

{code:groovy}
<%
  String[] fieldDeep = ["jcrPath=/node/exo:isDeep", "defaultValues=true", "options=checkbox1,checkbox2,checkbox3"];
  uicomponent.addCheckBoxField("isDeep", fieldDeep);
%>
{code}

h1. Mixin Field {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.MixinField}

* *Additional parameters* {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.MixinField.AdditionParameters}

See also: [Common parameters|#CONTref.InsideWCMTemplates.ContentTypes.Dialog.CommonParameters]

* *Example* {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.MixinField.Example}

{code:groovy}
<%
  String[] fieldId = ["jcrPath=/node", "editable=false", "visible=if-not-null"] ;
  uicomponent.addMixinField("id", fieldId) ;
%>
{code}

h1. Action Field {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.ActionField}

* *Additional parameters* {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.ActionField.AdditionParameters}

|| *Parameter* || *Type* || *Required* || *Description* || *Example* ||
| *selectorClass* | {{string}} | !images/check.gif! | The component to display. | {{selectorClass=org.exoplatform.ecm.webui.tree.selectone.UIOneNodePathSelector}} |
| *selectorIcon* | {{string}} | !images/check.gif! | The action icon. | {{selectorIcon=SelectPath24x24Icon}} |

Depending on the {{selectorClass}}, some other parameters can be added.

For example, the component {{org.exoplatform.ecm.webui.tree.selectone.UIOneNodePathSelector}} needs the following parameter:

|| *Parameter* || *Type* || *Required* || *Description* || *Example* ||
| *workspaceField* | {{string}} | !images/error.gif! | The field which enables you to select a workspace. | {{workspaceField=targetWorkspace}} |

The component {{org.exoplatform.ecm.webui.selector.UIPermissionSelector}} does not need any special parameters.

See also: [Common parameters|#CONTref.InsideWCMTemplates.ContentTypes.Dialog.CommonParameters]

* *Example* {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.ActionField.Example}

{code:groovy}
<%
  String[] fieldPath = ["jcrPath=/node/exo:targetPath", "selectorClass=org.exoplatform.ecm.webui.tree.selectone.UIOneNodePathSelector", "workspaceField=targetWorkspace", "selectorIcon=SelectPath24x24Icon"] ;
  uicomponent.addActionField("targetPath", fieldPath)  ;
%>
{code}

h1. Interceptors {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.Interceptors}

To add an interceptor to a dialog, you can use this method {{*uicomponent.addInterceptor(String scriptPath, String type)*}}
|| *Parameters* ||*Type* ||*Description* ||
| *scriptPath* | {{string}} | The relative path to the script file. |
| *type* | {{string}} | The type of interceptor: {{prev}} or {{post}}. |

* *Example* {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.Interceptors.Example}

{code:groovy}
<%
  uicomponent.addInterceptor("ecm-explorer/interceptor/PreNodeSaveInterceptor.groovy", "prev");
%>
{code}

h1. How to add a new ECM template with tabs {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.HowToAddNewECMTemplateWithTabs}

To avoid refreshing the first tab for every action execution, add a new private function to the template with tabs.
In the template, you must insert a new piece of code like the following:

{code:groovy}
private String getDisplayTab(String selectedTab) {
  if ((uicomponent.getSelectedTab() == null && selectedTab.equals("mainWebcontent"))
			|| selectedTab.equals(uicomponent.getSelectedTab())) {
		return "display:block";
	}
	return "display:none";
}

private String getSelectedTab(String selectedTab) {
	if (getDisplayTab(selectedTab).equals("display:block")) {
		return "SelectedTab";
	}
	return "NormalTab";
}
{code}

Changing in every event of *onClick* must be done like the following:

{code:html}
<div class="UITab NormalTabStyle">
  <div class="<%=getSelectedTab("mainWebcontent")%>
    ">
    <div class="LeftTab">
      <div class="RightTab">
        <div class="MiddleTab" onClick="<%=uicomponent.event("ChangeTab", "mainWebcontent")%>"><%=_ctx.appRes("WebContent.dialog.label.MainContent")%></div>
      </div>
    </div>
  </div>
</div>

<div class="UITab NormalTabStyle">
  <div class="<%=getSelectedTab("illustrationWebcontent")%>
    ">
    <div class="LeftTab">
      <div class="RightTab">
        <div class="MiddleTab" onClick="<%=uicomponent.event("ChangeTab", "illustrationWebcontent")%>"><%=_ctx.appRes("WebContent.dialog.label.Illustration")%></div>
      </div>
    </div>
  </div>
</div>

<div class="UITab NormalTabStyle">
  <div class="<%= getSelectedTab("contentCSSWebcontent")%>
    ">
    <div class="LeftTab">
      <div class="RightTab">
        <div class="MiddleTab" onClick="<%=uicomponent.event("ChangeTab", "contentCSSWebcontent")%>"><%=_ctx.appRes("WebContent.dialog.label.Advanced")%></div>
      </div>
    </div>
  </div>
</div>
{code}

Finally, to display the selected tab, simply add it to the style of UITabContent class.

{code:html}
<div class="UITabContent" style="<%=getDisplayTab("mainWebcontent")%>">
{code}

h1. How to prevent XSS attacks {anchor:id=CONTref.InsideWCMTemplates.ContentTypes.Dialog.HowToPreventXSS}
In the content management sytem, its typical feature is enabling JavaScript in a content. This causes the XSS (Cross-site Scripting) attacks to the content displayed in the HTML format.

However, there is no solution to keep JavaScript and to prevent the XSS attacks at the same time, so Content allows you to decide whether
JavaScript is allowed to run on a field of the content template or not by using the {{option}} parameter.

* To allow JavaScript to execute, add "{{options = noSanitization}}" to the dialog template file. Normally, this file is named {{dialog1.gtmpl}}.

* For example: The following code shows how to enable JavaScript in the *Main Content* field of the *Free Layout Wecontent* content:

{code:java}
String [] htmlArguments = ["jcrPath = / node / default.html / JCR: content / JCR: data", "options = toolbar: CompleteWCM, height: '410px ', noSanitization" htmlContent];
{code}

* By default, there is no "{{options = noSanitization}}" parameter in the dialog template file and this helps you prevent the XSS attacks. When end-users input JavaScript into a content, the JavaScript is automatically deleted when the content is saved.

