Last Updated: February 25, 2016
·
433
· nicocrm

InforCRM Attachment Form & List

Attachment form customizations (in version 8.1+) need to be carried out in Javascript. By using "monkey patch" technique the customizations can be unobtrusive and (relatively) upgrade safe - it makes use of private methods and implementation details, but it does not requiring modifying the stock files. By using aspect.after it is also possible to have multiple module customizing the form / grid independently. My co-worker Adam and I came up with the following for a customer:

Here is how to add a new column:

//add the document type column to the grid and the sdata query
aspect.after(AttachmentList.prototype, 'onBeforeCreateGrid', function (options) {
    options.columns.push({
        field: "documentType",
        name: "Doc Type",
        sortable: true,
// Optionally, provide custom filter configuration
// This can make use of custom made widgets
//        filterConfig: {
//            widgetType: PickListFilterWidget,
//            label: 'Document Type'
//        }
    });

    options.storeOptions.select.push("documentType");
}, true);

Customizations to the edit form are a little bit more involved but we can take advantage of a hook provided by Infor: onDescriptionsEntered. The controls are a few pixels off unless you dig pretty deep in the internals of the DescriptionsForm class (which I wanted to avoid to stay mostly upgrade safe) or spend a bit of time fiddling with the CSS.

//add the form parts for the document type drop down to the attachment details screen when a new attachment is uploaded
aspect.after(DescriptionsForm.prototype, '_addFormParts', function () {

    for (var i = 0; i < this.files.length; i++) {

        var file = this.files[i];

        var contentPane = new dijit.layout.ContentPane({
            id: 'panAttachmentAdditionalFields_' + i,
            content: '<div class="attachment-additional-fields">' + 
                '<div style="float: left; width: 50%"><label>Document Type:</label><br/><input type="text" class="txtDocumentType"/></div>' +
                '<div style="float: left; width: 50%"><label>Private?<input type="checkbox" class="chkPrivate"/></label></div>' + 
                '</div>'
        });
        var docTypeFld = new SingleSelectPickList({
            id: 'docType_' + i,
            value: '',
            pickListName: 'Attachment Type'
        }, contentPane.domNode.querySelector('input.txtDocumentType'));
        var chkPrivate = new CheckBox({
            id: 'chkPrivate_' + i
        }, contentPane.domNode.querySelector('input.chkPrivate'));
        this.contentNode.addChild(contentPane);

        // Note that we do NOT add the fields to the form parts.
        // this is because clearForm is called before onDescriptionsEntered, thus would make it impossible to retrieve the control values.
        //                this._formParts.push(contentPane);
    }
});

//hijack the onDescriptionsEntered function to pull out the values from the documentType drop down
DescriptionsForm.prototype.onDescriptionsEntered = function (files, descriptions) {            
    for (var i = 0; i < descriptions.length; i++) {
        descriptions[i].documentType = dijit.byId('docType_' + i).get('value');
        if(!descriptions[i].details)
            descriptions[i].details = {};
        descriptions[i].details.isPrivate = dijit.byId('chkPrivate_' + i).get('value') == "on";
        descriptions[i].details.importSource = 'Attachment Tab';
        dijit.byId('panAttachmentAdditionalFields_' + i).destroyRecursive();
    }
};

This will be wrapped in a require call, something like:

require(["dojo/aspect",
        "Sage/UI/AttachmentList",       
        'Sage/UI/Controls/SingleSelectPickList', 
        'dijit/form/CheckBox', 
        'Sage/Utility/File/DescriptionsForm'],
function(aspect, AttachmentList, SingleSelectPickList, CheckBox, DescriptionsForm) {
  //  ... 
}