Five New Optimizely Certifications are Here! Validate your expertise and advance your career with our latest certification exams. Click here to find out more
Five New Optimizely Certifications are Here! Validate your expertise and advance your career with our latest certification exams. Click here to find out more
EPiServer page editing is based on the Dojo client JavaScript toolkit. Each property or block that you edit consists of one or more widgets. A widget is a Dojo JavaScript class creates a user interface. Widget methods are used by the wrapper that displays the widget.
NOTE: You can add properties for a particular widget by using a PropertyEditorDescriptor.
The following example shows the basic structure of a widget class and creates a simple widget for entering a valid email address. To create a widget for a dialog editor, you must inherit from the dijit._widget class.
JavaScript
define("acme.widget.EmailTextbox", [ "dojo/_base/declare", "dijit/_Widget", "dijit/_TemplatedMixin" ], function ( declare, _Widget, _TemplatedMixin) { declare("acme.widget.EmailTextbox", [_Widget, _TemplatedMixin], { // templateString: [protected] String // A string that represents the default widget template. templateString: '<div> \ <input type="email" data-dojo-attach-point="email" data-dojo-attach-event="onchange:_onChange" /> \ </div>' }) });
When you create this widget, the initial value is passed in as a constructor argument with the property name value, which is automatically mixed into the widget by the constructor in the dijit._widget class. To make sure you update the value in the text box when it is set on the widget, declare a _setValueAttr method, which is called with set('value', value).
postCreate: function () { // summary: // Set the value to the textbox after the DOM fragment is created. // tags: // protected this.set('value', this.value); if (this.intermediateChanges) { this.connect(this.email, 'onkeydown', this._onIntermediateChange); this.connect(this.email, 'onkeyup', this._onIntermediateChange); } }, _setValueAttr: function (value) { // summary: // Sets the value of the widget to "value" and updates the value displayed in the textbox. // tags: // private this._set('value', value); this.email.value = this.value || ''; }
This example adds a postCreate method to pass the value to set, which ensures the widget updates correctly with the initial value (because the widget constructor uses a mixin which does not call set).
The set method also references a variable named email, which is the textbox DOM node; it is automatically assigned to this variable name by the dijit._Templated class when it parses the data-dojo-attach-point in the template code.
When you need to populate the changes made in the widget, call the onChange method and pass a new value to it. You should call onChange as often as necessary during editing to provide an accurate preview of changes.
_onChange: function (event) { // summary: // Handles the textbox change event and populates this to the onChange method. // tags: // private this._set('value', event.target.value); this.onChange(this.value); }
The _onChange method is a private event handler that is triggered when a change is made on the text box. It is configured in the template using the data-dojo-attach-event syntax. After it updates the value it calls the onChange method which in turn causes a page to update.
The following example shows how to update the UI when a user types in it. In the postCreate method, connect to the onKeyDown and onKeyUp events on the text box element if the intermediateChanges property is set to true.
_onIntermediateChange: function (event) { // summary: // Handles the textbox key press events event and populates this to the onChange method. // tags: // private if (this.intermediateChanges) { this._set('value', event.target.value); this.onChange(this.value); } }
You also can control where you set the focus when the control loads by implementing the focus method.
focus: function () { // summary: // Put focus on this widget. // tags: // public dijit.focus(this.email); }
To support validation the widget must implement the isValid method.
The constraints for a property are mixed into the widget when it is constructed. For example, if the value has the required checkbox selected in admin mode then that is passed through as the property required.
isValid: function () { // summary: // Indicates whether the current value is valid. // tags: // public var emailRegex = '[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+'; if (!this.required) { emailRegex = '(' + emailRegex + ')?'; } var regex = newRegExp('^' + emailRegex + '$'); return regex.test(this.value); }
If your widget needs to launch a dialog box of its own, extend an additional class with epi.cms.widget._HasChildDialogMixin, and set a few property values in the correct place to ensure that the blur event, (going from the main dialog box to the new one), does not close the main dialog box. The class provides one additional property called isShowingChildDialog, which is used in the blur event of the main dialog to determine whether it should hide itself. Therefore, if you want to prevent hiding of the main dialog box when the widget launches a child dialog box, set the value to true before launching the child dialog box, then set it back to false after the child dialog box closes.
_showChildDialog: function () { var dialog = dijit.Dialog({ title: 'Child Dialog' }); this.connect(dialog, 'onHide', this._onHide); this.isShowingChildDialog = true; dialog.show(); }, _onHide: function () { this.isShowingChildDialog = false; }
Last updated: Feb 23, 2015