IBM Content Navigator 3.x - Предварительное заполнение значений ChoiceList в AddContentItemDialog

Мы стремимся реализовать предварительно заполненную форму создания документа со значениями, полученными из PluginService объект.

Когда пользователь щелкает правой кнопкой мыши на документе и выбирает "Новый документ из этого", он запускает Action который открывает AddContentItemDialog, Затем служба вызывается для извлечения свойств выбранного документа (может быть, это и не нужно, через панель разработчиков 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 ответ

Решение

Обновлено. 1) Теперь код корректно ожидает получения содержимого шаблона записи. 2) Этот ответ также должен работать с предыдущими версиями ICN. 3) Этот ответ определяет функции в глобальном масштабе. Будьте предельно осторожны, вы можете столкнуться с конфликтным именем с другими плагинами и кодом ICN. Вместо этого используйте функцию обратного вызова или назовите "строго" ваши функции.

Я следовал за этими шагами, чтобы написать Действие Плагина:

  1. Получить исходный документ и родительскую папку
  2. Вызов службы плагинов, которая выбирает свойства выбранного документа.
  3. Получите шаблон ввода и заполните его значения по умолчанию извлеченными свойствами
  4. Создать 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, n3propertyOption записи:

// "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"]; 

Ниже приведена реализация клиентского кода Javascript действия PluginAction. Я не предоставил ни реализацию сервиса, ни код для заполнения шаблона ввода, потому что это немного не по теме. (Для получения дополнительной информации о написании подключаемого модуля ICN вы можете обратиться к разделу Настройка и расширение IBM Redbook IBM Content Navigator.)

Также обратите внимание, что я не считаю этот ответ лучшим способом разработки подключаемого модуля действий, не стесняйтесь предлагать варианты оптимизации / передовой практики. Я просто нашел затруднительным использовать функцию обратного вызова, поэтому я решил определить большинство из них на верхнем уровне, мне не нравится монолитный код.

Во-первых, основная часть блока:

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. :-)
}
Другие вопросы по тегам