All posts by Alexander Bautz

Highlight changes from the last save in DispForm or EditForm

This solution is designed for use in Custom JS in a DFFS enabled form. It will highlight the changes made in he last save so the person viewing the DispForm or EditForm can quickly identify what fields have changed and what was changed.

Please note that it is only tested in SharePoint online, but it might also work in an on-premises 2016 or 2019 SharePoint form.

This is how it looks in the form:

And when you click the icon to the right of the highlighted row you can view the actual changes:

How to install

Just add this code to your Custom JS and you are good to go:

spjs.highlightChanges = {
    "version": "1.0.0.0",
    "settings": {
        "highlightStyle": {
            "backgroundColor": "#ffaa44"
        },
        "iconSrc": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAZdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuMTZEaa/1AAABBUlEQVQ4T9WTPQrCQBCFcwCrgOexEmwDHsA6EPLXCwHBGwg5iZVtwMobBAQPIKQShPje8nCJWRPt9MGwmTff7M+g3n8oDMNJmqbrLMsqxF1R0WNN2LAAz5IkqdF4wbrDumLom15NRrhbAALALdbSdbJuWooJZHeFgg+gISjLCPmBodSIjFhflhWuvEHx/HoTeHuGUiMyZNkjywqFE07YKh0VWfYotYrj+Jbn+VLpU4BbhtKnyKLnqtSK5rcbwW+UWsF0Pu3dRppp/2kDw+5tNDjsKIqmKDYo7mQZuTYiQ5Y9srrSuz/6Qbrm2RGgOU4c+4sshA9LMygQR4R5mr4L101/UZ73ADXvzFKUWbsAAAAAAElFTkSuQmCC",
        "iconTooltip": "Show changes made in last edit",
        "dlgTitle": "Changes in the last version for",
        "currentVersionLabel": "Current version",
        "previousVersionLabel": "Previous version",
        "modifiedLabel": "Modified ",
        "modifiedByLabel": " by "
    },
    "init": function () {
        jQuery.ajax({
            "url": _spPageContextInfo.webAbsoluteUrl + "/_api/Web/Lists/getbyid('" + _spPageContextInfo.pageListId + "')/items('" + spjs.dffs.data.thisItemID + "')/?$select=Versions/VersionId&$expand=Versions",
            "method": "GET",
            "headers": {
                "accept": "application/json; odata=verbose",
                "content-type": "application/json;odata=verbose",
                "X-RequestDigest": jQuery("#__REQUESTDIGEST").val()
            },
            "success": function (data) {
                var previousVersionId = data.d.Versions.results[1].VersionId;
                var currentVerionsId = data.d.Versions.results[0].VersionId;
                var previous = null;
                var current = null;
                spjs.highlightChanges.getVersion(_spPageContextInfo.pageListId, spjs.dffs.data.thisItemID, previousVersionId).done(function (data) {
                    previous = data;
                    spjs.highlightChanges.compare(previous, current);
                });
                spjs.highlightChanges.getVersion(_spPageContextInfo.pageListId, spjs.dffs.data.thisItemID, currentVerionsId).done(function (data) {
                    current = data;
                    spjs.highlightChanges.compare(previous, current);
                });
            },
            "error": function (err) {
                console.log(err);
            }
        });
    },
    "getDisplayValue": function (fin, val) {
        var value = val === null || val === null ? "" : val;
        if (value !== "") {
            switch (spjs.dffs.fieldtype[fin]) {
                case "SPFieldDateTime":
                    value = new Date(val.split("T").join(" ")).toLocaleString();
                    break;
                case "SPFieldMultiChoice":
                    value = value.results.join("; ");
                    break;
                case "SPFieldLookupMulti":
                case "SPFieldUserMulti":
                    var arr = [];
                    jQuery.each(value.results, function (i, o) {
                        arr.push(o.LookupValue);
                    });
                    value = arr.join("; ");
                    break;
            }
        }
        return value;
    },
    "compare": function (po, co) {
        if (po !== null && co !== null) {
            // Fix internal names where _ is escaped
            var p = {};
            jQuery.each(po, function (fin, o) {
                p[fin.split("_x005f_").join("_")] = o;
            });
            var c = {};
            jQuery.each(co, function (fin, o) {
                c[fin.split("_x005f_").join("_")] = o;
            });
            var changes = [];
            jQuery.each(spjs.dffs.fieldData, function (fin, o) {
                if (fin === "Proforma_x0020_Available_x0020_D") { }
                var pv = JSON.stringify(p[fin]);
                if (typeof pv === "string") {
                    pv = pv.replace(/[^a-z0-9\s]/gi, '');
                }
                var cv = JSON.stringify(c[fin]);
                if (typeof cv === "string") {
                    cv = cv.replace(/[^a-z0-9\s]/gi, '');
                }
                if (pv !== cv) {
                    changes.push({
                        "fin": fin,
                        "disp": o.disp,
                        "previous": spjs.highlightChanges.getDisplayValue(fin, p[fin]),
                        "current": spjs.highlightChanges.getDisplayValue(fin, c[fin]),
                        "previousEditor": p.Editor.LookupValue,
                        "currentEditor": c.Editor.LookupValue,
                        "currentModified": new Date(c.Modified.split("T").join(" ")).toLocaleString(),
                        "previousModified": new Date(p.Modified.split("T").join(" ")).toLocaleString()
                    });
                }
            });
            spjs.highlightChanges.__spjsChanges = changes;
            jQuery.each(changes, function (i, o) {
                jQuery("#dffs_" + o.fin).find(">td").css(spjs.highlightChanges.settings.highlightStyle);
                jQuery("#dffs_" + o.fin).find("td.ms-formbody").prepend("<img title='" + spjs.highlightChanges.settings.iconTooltip + "' style='float:right;margin-right:-25px;cursor:help;' src='" + spjs.highlightChanges.settings.iconSrc + "' onclick='spjs.highlightChanges.view(\"" + i + "\")'>");
            });
        }
    },
    "view": function (index) {
        var c = spjs.highlightChanges.__spjsChanges[index];
        spjs.modal.add({
            "title": spjs.highlightChanges.settings.dlgTitle + " " + c.disp,
            "html": "<strong>" + spjs.highlightChanges.settings.currentVersionLabel + "</strong> [" + spjs.highlightChanges.settings.modifiedLabel + c.currentModified + spjs.highlightChanges.settings.modifiedByLabel + c.currentEditor + "]<br>" + JSON.stringify(c.current, null, 4) + "<hr style='margin:10px 0'><strong>" + spjs.highlightChanges.settings.previousVersionLabel + "</strong> [" + spjs.highlightChanges.settings.modifiedLabel + c.previousModified + spjs.highlightChanges.settings.modifiedByLabel + c.previousEditor + "]<br>" + JSON.stringify(c.previous, null, 4),
            "ok": function () {
                // Close
            }
        });
    },
    "getVersion": function (listId, listItemId, verionsId) {
        var deferred = jQuery.Deferred();
        jQuery.ajax({
            "url": _spPageContextInfo.webAbsoluteUrl + "/_api/Web/Lists/getbyid('" + listId + "')/items('" + listItemId + "')/versions('" + verionsId + "')",
            "method": "GET",
            "headers": {
                "accept": "application/json; odata=verbose",
                "content-type": "application/json;odata=verbose",
                "X-RequestDigest": jQuery("#__REQUESTDIGEST").val()
            },
            "success": function (data) {
                deferred.resolve(data.d);
            },
            "error": function (err) {
                console.log(err);
            }
        });
        return deferred.promise();
    }
};

spjs.highlightChanges.init();

You can change the settings in the top of the script to change the text and styling of the highlight.

Please post any questions below or in the forum.

Alexander

DFFS Package updated to v4.4.5.5

This version fixes a breaking change in Office 365 – introduced by Microsoft in the latest update. The DFFS installer is updated to fix this for new forms installed, but I have also made a tool that you can run in a site to fix all forms already installed. Read about it here: https://spjsblog.com/2020/07/30/fix-classic-form-fallback-on-modern-lists/.

There are also some other small bugfixes that are described in the change log.

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

Post comments below, or use the form.

Best regards,
Alexander

Fix classic form fallback on modern lists

This will fix the problem where the form is opened in the sidepanel without DFFS when you click to view, edit or add a new item from a modern list view.

Updated August 13, 2020

Great news! Microsoft has actually backed down and rolled back this breaking change yesterday!

It’s not all sunshine though because it will only be reversed for lists that have already been created and NOT for lists created from now and forward.

This means you must update to the latest DFFS installer to ensure it applies the necessary changes when installing in a new list.

Updated August 8, 2020

Microsoft admits to have broken the auto-detection of a modified form (with DFFS or other custom code) from a modern view, but won’t fix it. This means all Office 365 customers will get this error when the new version of SharePoint is rolling out.

ChangeLog

July 31, 2020 – v1.0.0.2

Fixed a bug where only the first 100 DFFS configurations in the SPJS-DynamicFormsForSharePoint list were checked. Also changed a jQspjs (jQuery noConflict namespace in DFFS) reference that made it only work when loaded in a DFFS form and not in a standalone page with plain jQuery loaded.


Microsoft is investigating the ticket i submitted yesterday regarding the breaking change or bug that was released for first release customers on Office 365link to my post from yesterday.

I have been able to create a script that fixes this problem on all DFFS enabled lists within a site (it must be run once for each site) by writing the NewFormUrl, DispForUrl and EditFormUrl to the content types for these lists. A big thanks to Earl Libby from SPMarketplace for helping me figure out this workaround!

I will release a new version of DFFS this weekend (August 8-9) where the DFFS installer is updated to include this fix.

This is what it does

  1. Gets all lists in current site to use in step 2
  2. Gets all stored configurations from the DFFS config list “SPJS-DynamicFormsForSharePoint” and gets all unique lists – finding the list GUID from the lists gathered in step one.
  3. Looping over all content types in all the DFFS enabled lists and checks if the NewFormUrl, DisplayFormUrl and EditFormUrl matches the current content type scope (the current list path) and if not update it.

How to use it

This script is designed to be dropped directly in the console of any page within a SharePoint site, but it needs jQuery to run so it may be best to open a list NewForm by typing in this in the browser address bar:

https://contoso.sharepoint.com/sites/YourSite/Lists/YourList/NewForm.aspx

The open the console and paste the script there.

I recommend using Google Chrome or the new Edge (chromium) as these have better console than Internet Explorer and the old Edge.

The script will log to the console so you know what is going on.

Please note that you need at least manage lists permissions to use this script. Also note that this only fixes lists that already have DFFS installed. This means that any new lists you install DFFS in might still fail unless you re-run this script. This will be fixed when I release a new version of the DFFS installer sometime later this week.

Get the script here

Link to script file (zipped).

Please let me know if you have any question in the comments below.

Best regards,
Alexander