Extended runtime function 'lookup' to use a list guid

Document created by lonesurvivor on Aug 4, 2016
Version 1Show Document
  • View in full screen mode

Hi everybody,

 

I just stumbled over the runtime function lookup. Why needs this display names for listnames instead of internal names?!

This makes absolutely no sense because as soon someone renames a list, it doesn't work any longer.

 

Even more worse is the fact that if your website supports multilingualism and a list has naturally another displayname than in english, the form crashes because the lookup-function doesn't find the list.

 

In my case, two lists "aTranslation" and "bTranslation" were created and renamed afterwards both to "Translation". So the lookup-function uses the first list, it find's with this name.

 

Solution:

 

In Nintex's JavaScript-Function in File RuntimeFunctions.js line 436 the client object model function get_lists().getByTitle(self.listName) is used.

I think, it would be useful to enhance the code by checking if listName is a GUID and if so, call .getById(self.listName). So the list would be obvious.

 

I built a workaround for the missing functionality. My Nintex form now includes an external javascript-file where I override the NWF.ClientRequests.Lookup-function and added a differentiation with regulary expressions. If listName is a Guid, the function-call is getById, else getByTitle.

 

NWF.ClientRequests.Lookup = function (clientContext, id, queryKey, listName, filterColumnName, filterColumnType, filterValue, returnColumnName) {
    console.log("overriden NWF.ClientRequests.Lookup");
    
    var self = this;

    self.clientContext = clientContext;
    self.id = id;
    self.queryKey = queryKey;
    self.listName = listName;
    self.filterColumnName = filterColumnName;
    self.filterColumnType = filterColumnType;
    self.filterValue = filterValue;
    self.listItems = null;
    self.pendingRequest = false;
    self.deferred = NWF$.Deferred();
    self.queryExecuted = false;
    self.fields = null;
    self.camlQueryText = "";
    self.retryCount = 0;
    self.queryExecutedAt = null;
    self.timeoutLength = 60 * 1000 * 2; // 2 minutes
    self.filterSPField = null;
    self.hasExternalDataSource = false;
    self.returnColumnName = returnColumnName;
    self.list = null;
    self.rowLimit = 1000;

    function refreshCache() {
        self.queryExecutedAt = null;
        self.queryExecuted = false;
        self.retryCount = 0;
        self.deferred = NWF$.Deferred();
    }
    
    function isLookupStale() {
        
        if (self.queryExecutedAt == null) {
            return false;
        }
        
        if (NWF$.now() - self.queryExecutedAt > self.timeoutLength) {
            return true;
        } else {
            return false;
        }
    }

    self.buildViewFieldsForExternalList = function () {
        var viewFields = '<ViewFields>';

        var fieldsEnumerator = self.fields.getEnumerator();

        while (fieldsEnumerator.moveNext()) {
            var field = fieldsEnumerator.get_current();

            viewFields += '<FieldRef Name="' + field.get_internalName() + '"/>';
        }

        viewFields += '</ViewFields>';

        return viewFields;
    };
    
    self.getFieldByInternalNameOrTitle = function (columnName) {

        var fieldsEnumerator = self.fields.getEnumerator();

        while (fieldsEnumerator.moveNext()) {
            var field = fieldsEnumerator.get_current();

            if (field.get_title().toLowerCase() == columnName.toLowerCase() || field.get_internalName().toLowerCase() == columnName.toLowerCase() || field.get_title() == columnName) {
                return field;
            }
        }

        return null;
    };

    self.request = function (requestGroupId, forceRefresh, viewFieldsXmlNode) {        
        if (!self.pendingRequest || forceRefresh) {
            self.pendingRequest = true;
            
            if (!requestGroupId) {
                requestGroupId = NF.GenerateGuid();
            }
            
            if (self.queryExecuted) {
                if (isLookupStale()) {
                    refreshCache();
                } else {
                    self.pendingRequest = false;
                    return self.deferred;
                }
            }

            if (self.retryCount > 0 && viewFieldsXmlNode == undefined) {
                self.filterColumnSPField = self.getFieldByInternalNameOrTitle(filterColumnName);
                
                if (self.filterColumnSPField != null) {
                    self.filterColumnName = self.filterColumnSPField.get_internalName();

                } else {
                    return handleRequestFailure({ get_message: function () { return "Internal Name not found for filter column: '" + self.filterColumnName + "'"; } });
                }
                
                console.log(NF.GetRequestGroupConsoleString(requestGroupId) + "Retrying SharePoint lookup request with internal column name: " + self.filterColumnName);
            }
            
            var camlQuery = new SP.CamlQuery();
            var valueAttribs = "";
            var fieldAttribs = "";
            
            if (self.filterColumnType == 'Date') {
                valueAttribs = "IncludeTimeValue='FALSE'";

            }
            else if (self.filterColumnType == 'DateTime') {
                valueAttribs = "IncludeTimeValue='TRUE'";

            }
            else if (self.filterColumnType == 'Lookup') {
                fieldAttribs = "LookupId='TRUE'";
            }

            self.camlQueryText = '<View>';
            
            if (viewFieldsXmlNode != undefined) {            
                self.camlQueryText += viewFieldsXmlNode;
            }
            
            if (self.filterValue == null || self.filterValue === "") {
                self.camlQueryText += '<Query><Where><IsNull><FieldRef Name=\'' + self.filterColumnName + '\' ' + fieldAttribs + ' /></IsNull></Where></Query><RowLimit>' + self.rowLimit + '</RowLimit>';

            } else {
                self.camlQueryText += '<Query><Where><Eq><FieldRef Name=\'' + self.filterColumnName + '\' ' + fieldAttribs + ' />' + '<Value Type=\'' + self.filterColumnType + '\' ' + valueAttribs + ' >' + self.filterValue + '</Value></Eq></Where></Query><RowLimit>' + self.rowLimit + '</RowLimit>';
            }
                                   
            self.camlQueryText += '</View>';
            console.log(NF.GetRequestGroupConsoleString(requestGroupId) + "Querying SharePoint for list item data: Query [" + self.camlQueryText + "]");
            camlQuery.set_viewXml(self.camlQueryText);
            
            var rx = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
            
            if (rx.test(self.listName))
            {
                console.log("query list by id");
                self.list = self.clientContext.get_web().get_lists().getById(self.listName);
            }
            else
            {
                console.log("query list by title");
                self.list = self.clientContext.get_web().get_lists().getByTitle(self.listName);
            }
            self.listItems = self.list.getItems(camlQuery);
            self.fields = self.list.get_fields();           
           
            self.clientContext.load(self.fields, 'Include(InternalName, TypeAsString, Title)');
            self.clientContext.load(self.listItems);            
            self.clientContext.load(self.list);
            
            self.clientContext.executeQueryAsyncDeferred().done(function () {
                
                self.hasExternalDataSource = self.list.get_hasExternalDataSource();
                if (self.hasExternalDataSource && self.retryCount < 1) {
                    self.retryCount++;
                    var viewFields = self.buildViewFieldsForExternalList();
                    console.log(NF.GetRequestGroupConsoleString(requestGroupId) + "List is an external list; Re-querying list item data with all view fields.");
                    self.request(requestGroupId, true, viewFields);
                } else {
                    self.queryExecutedAt = NWF$.now();
                    self.queryExecuted = true;
                    self.pendingRequest = false;
                    self.deferred.resolve();
                }
            })
           .fail(function (sender, err) {
               // retry with internal name if found
               if (self.retryCount < 1) {
                   console.log(NF.GetRequestGroupConsoleString(requestGroupId) + "A request for SharePoint data failed. Re-fetching columns in list: " + self.listName);

                   self.clientContext.load(self.fields, 'Include(InternalName, TypeAsString, Title)');
                   self.clientContext.load(self.list);

                   self.clientContext.executeQueryAsyncDeferred().done(function () {
                       self.retryCount++;

                       try {
                           self.hasExternalDataSource = self.list.get_hasExternalDataSource();
                           if (self.hasExternalDataSource) {
                               console.log(NF.GetRequestGroupConsoleString(requestGroupId) + "List is an external list; Re-querying list item data with all view fields.");
                               return self.request(requestGroupId, true, self.buildViewFieldsForExternalList());
                           }
                       }
                       catch (err) {
                           console.log(NF.GetRequestGroupConsoleString(requestGroupId) + "Failed to determine if list has an external data source.");
                           return null;
                       }

                       return self.request(requestGroupId, true);
                   }).fail(function (sender, err) {
                       handleRequestFailure(err, requestGroupId);
                   });
               } else {
                   handleRequestFailure(err, requestGroupId);
               }
           });
        }

        return self.deferred;
    };
    
    function handleRequestFailure(err, requestGroupId) {
        self.queryExecutedAt = NWF$.now();
        self.retryCount = 0;
        self.queryExecuted = true;
        self.pendingRequest = false;

        var errMessage = "";
        if (err && err.get_message != undefined) {
            errMessage = err.get_message();
        }

        var friendlyErrDesc = "A request for SharePoint data failed. Error details: " + errMessage;
        console.log(NF.GetRequestGroupConsoleString(requestGroupId) + friendlyErrDesc);

        self.deferred.reject(errMessage);
    }
};

 

Dieses Dokument wurde aus folgender Diskussion erzeugt: Why does the Runtime function 'lookup' asks for display names instead of internal names?!

Attachments

    Outcomes