Guidelines for building Smartlets

Release 1.1 - ...

This article list several requirements and recommendations applicable that should be taken into consideration when building Smartlets.

General

It is important to realize that Smartlets are modular page components that should not influence anything the page outside of its container, unless specifically required (and documented). This implies that the logic (server- and client side) and style rules (CSS) used by the Smartlet should be explicitly bound to the Smartlet itself and not to some generic page elements.

SXML coding

Properties Collection

The Smartlet should have a clear public interface. You'll have to think about which properties will be editable, add description attributes, and set the clientaccess and callbackaccess attributes.

Business logic

All business logic should be contained in the Smartlet item, or in local translations in the smartlet folder, called using translation.localscope.

Keep the Smartlet item as small as possible, and use local translations for business logic units (functions), just like you would do in other programming languages.

Also, try to make the local translations you use self-containing and non-dependent on the main Smartlet item in the containing folder. An easy way to test this is to create preview scenarios for each translation. Such preview scenarios guarantee that the translations function properly and force you to think about the modularity of the solution.

Update (1.3+)

Use sys.eval() to cal translations that may be subclassed.

Scripting and CSS

Create a CMS folder in your Smartlet Root Folder named 'ClientData'. All CSS and JS includes in this folder will automtically be included when one or more instances of your Smartlet live in a page (unless the 'Add to Global Include' flag is set - that is).

CSS

Normally, Smartlet CSS should be connected to the name of the Smartlet, using the smartlet.name() and smartlet.nameselector() methods:

Smartlet code:

Smartsite SXML CopyCode image Copy Code
<div class="{smartlet.name()}" id="{smartlet.id()}">
   Your HTML
</div> 

This ensures that the CSS does not conflict with other style definitions used on the page. When attaching a CSS rule to the Smartlet name, multiple instances of a Smartlet can share the same CSS rules. Those CSS rules can be maintained in CSS items located in the ClientData subfolder.

CSS code:

Smartsite SXML CopyCode image Copy Code
{smartlet.nameselector()} {
  margin: .5em;
  background: url("{smartlet.getresource('/clientdata/images/bg.png')}");
  }

If you need to apply specific style to an instance of a Smartlet, you must use the id of the smartlet. In this case, the rule must be emitted in the Smartlet code itself as inline style elements (use the placeholder techniques for that) and cannot be used from an include file. This is because Smartlet ids are generated dynamically and can therefore not be used from a static include file.

In general, you should avoid in-document CSS, unless the style rules are specifically tied to the value of one or more Smartlet properties, such as an explicitly given width parameter.

Script

Smartlet scripting should be coded as Javascript items in the ClientData folder, unless there is a very good reason not to do so, like the use of standard scripting libraries from third parties.

Use a Behavior tied to the name of the Smartlet, as follows

Script code:

Javascript CopyCode image Copy Code
$j.scf.behavior.add("{smartlet.name(Behavior)}", { 
 attach: function(el, settings, jQ){
   // your code
 }
});

This way, you are safe in terms of avoiding scoping conflicts.

Attach the behavior to the outer element of your Smartlet's html being rendered:

Smartsite SXML CopyCode image Copy Code
{smartlet.behavior.attach(smartlet.name(Behavior))}

This line of SXML code attaches the your behavior to the element with the Smartlet id.

Error handling

To create robust applications, make sure that you add error handling as needed, especially when doing ajax or other calls that have unpredictable outcome.

Localization

Every Smartlet should include localization strings for text used in it. See the web toolkit Smartlets configuration.

Deployment

Smartlets should be self-contained. All elements needed for the Smartlet to work need to be contained in the root folder of the Smartlet.

The best test is to export the complete Smartlet root folder as XML and import it in another site. It should work.

If work needs to be done in order to get the Smartlet to work, it should be contained in the Configuration/Setup subfolder of the Smartlet.

Editor

To make a Smartlet work with the Add/Configure Smartlet addin, the root folder of the Smartlet must render in the current channel, and it needs an Editor item in the Configuration/Editors folder containing a call to the smartlet editor module:

Smartsite SXML CopyCode image Copy Code
<se:smartleteditor/>

If the Smartlet has parameters that require a different input than the defaults defined in Scf/Smartlet Helpers/SmartletEditorDefaultTypes, extra rowformats can be passed in the RowFormats collection parameter. Use the expression attribute to select the field(s) that need special treatment:

Smartsite SXML CopyCode image Copy Code
<se:smartleteditor>
  <se:parameters>
    <se:parameter name="rowformats">
      <se:collection>
        <se:member expression="this.field(name)=='newCommentStatus'">
          <label for="{this.field(name)}">{string.capitalize(this.field(name))}</label>
          <se:xmldatatable save="selectdata" resulttype="datatable">
            <se:row>
              <se:col name="key">ACTIVE</se:col>
              <se:col name="caption">Active</se:col>
            </se:row>
            <se:row><se:col>WAITINGFORAPPROVAL</se:col><se:col>Waiting for approval</se:col></se:row>
            <se:row><se:col>DISAPPROVED</se:col><se:col>Disapproved</se:col></se:row>
            <se:row><se:col>DELETED</se:col><se:col>Deleted</se:col></se:row>
          </se:xmldatatable>
          {smartleteditordropdown($selectdata,this.field(name),this.field(defaultvalue),this.field(type))}<br />
        </se:member>
      </se:collection>
    </se:parameter>
  </se:parameters>
</se:smartleteditor>