The following code example shows a more complex scenario, where a field for a URL is created that lets the user open a browser window or tab for the linked page with a single click.
The EXML declaration:
<?xml version="1.0" encoding="UTF-8"?> <exml:component xmlns:exml="http://www.jangaroo.net/exml/0.8" xmlns="exml:ext.config" xmlns:editor="exml:com.coremedia.cms.editor.sdk.config" xmlns:ui="exml:com.coremedia.ui.config" baseClass="com.coremedia.ui.examples.propertyField.UrlPropertyFieldBase"> <exml:cfg name="bindTo" type="com.coremedia.ui.data.ValueExpression"> <exml:description> A property path expression leading to the Bean whose property is edited. </exml:description> </exml:cfg> <exml:cfg name="propertyName" type="String"> <exml:description> The property of the Bean to bind in this field. </exml:description> </exml:cfg> <exml:description> A text field that binds to a string property being edited inside of a document form. It allows to open the link target in a new window. </exml:description> <container cls="url-property-wrapper" layout="form"> <items> <!-- The URL is edited in a text field. --> <textfield itemId="urlTextField" name="{'properties.' + config.propertyName}" labelSeparator="" cls="string-property-field"> <plugins> <!-- register the new property editor --> <editor:propertyFieldPlugin propertyName="{config.propertyName}"/> <!-- Generate an appropriate label. --> <editor:setPropertyLabelPlugin bindTo="{config.bindTo}" propertyName="{config.propertyName}"/> <!-- Write back changes even before the user leaves the field. --> <ui:immediateChangeEventsPlugin/> <!-- When the field is empty, an informational message should appear. --> <editor:setPropertyEmptyTextPlugin bindTo="{config.bindTo}" propertyName="{config.propertyName}"/> <!-- Disable the field as appropriate for a content form. --> <editor:bindDisablePlugin bindTo="{config.bindTo}"/> <!-- Bind the content of the field to the given content property. --> <ui:bindPropertyPlugin bindTo="{config.bindTo.extendBy('properties', config.propertyName)}" ifUndefined="" bidirectional="true"/> </plugins> </textfield> <!-- Add a link to the URL displayed in the field. The actual handling is done by the super class. --> <ui:textLink itemId="textLink" text="{PropertyFieldExample_properties.INSTANCE.UrlPropertyField_open_text}" handler="{openFrame}"/> </items> </container> </exml:component>
The base class:
package com.coremedia.ui.examples.propertyField { import com.coremedia.ui.data.ValueExpression; import com.coremedia.ui.examples.propertyField.config.urlPropertyField; import ext.Container; public class UrlPropertyFieldBase extends Container { public function UrlPropertyFieldBase(config:urlPropertyField) { super(config); } /** * A property path expression leading to the Bean whose property is edited. */ public native function get bindTo():ValueExpression; /** * The property of the Bean to bind in this field. */ public native function get propertyName():String; /** * Try to open a new window with the string currently stored in the property used as the URL. */ public function openFrame():void { var url:String = bindTo.extendBy('properties', propertyName).getValue() as String; if (url) { window.open(url, 'externalLinkTarget') } } } }
The above is an example of a compound field, where you need to wrap multiple Ext JS components in a container. This is possible, but you must take care to declare and pass around all configuration properties that need to be set on subcomponents.
There is also some application logic, which is what the base class is for. While you could
technically embed any code into the EXML file itself, it is good practice to separate out
application code in an ActionScript base class. Note how the EXML component references the
method openFrame
from the base class using curly brackets:
<ui:textLink itemId="textLink" text="{PropertyFieldExample_properties. INSTANCE.UrlPropertyField_open_text}" handler="{openFrame}"/>
Example 7.25. Using a base class method