0

Situation: I have a list with 2 columns (ActYear and LastNumber). Both column conatains only 1 number element. The ActYear contains the current year and the LastNumber is the number of items created this year.

How should my code works: When the user click on the "save" button the script get the number from ActYear and compare to the current year. If the number is not to same that means this is the first process of the new year so it refresh the ActYear to the current year and reset the LastNumber to 1. But if this is not to first process of the year simply need to update the LastNumber with +1.

What happens if I run: I belive the new year part of the if working fine or I didn't test enough time to get an error. But if I test the simply +1 side of the if I have about 10-20% chance that the LastNumber field ll be not updated. I don't get the reason why fail sometime. Also if I wanna use brutal force to test it and put the whole +1 upgrade into a for 100 time to see how many % is the unsuccesful process it is not works at all (or if run not update or only very rarely). (Maybe .get() not work many time in a row). Also I don't get any error message on the console, or it vanish so fast I can't see it. (When I press the "save" it go to the default list view page from the new view)

UPDATE: I simplified the code based on the tips and after testing sharepointplus quite a lot. Now I have about 30% chance to fail still don't get why not any error and fail randomly.

UPDATE2: I tested the new year part of the If about 30 time, but I didn't got any error. I changed the +1 part to create a variable with the math part and the update give the LastNumber that value of the variable. This way fails only about 5% of the time. So adding number to number inside the update process was related to have about 30% fail rate. But 5% is still a problem it have to be perfect.

UPDATE3: I added an alert after the variable generation. After about 40 test I noticed, the alert sometime not appear or the number in the alert shows the default number of the LastNumber not the LastNumber+1. So I guess the program is doing all the work parallel and sometime the alert fire when the +1 is not calculated yet or the update finish before the alert or the calcualtion. So looks like I have to ensure somehow the correct order. So the update must be run after the calculation done. Can u tell me, how to force that?

    function PreSaveAction()
{
$(function ()
{
  $SP().list("TargetList","http://.../sites/Registry/").get(
  {
    where: "ID=1"  //get the first row only, I have only 1 row so this gets everything :)
  },
  function getData(data)
  {
    for (var i = 0; i < data.length; i++)
    {
      if((Number(data[i].getAttribute("ActYear"))) < (Number(new Date().getFullYear())))
      {
        $SP().list("IktatoKonyvLista","http://.../sites/Registry/").update(
        [{ID:1, ActYear: Number((new Date()).getFullYear())}, {ID:1, LastNumber: Number("1")}]);
      }
      else
      {
          var calc = (Number(data[i].getAttribute("LastNumber"))+Number("1"));
          alert(calc);
          $SP().list("TargetList","http://.../sites/Registry/").update(
          {ID:1, Sorszam: calc}); 
      }
    }
  });
});
    return true;
}

I am using jquary and sharepointplus. I am a beginer with both so it can be a trivial mistake. If u have any tips what to test or how to make is "fail safe" pls let me know! Thank you very much for your kind help!

2 Answers 2

1

You're trying to use a synchronized function (preSaveAction()) with an asynchronize code (your requests against the server).

It's why it doesn't work.

You should use this blog post that explains what to do to proceed with async code before saving a Sharepoint form. I'll recopy the code from the blog post and mix it with your code:

// this function will execute your code
function beforeSaving() {
  var deferred=jQuery.Deferred();
  // your code here
  // please note that "http://.../sites/Registry/" is not required if the list "TargetList" is into the same website
  $SP().list("TargetList","http://.../sites/Registry/").get({where:"ID=1"}, function getData(data) {
    // your request will return 1 item because you use "ID=1"
    // so I change a bit your code:
    if (data.length===1) {
      if((Number(data[0].getAttribute("ActYear"))) < (Number(new Date().getFullYear()))) {
        // The params for Update should be different.... Let me fix it:
        $SP().list("IktatoKonyvLista","http://.../sites/Registry/").update({ID:1, ActYear: Number((new Date()).getFullYear()), LastNumber: Number("1")}, {
          after:function() {
            // you now need to indicate the operation has been completed:
            deferred.resolve();
          }
        });
      } else {
        var calc = (Number(data[0].getAttribute("LastNumber"))+Number("1"));
        alert(calc);
        $SP().list("TargetList","http://.../sites/Registry/").update({ID:1, Sorszam:calc}, {
          after:function() {
            // you now need to indicate the operation has been completed:
            deferred.resolve();
          }
        }); 
      }
    }
  });
  return deferred;
}

// force PostBackRequired to true in the context, otherwise it won't work if you open the into a modal
// Please note that "WPQ2FormCtx" may change depending of your server...
// Look at the source code of your page to find "FormCtx" and verify this variable is correct
WPQ2FormCtx.PostBackRequired=true;

// we override SPClientForms.ClientFormManager.SubmitClientForm
SPClientForms.ClientFormManager.SubmitClientForm=function(b){
  var a=SPClientForms.ClientFormManager.GetClientForm(b);
  var res = (a!=null&&a.SubmitClientForm());
  // if the form is not valid, then res===true
  if (res === true) return true;
  else {
    // if the form is valid we now want to do our asynchronous check
    beforeSaving().done(function() {
      // our test is valid too so we can send the form to the server
      WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions($get(WPQ2FormCtx.SubmitButtonID).name, "", true, "", "", false, true))
    }).fail(function() {
      // if it fails we just unblock the save button
      $get(WPQ2FormCtx.SubmitButtonID).disabled=false;
    })
  }
  // to make sure the form won't be submitted yet
  return true;
};
1
  • WoW. Thank you very much for the detailed comments it is rly worked well! Just I need to analize a bit more to understand every aspect ot this code. And thank you for creating sharepointplus, it makes everything easier! :)
    – Nefri
    Oct 11, 2017 at 9:19
1

Remove the

$(document).ready(function ()

And the opening and closing braces and parens. This does not belong here. This is a jquery function call that executes code when a page is finished loading. That’s not what you need here - the page is already loaded.

Also, what’s the point of “if (true)”?

3
  • I updated the code based on your tips and some testing. Pls take a look. And thanks you very much for your help!
    – Nefri
    Oct 10, 2017 at 8:47
  • 1
    I have not used the SP library you are using (I use SPServices). Are the $SP calls asynchronous? If so that could be the source of your inconsistency. Is there an option to make them synchronous or use something like promises?
    – mannaggia
    Oct 11, 2017 at 0:29
  • Yeah in the end I figured out I should use .then() to solve this.
    – Nefri
    Oct 11, 2017 at 7:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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