对于Alfresco共享中的表单,我想要一个下拉框,其中填充了自定义选项,具体取决于表单中较早的字段的值。
我的表单至少有两个字段。第一个是文本框,必须输入唯一代码。完成后,第二个选择框必须使用输入的代码加载它的选项。
支持此要求的数据存储在数据列表中。我也通过webscript(/getOptions/{uniqueCode
的行)提供它,返回有效选项的JSON数组。
现在,我对如何构建将在代码文本字段中监视状态更改的表单部分以及重新加载下拉框感到困惑。我可以想到一些javascript,但我甚至不知道从哪里开始更改/添加文件。
我查看了FDK
,在那里我发现了selectone ftl。不幸的是,这仅支持固定选项。
我的实施基于我选择的答案
这与我已经做的非常相似,我原本希望能够在服务器端执行此操作,而不包括额外的往返。到目前为止,这是我所拥有的最好的。
share-config-custom.xml
我在这里定义表单,并将我想要成为我的selectone的属性指向我自己的自定义字段模板。我将参数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>
答案 0 :(得分:4)
<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
的{{1}}。
my:type
将包含显示您的数据所需的html,当然还包含将从您的webscript加载列表的javascript类调用。
所以它看起来像这样
custom-options.ftl
答案 1 :(得分: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>