Category Archives: DFFS

DFFS Reverse Lookup

I got this request:

The OOTB Reverse Lookup in SharePoint is very useful for several use cases. Using DFFS cascading dropdowns means that capability is lost. Is there any way to emulate reverse lookup when using DFFS cascading dropdowns with large lists (over 5K), perhaps with some custom JavaScript? Something that works with a single choice or multiple choice?

https://spjsblog.com/forums/topic/can-custom-js-emulate-sp-reverse-lookup/#post-26634

I’ll make this short – just follow the below steps.

Add this to the DFFS Tab where you want the items to show (in the Parent list)

<div style="font-size:1.5em;font-weight:300;">Related items</div>
<div id="relatedItemsPlaceholder"></div>

Add this to your Custom JS (in the Parent list)

 function getRelatedItems(arg) {
    var isGuid = arg.listName.charAt(0) === "{", b = [];
    jQspjs.ajax({
        "url": arg.listBaseUrl + "/_api/Web/Lists/" + (isGuid ? "getById" : "getByTitle") + "('" + arg.listName + "')/items?$filter=" + arg.filter + "&$select=" + (arg.select.length > 0 ? arg.select.join(",") : "*") + ",Id,FileDirRef" + (arg.expand.length > 0 ? "&$expand=" + arg.expand.join(",") : "") + "&$top=" + arg.itemLimit,
        "type": "GET",
        "headers": {
            "accept": "application/json; odata=verbose",
            "content-type": "application/jsom;odata=verbose",
            "X-RequestDigest": document.getElementById("__REQUESTDIGEST").value
        },
        "success": function (data) {
            if (data.d.results.length > 0) {
                // Header row
                b.push("<tr class='dffs_relatedItems_headerRow'>");
                if (arg.linkToItem.view.on) {
                    b.push("<td class='dffs_relatedItems_headerCell'></td>");
                }
                if (arg.linkToItem.edit.on) {
                    b.push("<td class='dffs_relatedItems_headerCell'></td>");
                }
                jQuery.each(arg.viewFields, function (i, o) {
                    b.push("<td class='dffs_relatedItems_headerCell'>" + o.label + "</td>");
                });
                b.push("</tr>");
                jQuery.each(data.d.results, function (i, item) {
                    var viewLink = item.FileDirRef + "/DispForm.aspx?ID=" + item.Id, editLink = item.FileDirRef + "/EditForm.aspx?ID=" + item.Id;
                    b.push("<tr class='dffs_relatedItems_row'>");
                    if (arg.linkToItem.view.on) {
                        b.push("<td class='dffs_relatedItems_cell'><img style='cursor:pointer;vertical-align:middel;' onclick='openInDlg(\"" + viewLink + "\")' src='" + arg.linkToItem.view.icon + "'></a></td>");
                    }
                    if (arg.linkToItem.edit.on) {
                        b.push("<td class='dffs_relatedItems_cell'><img style='cursor:pointer;vertical-align:middel;' onclick='openInDlg(\"" + editLink + "\")' src='" + arg.linkToItem.edit.icon + "'></a></td>");
                    }
                    jQuery.each(arg.viewFields, function (j, o) {
                        var a = o.fin.split("/"), val;
                        if (a.length === 1) {
                            val = item[a[0]];
                        } else {
                            val = item[a[0]][a[1]];
                        }
                        if (o.parseFunction !== null) {
                            val = window[o.parseFunction](val, item);
                        }
                        b.push("<td class='dffs_relatedItems_cell'>" + val + "</td>");
                    });
                    b.push("</tr>");
                });
            }
            if (b.length === 0) {
                b.push("<div style='padding:10px;'>" + arg.labels.noItemsFound + "</div>");
            } else {
                b.unshift("<table class='dffs_relatedItems_table'>");
                b.push("</table>");
            }
            jQuery("#" + arg.placeholderID).html(b.join(""));
        },
        "error": function (err) {
            console.log(err);
        }
    });
}

// Parse function for date fields
function dateObjToFriendlyDate(v, item) {
    var r = "";
    try {
        var d = new Date(v);
        r = d.toLocaleDateString(_spPageContextInfo.currentUICultureName);
    } catch (ignore) {
        // Nothing
    }
    return r;
}

// Open form in dialog
function openInDlg(url) {
    var options = {
        "url": url
    };
    SP.UI.ModalDialog.showModalDialog(options);
}

getRelatedItems({
    "placeholderID": "relatedItemsPlaceholder",
    "listName": "{8c75ce59-f1a0-4823-b5a1-81afa9884b27}", // Use DisplayName or GUID (GUID must start and end with curly brace)
    "listBaseUrl": _spPageContextInfo.webServerRelativeUrl,
    "filter": "ParentItem eq '" + spjs.dffs.data.thisItemID + "'", // Please note that the field you want to filter by must be indexed if your liste has more than 5000 items
    "select": ["Title", "Author/Id", "Author/Title", "Created"],
    "expand": ["Author"],
    "linkToItem": {
        "view": {
            "on": true,
            "icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABMUlEQVQ4T6WSvUsDQRDF522bYKmgtaS2kKvD3P4PoiD4WQmSKpDCUtBOOxVNJQjWVnuTA7urrIOtCNopB3YzEkkgJpeQj2kWhsePt28eqDve+2VVrQPYIKJFIvo0swfn3FkI4b2nG3zRWTCzB3BlZhd5njezLPuOomihVCptAqgR0ZGIhCIIqtVqxTl3D+AgSZKXQVEcx2tmdqOqW2matoccMPM5EbVF5HaUTWbeI6KKiNSJyPp1YOZH51wjhPA6CuC9X1XVUwD7SZJ8/QPEcfxkZrsi8jHGwRKAuyLd/A66GbyJyOVMGcx9hXE9KJfLOwAaZvZjZtutVuu5sEid5bgmquoKgGtVPR6E/DVxkmHmdSJqElGtv5UTA7pfHYJMBSiCTA3oQTqZmNnhTIA+Jye/ts29i6m1dSsAAAAASUVORK5CYII="
        },
        "edit": {
            "on": true,
            "icon": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA6klEQVQ4T+WTPQoCMRBG5yNrs9VWijewzwWEqa30BN5ABGsbUbAQBFvP4AUWFvcSgqWVIFYWCkNGIruw+LOrtSmSEPLeTMIMKBvM3ACwVtW+P6rax3F8fNzzUwYnRNTKhRXrTlXbXlIUPKLn5k+CYqb/KrDW1sIwjNI0PRGR/vyJ1towiqI5EfUBTH4SZPACwE1ElkEQrL4WFGFjzFhEpkR0+UrwDs6yGFUKyuAkSa6lgir4uRdeSpmZewA6xpiBf3Oeto+cl3ppBsw8A1BX1SaAvYiMinBZNx5UtUtEQwBn59zGObd9hr3gDipMDAs8Vm/dAAAAAElFTkSuQmCC"
        }
    },
    "viewFields": [
        {
            "label": "Title",
            "fin": "Title",
            "parseFunction": null
        },
        {
            "label": "Author",
            "fin": "Author/Title",
            "parseFunction": null
        },
        {
            "label": "Created",
            "fin": "Created",
            "parseFunction": "dateObjToFriendlyDate"
        }
    ],
    "labels": {
        "noItemsFound": "There are no related items"
    },
    "itemLimit": 3
});

Add this to your Custom CSS (in the Parent list)

 #relatedItemsPlaceholder{
    padding:5px;
    border:1px #e1dfdd solid;
}
.dffs_relatedItems_table{
    border-collapse:collapse;
}
.dffs_relatedItems_headerCell{
    padding:2px 3px;
    font-size:1.3em;
    font-weight:300;
}
.dffs_relatedItems_cell{
    padding:2px 3px;
    font-size:1.1em;
    font-weight:300;
}
.dffs_relatedItems_row:hover td{
    background-color:#f3f2f1;
} 

This example uses the following lists

The parent list has only the Title field.
The child list ha a lookup to the parent list.

When you click the First parent item you see the children

Please note that only 3 items are retrieved because of the itemLimit setting in the function call.

When you click the Second parent item you see this message

This item does not have any child items.

You must read trough the code and modify the argument to the function call to getRelatedItems.

Post any questions in the comments below.

Alexander

DFFS Package updated to v4.4.4.1

I have fixed a few bugs and small issues, and added some more error handling regarding custom functions. You find the compete change log here, and the updated files in the download section of the user manual.

Post comments below, but use the form if you have questions or you think you have found a bug.

Best regards,
Alexander

DFFS Package updated to v4.4.4.0

I have finally been able to release the new version of DFFS where I have fixed several issues and done a major overhaul of the trigger handling to fix some problems with rule order when using multiple rules on the same field.

A special thanks to Rudolf Vehring for his help with testing of all the changes in this release.

You find the compete change log here, and the updated files in the download section of the user manual.

Post comments below, but use the form if you have questions or you think you have found a bug.

Best regards,
Alexander

DFFS Rule reversing explained

One of the main areas of confusion when using DFFS is the automatic rule reversing of rules that are NOT evaluated to true.

This example show how most users first set it up and ends up with the wrong result. I’ll first show how it is set up to make it fail, and then I’ll highlight the missing part at the bottom of this post.

The example form

Let’s say you have a choice field TabVisibility that controls the visibility of a specific tab. For this example I have created a choice field with two values: Show and Hide, an have set up three rules.

The tabs:

Tab is set to hidden but this will not work because the rules show below will override it.

The rules:

One for hiding the tab when the TabVisibility choice field is empty:

One for showing the tab when the value is Show:

And one for when the value is Hide:

This is how it looks when loading NewForm and the value in TabVisibility = blank, but it is not doing what you expect:

This must be wrong – the tab is not hidden???

Why this is not working

When you have trouble with a form you should always use the Debug this rule setting:

This will show you the debug panel below the form:

When the form loads, each of the three rules are evaluated. The first rule is evaluated as “true” and hides the tab as it should:

Hides the tab.

Then the next rule runs and is evaluated as “false” and does the opposite of what it is configured to do. It doesn’t do anything wrong here because the tab is already hidden, but you see where this is going:

Should show the tab if true, but reverses and hides the tab instead.

Then the last rule comes in and messes it up by showing the tab despite it being set up to HIDE the tab and not to show it:

Shows the tab because the rule is reversed when not evaluated to true.

Why is this happening?

The reason for this behavior is to avoid writing two rules for every action and just let DFFS handle the reversing – for example if a Yes/No field is checked: show some fields, set some fields required etc. Then if the field is unchecked, all visible field are hidden, required fields are set as optional etc. This is by design to limit the number of rules required to make a dynamic form.

This will however create problems when you use multiple rules on for example a single choice column as described above.

How to fix it

In this scenario you must use the No reversing of this rule setting in each of the three rules (optionally you can check the Disable reversing of all rules in the top of the Rules tab):

No reversing set on each rule.

When you have done this your NewForm will load correctly and hide the tab:

That’s it – post any comments below, or use the forum.

Alexander

DFFS Example: Limit access to form

This example show how you can use a set of rules to ensure only persons assigned in a people picker in the form, or members in an admin group can view or edit a list item.

Add these three rules:

This rule doesn’t have any actions.
This rule doesn’t have any actions.
This rule checks the two previous rules, and calls a function if both are false.

Then add this function to your Custom JS:

function noAccessToThisForm(){
jQuery("#part1").hide();
spjs.dffs.alert({
"title":"No access",
"msg":"You don't have access to this list item.",
"ok":function(){
window.history.back();
}
});
}

You can use this setup in both DispForm and EditForm, and it will show this message box if the user doesn’t have access:

Post any questions below, or use the forum.

Alexander