cancel
Showing results for 
Search instead for 
Did you mean: 
rdpDen
Nintex Newbie

SharePoint Nintext NewForm Custom Javascript Require Attachment

Jump to solution

Hello - New to nintex and javascript.

I have a SharePoint custom list with a nintex NewForm including custom javascript (and HTML, CSS) and I need to make the attachment control required.  I have found many solutions and suspect the reason I have not been able to solve the issue is placement of the attachment validation within the existing javascript:

var queryString = function(field, url)
{
 var href = url ? url : window.location.href;
 var reg = new RegExp('[?&]' + field + '=([^&#]*)','i');
 var string = reg.exec(href);
 return string ? string[1] : null;
};NWF$(document).ready(function()
{
 NWF$(".nf-form-footer").hide();
 NWF$("#"+ IIStatus).hide(); 
 NWF$("#"+ ICStatus).hide();  var isEditMode = document.location.pathname.indexOf("/EditForm.aspx") > -1;
 if(!isEditMode )
 {
 NWF$("#"+ SumComment).val('Please Approve.'); 
  var amount = NWF$("#"+ IAmount).val();
  var location = NWF$("#"+ ILocation).val() == null ? '' : NWF$("#"+ ILocation)[0].options.length > 0 ? NWF$("#"+ ILocation)[0].options[NWF$("#"+ ILocation)[0].selectedIndex].title : null;
  var department = NWF$("#"+ IDepartment).val() == null ? '' : NWF$("#"+ IDepartment)[0].options.length > 0 ? NWF$("#"+ IDepartment)[0].options[NWF$("#"+ IDepartment)[0].selectedIndex].title : null; 
  
  NWF$("#"+ IAmount).blur(function(){
   amount = this.value;
   getApprover(amount,location,department);
  });    NWF$("#"+ ILocation).change(function()
  {  
   if(this.value != '')
   {   
    location = this.options[this.selectedIndex].title;
    getCoder(location);
    getApprover(amount,location,department);
   }
  });     
  
  NWF$("#"+ IDepartment).change(function()
  {
   if(this.value != '')
   {
    department = this.options[this.selectedIndex].title;
    getApprover(amount,location,department);
   }
  });
 }
 else
 {
  if(NWF$("#"+ ICStatus).val() == "Rejected" || NWF$("#"+ IIStatus).val() == "Rejected")
  {
   NWF$("#"+ IIStatus).val('Coder Approval Pending');
   NWF$("#"+ ICStatus).val('Pending Approval');
  }  
 }
}); 
   
function getApprover(amount,location,department)
{ 
 approverClear();
 if(amount != '' && location != '' && department != '')
 {  
  NWF$.ajax({ 
   url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('Approver Detail')/Items?$orderby=Amount asc&$select=Location/Title,Department/Title,Amount, Title&$expand=Location, Department&$filter=Location/Title eq '" + location + "' and Department/Title eq '" + department + "'",   type: "GET", 
   headers: {"accept": "application/json;odata=verbose"}, 
   success: function (data)
   { 
    debugger;
    if(data != undefined && data.d != undefined && data.d.results != undefined && data.d.results.length > 0)
    { 
     var maxAmt = true;
     for(var cnt = 0; cnt < data.d.results.length; cnt++)
     {
      if(data.d.results[cnt].Role != "Coder 1" && data.d.results[cnt].Role != "Coder 2")
      {
       if(data.d.results[cnt].Amount == amount) 
       {
        AddUserToPPL(data.d.results[cnt].Title);
        maxAmt = false;
        return false;
       }
      }
     }     if(maxAmt)
     {
      for(var cnt = 0; cnt < data.d.results.length; cnt++)
      {
       if(data.d.results[cnt].Role != "Coder 1" && data.d.results[cnt].Role != "Coder 2")
       {
        if(data.d.results[cnt].Amount > amount) 
        {
         AddUserToPPL(data.d.results[cnt].Title);
         return false;
        }
       }
      }
     }
    } 
   }, 
   error: function (xhr) { 
    alert(JSON.stringify(xhr));   
    alert(xhr.status + ': ' + xhr.statusText); 
   } 
  }); 
 }
}function AddUserToPPL(ApproverEmail) 
{
 var requestUri = _spPageContextInfo.webAbsoluteUrl + "/_api/web/siteusers/getbyemail(@v)?@v='" + ApproverEmail + "'";
 try 
 {
  NWF$.ajax({
   url: requestUri,
   type: 'GET',
   headers: { 'ACCEPT': 'application/json;odata=verbose' },
   success: GetApproverSuccess,
   error: GetApproverError
  });
 }
 catch (err) 
 {
  //jQuery('#errorMsg').html('getListData Error: ' + err);
 }
}function GetApproverSuccess(data) 
{
 //var Approver = data.d.GetUserProfilePropertyFor;
 var Approver = data.d.LoginName;
 var ApproverPicker = new NF.PeoplePickerApi('#' + IAssign);
 ApproverPicker.search(Approver).done(function (data) 
 { 
  //ApproverPicker.clear();
  ApproverPicker.add(data[0]);
 });
}function GetApproverError(sender, args) 
{
 //$get("results").innerHTML = "Error: " + args.get_message();
 approverClear();
} function getCoder(location)
{ 
 coderClear(); if(location != '')
 {  
  NWF$.ajax({ 
   url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('Approver Detail')/Items?$select=Location/Title,Title,Role&$expand=Location&$filter=Location/Title eq '" + location + "'",
   type: "GET", 
   headers: {"accept": "application/json;odata=verbose"}, 
   success: function (data)
   { 
    if(data != undefined && data.d != undefined && data.d.results != undefined && data.d.results.length > 0)
    { 
     for(var cnt = 0; cnt < data.d.results.length; cnt++)
     {
      if(data.d.results[cnt].Role == "Coder 1" || data.d.results[cnt].Role == "Coder 2")
      {
    if(cnt == 0)
   AddCoderToPPL(data.d.results[cnt].Title);
      }
     }
     //data.d.results[0].Title 
    } 
   }, 
   error: function (xhr) { 
    alert(JSON.stringify(xhr));   
    alert(xhr.status + ': ' + xhr.statusText); 
   } 
  }); 
 }
}function AddCoderToPPL(ApproverEmail) 
{
 var requestUri = _spPageContextInfo.webAbsoluteUrl + "/_api/web/siteusers/getbyemail(@v)?@v='" + ApproverEmail + "'";
 try 
 {
  NWF$.ajax({
   url: requestUri,
   type: 'GET',
   headers: { 'ACCEPT': 'application/json;odata=verbose' },
   success: GetCoderSuccess,
   error: GetCoderError
  });
 }
 catch (err) 
 {
  //jQuery('#errorMsg').html('getListData Error: ' + err);
 }
}
function GetCoderSuccess(data) 
{
 //var Approver = data.d.GetUserProfilePropertyFor;
 var Coder = data.d.LoginName;
 var CoderPicker = new NF.PeoplePickerApi('#' + ICoder);
 CoderPicker.search(Coder).done(function (data) 
 { 
  //CoderPicker.clear();
  CoderPicker.add(data[0]);
 });
}
function GetCoderError(sender, args) 
{
 //$get("results").innerHTML = "Error: " + args.get_message();
 coderClear();
} 
function coderClear()
{
 var CoderPicker = new NF.PeoplePickerApi('#' + ICoder);
 CoderPicker.clear();
}
function approverClear()
{
 var ApproverPicker = new NF.PeoplePickerApi('#' + IAssign);
 ApproverPicker.clear();
}
function cancel()
{
 window.location = "MyCompanyURL";
} 
//url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('Approver Detail')/Items?$orderby=Amount&$select=Location/Title,Department/Title,Amount, Title&$expand=Location, Department&$filter=Location/Title eq '" + location + "' and Department/Title eq '" + department + "' and Amount ge '" + amount + "'", function InvoiceUpdate()
function InvoiceUpdate()
{
  if(isEditMode )
  {
  debugger;
  var itemType1 = GetItemTypeForListName("Invoice Pending");
  var item1 = {
   "__metadata": { "type": itemType1 },
   "Title": NWF$("#" + _invoiceID).val(),
   "LocationId":NWF$("#" + ILocation).val(),
   "DepartmentId": NWF$("#" + IDepartment).val(),
   "InvoiceAmount": NWF$("#" + IAmount).val(),
   "InvoiceDate": NWF$("#" + _InvoiceDate).val(),
   "InvoiceDueDate": NWF$("#" + _InvoiceDueDate).val(),
   "AssignTo": NWF$("#" + IAssign).val(),
   "Coder": NWF$("#" + ICoder).val(),
   "Vendor": NWF$("#" + _VendorName).val(),
   "VendorNo": NWF$("#" + _VendorNum).val(),
   "Comment": NWF$("#" + _cmts).val()
  };  updateListItem(NWF$("#_invoiceID").val(), "Invoice Pending", _spPageContextInfo.webAbsoluteUrl, item1, function () {
   //amtCount = amtCount + 1;
   //updatePendingInvoice(amtCount); 
  }, function () { errorMsg = true; });
  }
  // Run Validation on Attachments
 function ValidateAttachment(source, arguments) {
      var Control = NWF$("#" + CtrlControl).val();
      var elm = NWF$("table[id*=idAttachmentsTable]");      // PRE ATTACHMENT CONTROL CHANGE
           var elmAttachmentRow = NWF$("table[id*=idAttachmentsRow]");      // POST ATTACHMENT CONTROL CHANGE           var elmAttachmentRow = NWF$("div[id*=idAttachmentsRow]");
      if ((elm != null && elm.prop('rows').length > 0) && (elmAttachmentRow != null)) {
           arguments.IsValid = true;
      }
      else {
           if (Control == "Yes") {
           arguments.IsValid = false;
           alert("Attachment Required")
           }
      }
 }
}function GetItemTypeForListName(name) {    return "SP.Data." + name.charAt(0).toUpperCase() + name.split(" ").join("").slice(1) + "ListItem";
}function getListItemWithId(itemId, listName, siteurl, success, failure) 
{
 var url = siteurl + "/_api/web/lists/getbytitle('" + listName + "')/items?NWF$filter=Title eq '" + itemId + "'";
    NWF$.ajax({
        url: url,
        method: "GET",
        async: false,
        headers: { "Accept": "application/json; odata=verbose" },
        success: function (data) {
         
            if (data.d.results.length == 1) {
             data.d.results[0].urls = url;
                success(data.d.results[0]);
            }
            else {
                failure("Multiple results obtained for the specified Id value");
            }
        },
        error: function (data) {
           
            failure(data);
        }
    });
}function updateListItem(itemId, listName, siteUrl, item, success, failure) {
 
    getListItemWithId(itemId, listName, siteUrl, function (data) 
    {
     NWF$.ajax({
            url: data.__metadata.uri,
            type: "POST",
            contentType: "application/json;odata=verbose",
            data: JSON.stringify(item),
            headers: {
                "Accept": "application/json;odata=verbose",
                "X-RequestDigest": NWF$("#__REQUESTDIGEST").val(),
                "X-HTTP-Method": "MERGE",
                "If-Match": data.__metadata.etag
            },
            success: function (data) { success(data); },
            error: function (data) { failure(data); }
        });
    }, function (data) { alert('Failed2'); failure(data); });
}
Labels: (1)
0 Kudos
Reply
11 Replies
jpmhuls
Nintex Newbie

Re: SharePoint Nintext NewForm Custom Javascript Require Attachment

Jump to solution

For Nintex Forms 2016 on-prem, there exists a Validation setting on the Attachment control where you can set the minimum number of attachments.

Using JS you have the function/method "NWF.FormFiller.Attachments.GetAttachedFilesCount" at your dispossal.

 

PS: if I understand Custom JavaScript requirements correctly, it is recommended to have the following snippet:

NWF$(document).ready(function(){
}

Within you can handle change events for certain controls. Any client click methods can be defined outside.

 

Hopefully this is enough to resolve your question.

0 Kudos
Reply
Automation Master
Automation Master

Re: SharePoint Nintext NewForm Custom Javascript Require Attachment

Jump to solution

If you're looking to Validate the Control, I'd suggest using the built in Rule System (either on the Control, or via the Rule Panel proper) to do it. 

However, if you're already doing that and you're just trying to call your ValidateAttachment() function from a rule, you're not going to be able to because its within the scope of the function named InvoiceUpdate(). Move ValidateAttachment() out to the global space if you're trying to invoke it from elsewhere. 

 

Maybe you're not trying to do either of those things and are instead just trying to do custom Validation completely bypassing the validation built into the forms. If that's the case it would be a lot more difficult to help you with the information provided (as you'd need to be handling the cancellation of the Submit, and in more explicit terms, show how you're calling / invoking the code below to initiate the Validation in the first place). 

----------

I wrote a giant post a long time ago on how to, for lack of a better term, 'self-reference' controls from the Rules that are being ran on them. Using the below pattern for a Validation Rule: 

(function(rowIndex) {
  "use strict";

  var internalElement = sourceContext.find("#" + rowIndex);

  return false;
}(rowIndex));‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

You should be able to easily do any particular tests and return either true (Failure) or false (Passing) based on what your code finds. 

Here is the link to the original post: https://community.nintex.com/t5/Community-Blogs/Breaking-The-Rules-A-Dive-Into-The-Nintex-Forms-Rule... 


 

0 Kudos
Reply
rdpDen
Nintex Newbie

Re: SharePoint Nintext NewForm Custom Javascript Require Attachment

Jump to solution

Thanks for the replies.

jpmhuls - I dont know where or how to include the document ready line or how to make use of it for requiring attachments.

 

The JS I posted is in Form - Settings - Custom Javascript&colon;

CustomJS.PNG

 

The Validation in the Attachements Control does nothing and my thinking is the Custom JS is overridding it?

Valid.PNG

nmarples giant post will certainly be a great resource as I learn enough to understand it but not as helpful from my current lack of skills/understanding and immediate need.

Would the suggested pattern for a Validation Rule be placed on my submit button?

 

I will be very grateful for any further assistance.

0 Kudos
Reply
Automation Master
Automation Master

Re: SharePoint Nintext NewForm Custom Javascript Require Attachment

Jump to solution

Because you have named a lot of functions in the global namespace, you very well might be overriding something, but off the top of my head, I wouldn't know if that's the case. 

Ideally when you have custom Javascript as you have, it's best to create a single new global variable that contains all of the functions / values that you'd like to reference or set during the course of your time spent on the form. 

instead of: 

function mySpecialFunction(){
  return "Hello World"; 
}

function theAnswerToLife(){
  return 42;
}


and then calling those functions like:

mySpecialFunction(); // "Hello World"
theAnswerToLife(); // 42


You can instead encapsulate them inside of a single Object:

var myNamespace = (function(){
  var mySpecialFunction;
  var theAnswerToLife;

  mySpecialFunction = function() {
    return "Hello World";
  };

  theAnswerToLife = function(){
    return 42;
  };

  return {
    mySpecialFunction: mySpecialFunction,
    theAnswerToLife: theAnswerToLife
  };
}());

 
Which you can then call using the following notation: 

myNamespace.mySpecialFunction(); // "Hello World"
myNamespace.theAnswerToLife(); // 42


As for the whole: 

NWF$(document).ready(function(){}


You don't really need to use that as your Javascript will load completely fine without it. 

To answer your question of, "Would the suggested pattern for a Validation Rule be placed on my submit button?", nope! You'd select your Attachment Control and then use the Add Rule button to place a new Validation Rule onto the control. 

So. At the top of your Ribbon in your Form Editor, look for this button: 
image.png

 

And you should see the Rule Panel pop out on the right side:
image.png

 

Select the Attachment Control in question, and again, at the top of your Ribbon click on the Add Rule button: 

image.png

 

A new Rule will pop up inside of the Rule Panel on the right side of your screen. From there you can configure the name, type, and add your code to the Rule which will run when the form tries to Validate the control: 
image.png

 

Just copy / paste the following code into the textarea:

(function(rowIndex) {
  "use strict";

  var internalElement = sourceContext.find("#" + rowIndex);
  debugger;

  /* This will always be invalid because we're returning true */
  return true;
}(rowIndex));‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍


As you can tell from the comments, this will ALWAYS make the control invalid. Additionally I have added in a Debugger line so if you open the Dev Console you should be able to play around during this validation phase to figure out what you *actually* want inside of there to meet whatever validation needs you have. 

Remember, in the real world you're not just going to always return true, and you'll need to obviously return true or false depending on your needs as mentioned previously. 

I hope that this helps you along the way. 


View solution in original post

Reply
rdpDen
Nintex Newbie

Re: SharePoint Nintext NewForm Custom Javascript Require Attachment

Jump to solution
Sincerely appreciate the clear detailed help!
When I put the rule as suggested on the attachments control and the debugger stops the page, I don't know how to interpret the results. When I remove the debugger the page freezes and validate attachments.

I would be glad to mark this as the solution as I am sure it would work although not for me specifically. I am in too deep and will have to find another approach entirely. I don't know how to work with code at this level well enough for these options.
0 Kudos
Reply
Automation Master
Automation Master

Re: SharePoint Nintext NewForm Custom Javascript Require Attachment

Jump to solution

Because I didn't exactly gather what it you were attempting to validate for the control, or in which way, I intentionally left it open ended. 

If you'd be willing to elaborate more on the problem you're trying to solve, in terms of your validation conditions, it would be easier to cook up something more specific that you might just be able to drop in and have work. 

(Note: That being said, when you open your developer tools (typically accessed by pressing F12 on your keyboard while in a browser), and you run into your debugger code, from there you should be able to play around in the console (typing javascript directly into there) in order to suss out exactly what you would end up putting into your code / validation rule proper so that it would happen every time the control ran it. The way that I wrote the rule will not really do anything on its own, and again is incredibly open ended and not meant for production stuff. Just to create a stopping point where you can play around with the Form in the state right before the final validation state is passed back to the function that determines whether or not to mark the control as Valid or Invalid.)




0 Kudos
Reply
rdpDen
Nintex Newbie

Re: SharePoint Nintext NewForm Custom Javascript Require Attachment

Jump to solution
I see! All I am looking to do is require the users attach one file to the form before a new item is created in SharePoint list.

Thanks so much!
0 Kudos
Reply
Automation Master
Automation Master

Re: SharePoint Nintext NewForm Custom Javascript Require Attachment

Jump to solution

You made a reply earlier where you input a minimum amount of attachments for the Control (link: https://community.nintex.com/t5/Nintex-for-SharePoint/SharePoint-Nintext-NewForm-Custom-Javascript-R...), but I suppose that didn't work? 

If you're unsure whether or not  your custom Javascript is interfering with this, I'd recommend just removing all of your custom code and then testing to see if the form will validate correctly. 

From there you can slowly add back functions one by one, to see if they mess with anything. 

You shouldn't need a custom function to do what you're trying to do. 

0 Kudos
Reply
rdpDen
Nintex Newbie

Re: SharePoint Nintext NewForm Custom Javascript Require Attachment

Jump to solution

I have tried to use the OOB minimum amount setting and it does not work in PROD however it does in a DEV site.  I am going to look for differences between the two and try your suggestions to iterate through adding in functions... I'll update when I get through some of that.

 

Thanks for your continued support!

0 Kudos
Reply