This example show a training application list with multi level approval and email alerts – all handled within one list and powered by DFFS.
The requester fill in the form by selecting training or conference from a autocomplete lookup (DFFS Plugin) in another list of training activities and conferences (screenshot at the bottom of this article).
When selected, the script pulls in the event name, start and end date, cost and number of hours.
When the “Program” is selected from another autocomplete lookup, the program name and the manager for this program is pulled in from another list (screenshot at the bottom of this article).
Use this as a guide to make your own customized approval workflow in DFFS, and post any questions of feedback in the forum.
The training application list has these fields:
The status field that controls the workflow has these options:
- Draft
- Awaiting approval by manager
- Rejected by manager
- Awaiting approval by finance
- Rejected by finance
- Fully approved
In the email messages in this example the “manager”, “finance” and the end user are all the same person.
Please let me know if you are missing some steps, or you need some more details.
NewForm
Tabs
Rules
Custom JS
// Autocomplete on training / conference spjs.ac.textField({ "applyTo":"Title", "helpText":"Type to search open training and conferences", "loadText":"", "listGuid":"Conference_Training", "listBaseUrl":"/DFFS/DFFS_Demo", "showField":"Title", "searchFields":["Title"], "filterCAML":"", "useREST":true, "filterREST":"Status eq 'Open'", "optionDetailFields":["StartDate","EndDate","NumberOfHours","Cost"], "optionDetailPrefix":["Start: ","End: ","Number of hours: ","Cost ($): "], "enforceUniqueValues":true, "rowLimit":15, "listOptionsOnFocus":false, "minLengthBeforeSearch":3, "reValidateOnLoad":false, "allowAddNew":false, "isLookupInSelf":false, "addNewAdditionalFields":[], "multiselect":false, "multiselectSeparator":"; ", "orderBy":[], "setFields":[ { "fromFIN":"StartDate", "toFIN":"StartDate", "parseFunction":"parseDateFunc" }, { "fromFIN":"EndDate", "toFIN":"EndDate", "parseFunction":"parseDateFunc" }, { "fromFIN":"Cost", "toFIN":"Cost" }, { "fromFIN":"NumberOfHours", "toFIN":"NumberOfHours" } ], "debug":false }); function parseDateFunc(a){ // Set the desired format in the variable "f" var f = "MM/dd/yyyy hh:mm" , d = new Date(a); f = f.replace("MM",(d.getMonth()+1) < 10 ? "0"+(d.getMonth()+1) : (d.getMonth()+1)); f = f.replace("dd",d.getDate() < 10 ? "0"+d.getDate() : d.getDate()); f = f.replace("yyyy",d.getFullYear()); f = f.replace("yy",d.getFullYear().toString().substring(2)); f = f.replace("hh",d.getHours() < 10 ? "0"+d.getHours() : d.getHours()); f = f.replace("mm",d.getMinutes() < 10 ? "0"+d.getMinutes() : d.getMinutes()); return f.split(/ |:/); } // Autocomplete on program spjs.ac.textField({ "applyTo":"Program", "helpText":"Type to search programs", "loadText":"", "listGuid":"Programs", "listBaseUrl":"/DFFS/DFFS_Demo", "showField":"Title", "searchFields":["Title"], "filterCAML":"", "useREST":true, "filterREST":"Status eq 'Open'", "optionDetailFields":["Manager/Title"], "optionDetailPrefix":["Manager: "], "enforceUniqueValues":true, "rowLimit":15, "listOptionsOnFocus":false, "minLengthBeforeSearch":3, "reValidateOnLoad":false, "allowAddNew":false, "isLookupInSelf":false, "addNewAdditionalFields":[], "multiselect":false, "multiselectSeparator":"; ", "orderBy":[], "setFields":[ { "fromFIN":"Manager/Name", "toFIN":"Manager", "parseFunction":"" } ], "debug":false }); function showApprovalStatus(){ var b = [], label, labelColor, status, spjsStatusArr = [ {"label":"Draft","icon":"①","color":"#107c10"}, {"label":"Awaiting approval by manager","icon":"②","color":"#107c10"}, {"label":"Rejected by manager","icon":"③","color":"#e81123"}, {"label":"Awaiting approval by finance","icon":"④","color":"#107c10"}, {"label":"Rejected by finance","icon":"⑤","color":"#e81123"}, {"label":"Fully approved","icon":"⑥","color":"#107c10"} ]; status = getFieldValue("Status"); jQuery.each(spjsStatusArr,function(i,c){ b.push("<div title='"+c.label+"' class='statusBannerIcon'"); if(status === c.label){ b.push(" style='color:"+c.color+"'"); label = c.label; currStatusIndex = i; labelColor = c.color; } b.push("'>"+c.icon+"</div>"); }); jQuery(".approvalWfStatus").html(b.join("")); jQuery(".approvalWfLabel").html("<span style='color:"+labelColor+"'>Current status: "+label+"</span>"); } setTimeout(function(){ showApprovalStatus(); },500);
Custom CSS
.ms-formlabel{ width:250px; } .statusBannerIcon{ display:inline-block; font-size:35px; margin:5px; color:#cccccc; } .approvalWfLabel{ font-size:18px; font-weight:bold; border-bottom:1px silver solid; padding:0 0 10px 5px; } .customHeading{ background-color: #1B619B; color: #EFF2F6; font-size:16px; padding:5px 10px; }
DispForm
Tabs
Custom JS
function showApprovalStatus(){ var b = [], label, labelColor, status, spjsStatusArr = [ {"label":"Draft","icon":"①","color":"#107c10"}, {"label":"Awaiting approval by manager","icon":"②","color":"#107c10"}, {"label":"Rejected by manager","icon":"③","color":"#e81123"}, {"label":"Awaiting approval by finance","icon":"④","color":"#107c10"}, {"label":"Rejected by finance","icon":"⑤","color":"#e81123"}, {"label":"Fully approved","icon":"⑥","color":"#107c10"} ]; status = getFieldValue("Status"); jQuery.each(spjsStatusArr,function(i,c){ b.push("<div title='"+c.label+"' class='statusBannerIcon'"); if(status === c.label){ b.push(" style='color:"+c.color+"'"); label = c.label; currStatusIndex = i; labelColor = c.color; } b.push("'>"+c.icon+"</div>"); }); jQuery(".approvalWfStatus").html(b.join("")); jQuery(".approvalWfLabel").html("<span style='color:"+labelColor+"'>Current status: "+label+"</span>"); } setTimeout(function(){ showApprovalStatus(); },500);
Custom CSS
.ms-formlabel{ width:250px; } .statusBannerIcon{ display:inline-block; font-size:35px; margin:5px; color:#cccccc; } .approvalWfLabel{ font-size:18px; font-weight:bold; border-bottom:1px silver solid; padding:0 0 10px 5px; } .customHeading{ background-color: #1B619B; color: #EFF2F6; font-size:16px; padding:5px 10px; }
EditForm
The first step in EditForm is “Approval by manager”, then “Approval by finance”. Both steps can either be approved or rejected.
If the manager approves, an email is sent to “finance”.
If the manager rejects, an email is sent to the author and the status set to “Rejected by manager”.
If it is approved, the finance representative follows the link in the email to this form:
Finance can reject or approve. If it is rejected, this email will be sent to the author of the request form:
If it is approved, this email is sent:
Tabs
Rules
Please note that the checkbox “Use custom list with workflow to send E-Mails” is checked. This is necessary to be able to postpone the sending of the email “eventFollowUp” that has this “Send date”:
{EndDate}+14
If you use the REST email option (by not checking this checkbox) your email will be sent immediately.
Please refer the user installation manual for details on the DFFS_Email list and workflow.
Custom JS
function showApprovalStatus(){ var b = [], label, labelColor, status, spjsStatusArr = [ {"label":"Draft","icon":"①","color":"#107c10"}, {"label":"Awaiting approval by manager","icon":"②","color":"#107c10"}, {"label":"Rejected by manager","icon":"③","color":"#e81123"}, {"label":"Awaiting approval by finance","icon":"④","color":"#107c10"}, {"label":"Rejected by finance","icon":"⑤","color":"#e81123"}, {"label":"Fully approved","icon":"⑥","color":"#107c10"} ]; status = getFieldValue("Status"); jQuery.each(spjsStatusArr,function(i,c){ b.push("<div title='"+c.label+"' class='statusBannerIcon'"); if(status === c.label){ b.push(" style='color:"+c.color+"'"); label = c.label; currStatusIndex = i; labelColor = c.color; } b.push("'>"+c.icon+"</div>"); }); jQuery(".approvalWfStatus").html(b.join("")); jQuery(".approvalWfLabel").html("<span style='color:"+labelColor+"'>Current status: "+label+"</span>"); } setTimeout(function(){ showApprovalStatus(); },500);
Custom CSS
.ms-formlabel{ width:250px; } .statusBannerIcon{ display:inline-block; font-size:35px; margin:5px; color:#cccccc; } .approvalWfLabel{ font-size:18px; font-weight:bold; border-bottom:1px silver solid; padding:0 0 10px 5px; } .customHeading{ background-color: #1B619B; color: #EFF2F6; font-size:16px; padding:5px 10px; }
Lookup lists for the Autocomplete plugin
The datasource for “Training/Conference” and “Program” is is two separate lists in the same site.
This looks really good but for a novice like me there is a lot not explained that I’m not sure about, like where are the status icons 1 to 6 in circles? are these built in or is this all up to me to figure out … it’s OK if it is; after all I’m not expecting you to give me a crash course in web development 🙂
Sorry for the delay – these are unicode “icons” defined in this array in the Custom JS section:
Look here: http://www.fileformat.info/info/unicode/char/2460/index.htm and use the “next character” navigation in the top right corner to see the next one.
PS: The HTML code for the icons are turned into actual icons in the above snippet.
Alexander
Issue: NewForm not saved
New Form:
Press Save Button:
– comment/comments field changed
– status field changed
– no storage, NewForm keeps open. No further response on pressing Save button.
happens often < 50% of time, looks like a latency problem.
System: SharePoint 2013 Server; IE Version:11.492.16299.0
I think I found the problem: the function parseDateFunc has to deliver the countryspecific date format to the Autocomplete function. “MM/dd/…” produces an error and “dd/MM…” works just fine.
The error is only shown if in the rule Saved (in the NewForm) the email ID “managerEmail” is removed from “Send or stop these E-mails”.
The parseDateFunc in the custom js in the example must return the current display format of your date picker as it inserts the parsed string into the datepicker input field.
Alexander
If you experience errors in the form you must hit F12 to bring up the developer tools and look at the Console for errors. I recommend using Google Chrome for debugging (and in general not use IE if you can avoid it).
Alexander
\n Disappears in email body
Rules: Saved (NewForm) , SaveForm (EditForm)
prepend:{CurrentUser} {timestamp}\n{Comment}\n\n
Comment and Comments field not showing correctly in the email body (Outlook Windows 10)
The \n disappears resulting in a string without new lines.
You cannot use \n for linefeed – use either a normal linefeed (hit Enter), or use a
if you like to write the email body as HTML.
Alexander
\n is used in the example in prepend a {comment} to {comments}
in the rule Saved. In a Note field without html this is the usual way.
If the Notefield is html a will work and the email and printout are correct but requires that every Note field in the DFFS application needs to be html based.
I would prefer to have a choice as user for all Note field variants.
Therefor preprocessing the Note field by replace the \n for in the DFFS application is highly desireable.
Ah – sorry, I thought you meant creating linefeeds in your manually entered email body text. Try using
instead of just
when appending the text.
Alexander
using \r\n doesn’t deliver the desired result.
In the Note field Comments the \r is added to the text with newlines and in the mail body the \r shows up again but without newlines:
Comments
Peter Giesselink zondag 10 februari 2019 12:38:25\rfinanace commentPeter Giesselink zondag 10 februari 2019 12:37:37\rmanager commentaarPeter Giesselink zondag 10 februari 2019 12:35:54\r123 help
The problem is that the text in the plain text multiline is retrieved as plain text when you use the default {FieldInternalName} reference to include it in the email body from NewForm or EditForm.
What you need to do is to add a snippet like this to your Custom JS to pick up the plain text and replace \n with <br>
Then use this format in the email body to pick up the content of the variable:
Alexander
Your solution works just fine. Thanks.
Peter
In the tabs Approval_by_manager and Approval_by_finance the rules ManagerEmailLinks respectivily FinanceEmailLink ar not working properly: The Comment field is not marked as required. The rule is correcty implemented for the fields Approved_by_Manager and Approved_by_Finance.
In the tab Follow_up_comment the is no problem with with the rule FollowUpComment which defines Comment field as a required field there is no problem
OK, I don’t have this example set up at the moment so I cannot test and fix it, but I guess you have already corrected it in your copy.
Alexander
Yes, I’ve corrected it.