4

对于 Alfresco 共享中的表单,我想要一个包含自定义选项的下拉框,具体取决于表单中较早的字段的值。

我的表单至少有两个字段。第一个是文本框,必须在其中输入唯一代码。完成后,第二个,一个选择框,必须使用输入的代码加载它的选项。

支持此要求的数据存储在数据列表中。我还通过 webscript 使其可用(沿着/getOptions/{uniqueCode,返回有效选项的 JSON 数组。

现在,我有点纠结于如何构建表单的一部分,该部分将监视代码文本字段上的状态变化,并重新加载下拉框。我可以想到一些 javascript,但我什至不知道从哪里开始更改/添加文件。

我浏览了FDK,在那里我找到了 selectone ftl。不幸的是,这仅支持固定选项。

我的实现基于我选择的答案

这与我已经在做的非常相似,我希望能够在服务器端做到这一点,而不包括额外的往返。到目前为止,这是我拥有的最好的。

share-config-custom.xml

我在此处定义表单,并将我想成为我的选择项的属性指向我自己的自定义字段模板。ds我向它传递了一个参数dataSource,它保存了我的 webscript 的路径。

<config evaluator="node-type" condition="my:contentType">
      <forms>
         <form>
            <field-visibility>
               <show id="my:code" />
               <show id="my:description" />
            </field-visibility>
            <appearance>
               <set id="general" appearance="bordered-panel" label="General" />
               <field id="my:description" set="general">
                   <control template="/org/alfresco/components/form/controls/customSelectone.ftl">
                       <control-param name="ds">/alfresco/service/mark/cache/options</control-param>
                   </control>
               </field>
            </appearance>
        </form>
    </forms>

customSelectone.ftl

我的自定义 ftl 包含三个主要步骤。首先,它接收我从 share config custom 传递的 ftl 参数,并将其分配给一个局部变量。然后它将一个 html<select>框作为字段放置,最后,它执行对我的 webscript 的调用以获取可能的选项。

范围

<#if field.control.params.ds?exists><#assign ds=field.control.params.ds><#else><#assign ds=''></#if>

html

<style type="text/css">
#${fieldHtmlId}-AutoComplete {
    width:${width}; /* set width here or else widget will expand to fit its container */
    padding-bottom:2em;
}
</style>

<div class="form-field">
   <#-- view form -->
   <#if form.mode == "view">
      <div class="viewmode-field">
         <#if field.mandatory && !(field.value?is_number) && field.value == "">
            <span class="incomplete-warning"><img src="${url.context}/components/form/images/warning-16.png" title="${msg("form.field.incomplete")}" /><span>
         </#if>
         <span class="viewmode-label">${field.label?html}:</span>
         <span class="viewmode-value">${field.value?html}</span>
      </div>
   <#else> 
   <#-- alternative:  if form.mode == "edit" -->
   <#-- Create/edit form -->
      <label for="${fieldHtmlId}">${field.label?html}:<#if field.mandatory><span class="mandatory-indicator">${msg("form.required.fields.marker")}</span></#if></label>
      <div id="${fieldHtmlId}-AutoComplete">
   <#-- Label to hold error messages from the javascript -->
      <p style="color:red" id="${fieldHtmlId}-scriptError"></p>
        <select id="${fieldHtmlId}" name="${field.name}" 
             <#if field.control.params.styleClass?exists>class="${field.control.params.styleClass}"</#if>
             <#if field.description?exists>title="${field.description}"</#if>
             <#if field.control.params.size?exists>size="${field.control.params.size}"</#if> 
             <#if field.disabled>disabled="true"</#if> >
   <#-- Add the field's current value if it has one as an option -->
             <option>${field.value}</option>
             </select>
          <div id="${fieldHtmlId}-Container"></div>       
      </div>
</div>

Javascript

<script type="text/javascript">//<![CDATA[
(function()
{
    <#-- This references the code field from the form model. For this, the -->
    <#-- share config must be set to show the field for this form. -->
    <#if form.fields.prop_my_code??>
        var code = "${form.fields.prop_my_code.value}";
    <#else>
        var code = 0;
    </#if>

    // get code
    if(code === null || code === "") {
        document.getElementById('${fieldHtmlId}-scriptError').innerHTML = 'No description available.';
        return;
    }

    // Create webscript connection using yui connection manager
    // Note that a much more elegant way to call webscripts using Alfresco.util is 
    // available in the answers here.
    var AjaxConnectionManager = {
        handleSuccess:function(o) {
            console.log('response: '+o.responseText);
            this.processResult(o);
        }, 

        handleFailure:function(o) {
            var selectBox = document.getElementById('${fieldHtmlId}');
            var i;

            document.getElementById('${fieldHtmlId}-scriptError').innerHTML = 'Descriptions not available.';
        }, 

        startRequest:function() {
            console.log('webscript call to ${ds} with params code='+code);
            YAHOO.util.Connect.asyncRequest('GET', "${ds}?typecode="+code, callback, null);
        },

        processResult:function(o) {
            var selectBox = document.getElementById('${fieldHtmlId}');
            var jso = JSON.parse(o.responseText);
            var types = jso.types;
            console.log('adding '+types.length+' types to selectbox '+selectBox);
            var i;

            for(i=0;i<types.length;i++) {
                // If the current field's value is equal to this value, don't add it.
                if(types[i] === null || types[i] === '${field.value}') {
                    continue;
                }
                selectBox.add(new Option(types[i], types[i]));
            }
        }
    }

    // Define callback methods
    var callback = {
        success:AjaxConnectionManager.handleSuccess,
        failure:AjaxConnectionManager.handleFailure,
        scope: AjaxConnectionManager
    };

    // Call webscript
    AjaxConnectionManager.startRequest();
})();
//]]></script>
<#-- This closes the form.mode != "create" condition, so the js is only executed when in edit/create mode. -->
</#if>
4

2 回答 2

4

我之前也有类似的任务。首先,您需要在配置 xml 中定义一个自定义模板

<config evaluator="node-type" condition="my:type">
    <forms>
        <form>
            <field-visibility>
                <show id="cm:name" />
                <show id="my:options" />
                <show id="cm:created" />
                <show id="cm:creator" />
                <show id="cm:modified" />
                <show id="cm:modifier" />
            </field-visibility>
            <appearance>
                <field id="my:options">
                    <control template="/org/alfresco/components/form/controls/custom/custom-options.ftl" />
                </field>
            </appearance>
        </form>
    </forms>
</config>

这里发生的是表单引擎将寻找custom-options.ftl渲染my:options类型my:typecustom-options.ftl将包含显示您的数据所需的 html,当然还有对 javascript 类的调用,该类将从您的 webscript 加载您的列表。所以看起来像这样

<#assign controlId = fieldHtmlId + "-cntrl">
<script type="text/javascript">//<![CDATA[
// Here you could call your webscript and load your list
</script>

<div id="${controlId}" class="form-field">
 <label for="${fieldHtmlId}">${msg("form.control.my-options.label")}:<#if field.mandatory><span class="mandatory-indicator">${msg("form.required.fields.marker")}</span></#if></label>
 <select id="${fieldHtmlId}" name="${field.name}" tabindex="0"
       <#if field.description??>title="${field.description}"</#if>
       <#if field.control.params.size??>size="${field.control.params.size}"</#if> 
       <#if field.control.params.styleClass??>class="${field.control.params.styleClass}"</#if>
       <#if field.control.params.style??>style="${field.control.params.style}"</#if>>
 </select>
 <@formLib.renderFieldHelp field=field />
</div>
于 2013-06-25T16:51:32.887 回答
2

您可以像这样调用 webscript:

<script type="text/javascript">//<![CDATA[
    var updateOptions = function(res){
        var result = eval('(' + res.serverResponse.responseText + ')');
        if(result.Options.length > 0 ) { // Options - returned JSON object
            // do something with JSON data
        }
    }

Alfresco.util.Ajax.jsonGet({
    url : Alfresco.constants.PROXY_URI + "/getOptions/{uniqueCode}"+ (new Date().getTime()),
    successCallback : {
        fn : updateOptions,
        scope : this
    },
    failureCallback : {
        fn : function() {},
        scope : this
    }
});
//]]></script>
于 2013-06-27T13:08:20.467 回答