IBM Content Navigator 3.x - 在 AddContentItemDialog 中预填充 ChoiceList 值
IBM Content Navigator 3.x - Pre-filling ChoiceList values in AddContentItemDialog
我们的目标是使用从 PluginService
对象中检索到的值来实现一个预填充的文档创建表单。
当用户右键单击文档并 select "New document from this one" 时,它会触发 Action
打开 AddContentItemDialog
。然后,调用该服务来检索 selected 文档的属性(也许没有必要,通过 Firefox 开发者面板我看到大多数,也许所有自定义属性都已经被获取)。
我可以填充文本字段属性,但不能填充 ChoiceList
的属性:它们不会更新,尽管它们 可能 会在内部填充。
这是一段注释过的代码示例:
require(["dojo/_base/declare",
"dojo/_base/lang",
"dojo/aspect",
"ecm/model/Request",
"ecm/widget/dialog/AddContentItemDialog"],
function(declare, lang, aspect, Request, AddContentItemDialog) {
// Parameters passed to the service as HttpServletRequest
// (Custom function)
var serviceParams = getServicesParams(items[0]);
// Object store and parentFolder retrieving (needed below)
var parentFolder = items[0].parent;
var objectStore = items[0].objectStore;
// Retrieving the template to use for the dialog
// (Custom function)
var entryTemplate = retrieveTemplate(objectStore, parentFolder);
// Service call
Request.invokePluginService("FormPlugin", "FormService", {
requestParams: serviceParams,
requestCompleteCallback: function(response) {
// Creating the global dialog box
var addContentItemDialog = new AddContentItemDialog();
// Box containing the document properties
var addContentItemPropertiesPane =
addContentItemDialog.addContentItemPropertiesPane;
// Box containing general stuff
var addContentItemGeneralPane =
addContentItemDialog.addContentItemGeneralPane;
// Showing the dialog box
addContentItemDialog.show(
repository,
parentFolder, /* parent folder */
true, /* document being added*/
false, /* not virtual */
null, /* no callback function */
null, /* no teamspace */
true, /* use an entry template */
entryTemplate, /* entry template */
true /* can't choose directory from another rep */
);
// Waiting for complete rendering before filling the properties and general fields
aspect.after(addContentItemPropertiesPane,
"onCompleteRendering",
function() {
// Setting the destination and lock it
var folderSelector = addContentItemGeneralPane.folderSelector;
folderSelector.setRoot(parentFolder, objectStore);
folderSelector .setDisabled(true);
// Property filling - Work :-)
addContentItemDialog.setTitle("New document from another");
addContentItemDialog.setIntroText("This form allow you to create a document from another one.");
addContentItemPropertiesPane.setPropertyValue("DocumentTitle", "Prefilled title");
// Property filling - Doesn't work :-(
addContentItemPropertiesPane.setPropertyValue("A_ChoiceList_Prop",
[ "Value\1", "Value\2", "Value\3"]);
}, true);
}
});
});
});
也许我错过了一些神奇的 IBM 代码行来完成它。
已更新。 1) 代码现在可以正确等待条目模板内容的检索。 2) 此答案也适用于以前版本的 ICN。 3)这个答案定义了全局范围内的功能。 要格外小心,您可能会遇到与其他插件和 ICN 代码冲突的名称。 请改用回调函数,或为您的函数命名 "strongly"。
我按照以下步骤编写了插件操作:
- 检索源文档和父文件夹
- 调用插件服务获取被点击文档的属性
- 检索条目模板并使用获取的属性填充其默认值
- 创建一个
AddContentItemDialog
对象并通过将条目模板传递给它来显示它。
条目模板 由 EntryTemplate
对象描述。它有一个引用数组的键 propertiesOptions
。该数组的每个元素代表一个文档 属性。每个元素都包含一个名为 defaultValue
:
的键
EntryTemplate {
addClassDescription: "An Entry Template",
addClassLabel: "An Entry Template",
addClassName: "AnEntryTemplate",
// [...]
propertiesOptions: [
{
dataType: "xs:string",
id: "a_prop",
name: "A Property",
// [...]
defaultValue: "A default value",
// [...]
},
// [...]
],
// [...]
}
字符串值作为(显然)字符串传递,日期作为 ISO8601 格式的字符串(yyyy-MM-ddTHH:mm:ss
)和列表作为数组传递。
例如,给定 n1
、n2
、n3
propertyOption
个条目:
// "xs:string" dataType
entryTemplate.propertiesOptions[n1].defaultValue = "Duck";
// "xs:timestamp" dataType
entryTemplate.propertiesOptions[n2].defaultValue = "1938-04-15T00:00:00";
// "xs:string" dataType, "LIST" cardinality
entryTemplate.propertiesOptions[n3].defaultValue = ["Huey", "Dewey", "Louie"];
下面是 PluginAction 的 Javascript client-side 代码的实现。我没有提供服务实现,也没有提供填充条目模板的代码,因为它有点离题。 (更多关于编写ICN插件的内容,可以参考ICN红皮书Customizing and Extending IBM Content Navigator。)
另请注意,我不认为这个答案是设计动作插件的最佳方式,请不要犹豫建议 optimizations/good 实践相关版本。我只是发现重叠回调函数很痛苦,所以我的目标是在 top-level 定义它们中的大部分,我不喜欢单一的代码。
首先,主要块部分:
require(["dojo/_base/declare",
"dojo/_base/lang",
"dojo/aspect",
"ecm/model/Request",
"ecm/widget/dialog/AddContentItemDialog"],
function(declare, lang, aspect, Request, AddContentItemDialog) {
/**
* Use this function to add any global JavaScript methods your plug-in requires.
*/
lang.setObject("openFilledCreateDocumentFormAction",
function(repository, items, callback, teamspace, resultSet, parameterMap) {
// Parameters passed to the service as HttpServletRequest
var serviceParams = new Object();
serviceParams.server = items[0].repository.id;
serviceParams.serverType = items[0].repository.type;
serviceParams.id = items[0].id;
// Object store and parentFolder retrieving (needed below)
var objectStore = items[0].objectStore;
var parentFolder = items[0].parent;
var entryTemplateClassName = null;
// Service call. "FormService" fetch the source document
// properties, then put them as JSON in the response.
// The response will be passed to the function
// requestCompleteCallback (see below)
Request.invokePluginService(
"FormPlugin",
"FormService", {
requestParams: serviceParams,
// Parameters below are for response callback
etClassName:"AnEntryTemplate",
repository:repository,
objectStore:objectStore,
parentFolder:parentFolder,
AddContentItemDialog:AddContentItemDialog,
aspect:aspect,
requestCompleteCallback: processRetrievalResponse
});
});
});
FormService
完成后调用 processRetrievalResponse()
。在这一篇中,我们将从检索我们想要的模板开始。
function processRetrievalResponse(response) {
// Some data passed to the parent object of this callback (see above)
var etClassName = this.etClassName;
var repository = this.repository;
var objectStore = this.objectStore;
var parentFolder = this.parentFolder;
var AddContentItemDialog = this.AddContentItemDialog;
var aspect = this.aspect;
// First we'll retrieve all the templates
repository.retrieveEntryTemplates(
function (entryTemplates, document_ET_count, folder_ET_count) {
var entryTemplate = null;
// Then we'll search for the one that we want
for (var i = 0; i < entryTemplates.length; i++) {
if (entryTemplates[i] &&
entryTemplates[i].addClassName == etClassName) {
entryTemplate = entryTemplates[i];
break;
}
}
// No Entry Template = abort.
if (!entryTemplate) {
alert("The Entry Template " +
"\"" + etClassName + "\" " +
"was not found. Please contact the administrators");
return;
}
// Now we got the Entry Template, time to retrieve its content
// First, we design a "waiter" object.
// We assume here the PluginService returns the values in
// the "properties" entry of the object response
retrievalWaiter =
new RetrievalWaiter (repository,
objectStore,
parentFolder,
entryTemplate,
response.properties,
AddContentItemDialog,
aspect);
// Then a call to retrieve its content
entryTemplate.retrieveEntryTemplate(null, false, true);
// We ignite the waiter. When the retrieval will be performed,
// It will fill its default values and use it to display
// the creation document dialog.
retrievalWaiter.wait();
}, "Document", parentFolder.id, null, objectStore);
}
RetrievalWaiter
代码。在这里,没有 while
循环,因为它会像恶心一样消耗。
该对象仅依赖于 setTimeOut() 来定期检查条目模板内容的检索。
function RetrievalWaiter(repository, objectStore, parentFolder,
entryTemplate, properties,
AddContentItemDialog, aspect) {
this.repository = repository;
this.objectStore = objectStore;
this.parentFolder = parentFolder;
this.entryTemplate = entryTemplate;
this.properties = properties;
this.aspect = aspect;
this.wait =
function() {
// If the Entry Template is not yet loaded, wait 500 ms
// and recheck
if (!this.entryTemplate.isRetrieved) {
var _this = this;
setTimeout(function() {_this.wait();}, 500);
return;
}
// Fill the Entry Template with defaults value
// (got from the PluginServer response, see above)
fillEntryTemplate(this.entryTemplate, this.properties);
// Show the document creation dialog with the
showDialog(AddContentItemDialog,
this.aspect,
this.repository, this.objectStore,
this.parentFolder, this.entryTemplate);
}
}
现在,该显示对话框了。
function showDialog(AddContentItemDialog, aspect,
repository, objectStore,
parentFolder,
entryTemplate) {
var addContentItemDialog = new AddContentItemDialog();
var addContentItemPropertiesPane =
addContentItemDialog.addContentItemPropertiesPane;
var addContentItemGeneralPane =
addContentItemDialog.addContentItemGeneralPane;
addContentItemDialog.show(
repository,
parentFolder, // parent folder
true, // document being added
false, // not virtual
null, // no callback function
null, // no teamspace
true, // Use an Entry Template
entryTemplate, // Entry template
true // don't allow choosing directory
// from another repository
);
// Use aspect to set the value *after* the complete rendering
// of the properties pane
aspect.after(
addContentItemPropertiesPane,
"onCompleteRendering",
function() {
addContentItemDialog.setTitle("Duplicate a document");
addContentItemDialog.setIntroText(
"This form is loaded from a right-clicked document.");
// Removing the help link to make the form looks like
// the document creation one
addContentItemDialog.setIntroTextRef("","");
// Set parent folder and prevent it from being edited.
addContentItemGeneralPane.folderSelector.setRoot(parentFolder, objectStore);
addContentItemGeneralPane.folderSelector.setDisabled(true);
}, true);
}
// This function relies on the PluginService response.
// It takes the Entry Template, a JSON formatted response
function fillEntryTemplate(entryTemplate, jsonResponse) {
// My mission ends here. :-)
}
我们的目标是使用从 PluginService
对象中检索到的值来实现一个预填充的文档创建表单。
当用户右键单击文档并 select "New document from this one" 时,它会触发 Action
打开 AddContentItemDialog
。然后,调用该服务来检索 selected 文档的属性(也许没有必要,通过 Firefox 开发者面板我看到大多数,也许所有自定义属性都已经被获取)。
我可以填充文本字段属性,但不能填充 ChoiceList
的属性:它们不会更新,尽管它们 可能 会在内部填充。
这是一段注释过的代码示例:
require(["dojo/_base/declare",
"dojo/_base/lang",
"dojo/aspect",
"ecm/model/Request",
"ecm/widget/dialog/AddContentItemDialog"],
function(declare, lang, aspect, Request, AddContentItemDialog) {
// Parameters passed to the service as HttpServletRequest
// (Custom function)
var serviceParams = getServicesParams(items[0]);
// Object store and parentFolder retrieving (needed below)
var parentFolder = items[0].parent;
var objectStore = items[0].objectStore;
// Retrieving the template to use for the dialog
// (Custom function)
var entryTemplate = retrieveTemplate(objectStore, parentFolder);
// Service call
Request.invokePluginService("FormPlugin", "FormService", {
requestParams: serviceParams,
requestCompleteCallback: function(response) {
// Creating the global dialog box
var addContentItemDialog = new AddContentItemDialog();
// Box containing the document properties
var addContentItemPropertiesPane =
addContentItemDialog.addContentItemPropertiesPane;
// Box containing general stuff
var addContentItemGeneralPane =
addContentItemDialog.addContentItemGeneralPane;
// Showing the dialog box
addContentItemDialog.show(
repository,
parentFolder, /* parent folder */
true, /* document being added*/
false, /* not virtual */
null, /* no callback function */
null, /* no teamspace */
true, /* use an entry template */
entryTemplate, /* entry template */
true /* can't choose directory from another rep */
);
// Waiting for complete rendering before filling the properties and general fields
aspect.after(addContentItemPropertiesPane,
"onCompleteRendering",
function() {
// Setting the destination and lock it
var folderSelector = addContentItemGeneralPane.folderSelector;
folderSelector.setRoot(parentFolder, objectStore);
folderSelector .setDisabled(true);
// Property filling - Work :-)
addContentItemDialog.setTitle("New document from another");
addContentItemDialog.setIntroText("This form allow you to create a document from another one.");
addContentItemPropertiesPane.setPropertyValue("DocumentTitle", "Prefilled title");
// Property filling - Doesn't work :-(
addContentItemPropertiesPane.setPropertyValue("A_ChoiceList_Prop",
[ "Value\1", "Value\2", "Value\3"]);
}, true);
}
});
});
});
也许我错过了一些神奇的 IBM 代码行来完成它。
已更新。 1) 代码现在可以正确等待条目模板内容的检索。 2) 此答案也适用于以前版本的 ICN。 3)这个答案定义了全局范围内的功能。 要格外小心,您可能会遇到与其他插件和 ICN 代码冲突的名称。 请改用回调函数,或为您的函数命名 "strongly"。
我按照以下步骤编写了插件操作:
- 检索源文档和父文件夹
- 调用插件服务获取被点击文档的属性
- 检索条目模板并使用获取的属性填充其默认值
- 创建一个
AddContentItemDialog
对象并通过将条目模板传递给它来显示它。
条目模板 由 EntryTemplate
对象描述。它有一个引用数组的键 propertiesOptions
。该数组的每个元素代表一个文档 属性。每个元素都包含一个名为 defaultValue
:
EntryTemplate {
addClassDescription: "An Entry Template",
addClassLabel: "An Entry Template",
addClassName: "AnEntryTemplate",
// [...]
propertiesOptions: [
{
dataType: "xs:string",
id: "a_prop",
name: "A Property",
// [...]
defaultValue: "A default value",
// [...]
},
// [...]
],
// [...]
}
字符串值作为(显然)字符串传递,日期作为 ISO8601 格式的字符串(yyyy-MM-ddTHH:mm:ss
)和列表作为数组传递。
例如,给定 n1
、n2
、n3
propertyOption
个条目:
// "xs:string" dataType
entryTemplate.propertiesOptions[n1].defaultValue = "Duck";
// "xs:timestamp" dataType
entryTemplate.propertiesOptions[n2].defaultValue = "1938-04-15T00:00:00";
// "xs:string" dataType, "LIST" cardinality
entryTemplate.propertiesOptions[n3].defaultValue = ["Huey", "Dewey", "Louie"];
下面是 PluginAction 的 Javascript client-side 代码的实现。我没有提供服务实现,也没有提供填充条目模板的代码,因为它有点离题。 (更多关于编写ICN插件的内容,可以参考ICN红皮书Customizing and Extending IBM Content Navigator。)
另请注意,我不认为这个答案是设计动作插件的最佳方式,请不要犹豫建议 optimizations/good 实践相关版本。我只是发现重叠回调函数很痛苦,所以我的目标是在 top-level 定义它们中的大部分,我不喜欢单一的代码。
首先,主要块部分:
require(["dojo/_base/declare",
"dojo/_base/lang",
"dojo/aspect",
"ecm/model/Request",
"ecm/widget/dialog/AddContentItemDialog"],
function(declare, lang, aspect, Request, AddContentItemDialog) {
/**
* Use this function to add any global JavaScript methods your plug-in requires.
*/
lang.setObject("openFilledCreateDocumentFormAction",
function(repository, items, callback, teamspace, resultSet, parameterMap) {
// Parameters passed to the service as HttpServletRequest
var serviceParams = new Object();
serviceParams.server = items[0].repository.id;
serviceParams.serverType = items[0].repository.type;
serviceParams.id = items[0].id;
// Object store and parentFolder retrieving (needed below)
var objectStore = items[0].objectStore;
var parentFolder = items[0].parent;
var entryTemplateClassName = null;
// Service call. "FormService" fetch the source document
// properties, then put them as JSON in the response.
// The response will be passed to the function
// requestCompleteCallback (see below)
Request.invokePluginService(
"FormPlugin",
"FormService", {
requestParams: serviceParams,
// Parameters below are for response callback
etClassName:"AnEntryTemplate",
repository:repository,
objectStore:objectStore,
parentFolder:parentFolder,
AddContentItemDialog:AddContentItemDialog,
aspect:aspect,
requestCompleteCallback: processRetrievalResponse
});
});
});
FormService
完成后调用 processRetrievalResponse()
。在这一篇中,我们将从检索我们想要的模板开始。
function processRetrievalResponse(response) {
// Some data passed to the parent object of this callback (see above)
var etClassName = this.etClassName;
var repository = this.repository;
var objectStore = this.objectStore;
var parentFolder = this.parentFolder;
var AddContentItemDialog = this.AddContentItemDialog;
var aspect = this.aspect;
// First we'll retrieve all the templates
repository.retrieveEntryTemplates(
function (entryTemplates, document_ET_count, folder_ET_count) {
var entryTemplate = null;
// Then we'll search for the one that we want
for (var i = 0; i < entryTemplates.length; i++) {
if (entryTemplates[i] &&
entryTemplates[i].addClassName == etClassName) {
entryTemplate = entryTemplates[i];
break;
}
}
// No Entry Template = abort.
if (!entryTemplate) {
alert("The Entry Template " +
"\"" + etClassName + "\" " +
"was not found. Please contact the administrators");
return;
}
// Now we got the Entry Template, time to retrieve its content
// First, we design a "waiter" object.
// We assume here the PluginService returns the values in
// the "properties" entry of the object response
retrievalWaiter =
new RetrievalWaiter (repository,
objectStore,
parentFolder,
entryTemplate,
response.properties,
AddContentItemDialog,
aspect);
// Then a call to retrieve its content
entryTemplate.retrieveEntryTemplate(null, false, true);
// We ignite the waiter. When the retrieval will be performed,
// It will fill its default values and use it to display
// the creation document dialog.
retrievalWaiter.wait();
}, "Document", parentFolder.id, null, objectStore);
}
RetrievalWaiter
代码。在这里,没有 while
循环,因为它会像恶心一样消耗。
该对象仅依赖于 setTimeOut() 来定期检查条目模板内容的检索。
function RetrievalWaiter(repository, objectStore, parentFolder,
entryTemplate, properties,
AddContentItemDialog, aspect) {
this.repository = repository;
this.objectStore = objectStore;
this.parentFolder = parentFolder;
this.entryTemplate = entryTemplate;
this.properties = properties;
this.aspect = aspect;
this.wait =
function() {
// If the Entry Template is not yet loaded, wait 500 ms
// and recheck
if (!this.entryTemplate.isRetrieved) {
var _this = this;
setTimeout(function() {_this.wait();}, 500);
return;
}
// Fill the Entry Template with defaults value
// (got from the PluginServer response, see above)
fillEntryTemplate(this.entryTemplate, this.properties);
// Show the document creation dialog with the
showDialog(AddContentItemDialog,
this.aspect,
this.repository, this.objectStore,
this.parentFolder, this.entryTemplate);
}
}
现在,该显示对话框了。
function showDialog(AddContentItemDialog, aspect,
repository, objectStore,
parentFolder,
entryTemplate) {
var addContentItemDialog = new AddContentItemDialog();
var addContentItemPropertiesPane =
addContentItemDialog.addContentItemPropertiesPane;
var addContentItemGeneralPane =
addContentItemDialog.addContentItemGeneralPane;
addContentItemDialog.show(
repository,
parentFolder, // parent folder
true, // document being added
false, // not virtual
null, // no callback function
null, // no teamspace
true, // Use an Entry Template
entryTemplate, // Entry template
true // don't allow choosing directory
// from another repository
);
// Use aspect to set the value *after* the complete rendering
// of the properties pane
aspect.after(
addContentItemPropertiesPane,
"onCompleteRendering",
function() {
addContentItemDialog.setTitle("Duplicate a document");
addContentItemDialog.setIntroText(
"This form is loaded from a right-clicked document.");
// Removing the help link to make the form looks like
// the document creation one
addContentItemDialog.setIntroTextRef("","");
// Set parent folder and prevent it from being edited.
addContentItemGeneralPane.folderSelector.setRoot(parentFolder, objectStore);
addContentItemGeneralPane.folderSelector.setDisabled(true);
}, true);
}
// This function relies on the PluginService response.
// It takes the Entry Template, a JSON formatted response
function fillEntryTemplate(entryTemplate, jsonResponse) {
// My mission ends here. :-)
}