0

I'm creating a script that will override submit form functionality when the save button is clicked. The goal is to validate user input by checking if a combination of columns already exists within a list. If the combination exists it will alert the user that their input is not unique and to enter in new input. The first column, "Name", is of type single line of text. The second column, "Training", is a choice column.

Ex: If the list already has the name "Bob" and "T1" then this combination cannot be duplicated. If the user attempts to input the same values, "Bob" and "T1" , when they click the save button it should throw an alert. "Bob" and "T2" is unique would allow the user to submit that form.

<script type="text/javascript" src="/JS/jquery-1.3.2.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
});
//PreSaveAction code to validate
function PreSaveAction()
{
  //Name variable
  var name = $('input[title="Name"]').val();
  //Training Variable
  var training = $('input[title="Training"]').val();
  
  //I'm trying to find a way to iterate through my list and compare the values that the user 
  //has just input to the existing list items and if there is a match then 
  //give an alert and return false 
  //also I'm assuming that an array might be beneficial to hold the variables?
  
  if(this.name & this.training !=null)
  {
  alert('Name and training already exist. Please Input Unique Values');
  return false;
  }
  else
  {
    return true;
  }
</script>

Any help with this would be appreciated , really stuck.

1 Answer 1

0

Yeah, this is a tricky problem, having to interrupt PreSaveAction to do some sort of async validation before you really know what you want to return from PreSaveAction.

How I have handled it in the past is to basically

  • have a flag set to false to indicate whether I made my check
  • when PreSaveAction fires, check the flag, if it's set one way, start the validation, but return false from PreSaveAction to prevent the item from saving
  • do the validation
  • set the flag to indicate the validation is done
  • re-trigger PreSaveAction by simulating another click on Save from code

Some example code so you get the idea:

// declare some variables outside the scope of any function
// so you can access them from anywhere
var madeValidationCheck = false;
var duplicateFound = false;

$(document).ready(function() {
    // whatever you have in here
});

function PreSaveAction() {
    // once PreSaveAction fires, see if you have done your validation
    if (!madeValidationCheck) {
        // the validation check hasn't happened yet, so we need to start that off.
        // since it is async and might take some time, i like to show the user that something is happening
        // so they don't get antsy
        $('input[id$="SaveItem"]').before('<img class="waitImage" src="' + _spPageContextInfo.webServerRelativeUrl + '/_layouts/15/1033/images/progress16.gif" />');
        // now we start our function that has the async code in it
        DoAsyncValidation();
        // now, since we are waiting for the async validation
        // to finish, we _don't_ want the form to save yet so:
        return false;
    } else {
        // our madeValidationCheck is true, so we must have our validation
        // result by now, so clear the visual cue for waiting,
        // and return the _actual_ result we want from the validation,
        // which could eb either true or false
        $('img.waitImage').detach();

        // you could optionally show your alert here
        if (duplicateFound) {
            alert('duplicate found!')
        }

        return !duplicateFound;
    }
}

function DoAsyncValidation() {
    // get the values that you want to check
    var name = $('input[title="Name"]').val();
    var training = $('input[title="Training"]').val();

    // you don't need to iterate over anything. you can find out if
    // any items in your list have this value combination by using
    // a REST query and filtering for items that have both of these values
    var itemRequest = "https://your-server/sites/your-site/_api/web/lists/getbytitle('Your List')/items?$filter=Name eq '" + name + "' and Training eq '" + training +"'";
    $.ajax({
        url: itemRequest,
        method: 'GET',
        headers: {
            accept: 'application/json;odatat=verbose'
        }
    }).done(function(data) {
        // if you get _any_ results, you found a match
        // for that value pair, so all you care is if
        // you got more than zero results
        if (data.d.results.length > 0) {
            duplicateFound = true;
            // or you could optionally alert your error message here
            alert('duplicate found!')
        } else {
            duplicateFound = false;
        }

        // ok, now we have our validation results so
        // set the flag that you check in PreSaveAction
        madeValidationCheck = true;

        // and then trigger PreSaveAction again by "clicking" the save button
        $('input[id$="SaveItem"]').click();

    }).fail(function(jqXhr, status, error) {

        // not sure what you want to do if the REST request failed.
        // you could force the form not to save by pretending that the validation failed

        duplicateFound = true;
        madeValidationCheck = true;
        alert('sorry there was an error')
        $('input[id$="SaveItem"]').click();

        // OR
        //
        // you could have another flag variable for this case
        // which you could set here and check back in PreSaveAction
        // to know not to show the "duplicate found" message
        // but instead show a different error
        // but still return false from PreSaveAction again
        // to make sure the item is not saved

        // many ways to handle this, i can't really tell you what to do here
    });
}
21
  • This really helps a lot. So if I understand correctly, in the DoAsyncValidation function if the data results are less than 1, it would return false and change the PreSaveAction flag to true. This would allow the user to save because that is a unique combination.
    – Will Simz
    Oct 14, 2021 at 23:55
  • If the data results are anything greater than zero, duplicateFound is set to true, then when the PreSaveAction runs for the second time it will return !duplicateFound i.e. "not" duplicateFound i.e. "not" true i.e. false, which is what you would want PreSaveAction to return to prevent saving. If the results are zero, duplicateFound is set to false (because no duplicates were found), so the second PreSaveAction returns !duplicateFound i.e. "not" false i.e. true, which is what you want PreSaveAction to return when no duplicates are found and it's OK to save. Oct 15, 2021 at 2:28
  • After implementation , its giving duplicate found alerts even with combinations that don't exist in the list are entered. Is there any way around this ?
    – Will Simz
    Oct 26, 2021 at 16:57
  • I believe its caused by the API request failing because it will always give the 'Sorry there was an error' alert.
    – Will Simz
    Oct 26, 2021 at 17:40
  • Then you need to figure out how to get the API call to work. My first guess is that the internal names of the columns you are checking against are not actually "Name" and "Training" because I don't know how you have your list set up. When you set up the API call to $filter for items, you need to use the internal column names. And again, I wrote extensively in the comments that I can't really tell you what to do if you get an API call error. If you don't want it to trigger a "duplicate found" alert then figure out how to do that. Oct 26, 2021 at 18:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.