Throw Error on SpBeforeSave

Hi,
I need to throw an error if certain values are not true. The values are in a different list so I am doing the code like this

fd.spBeforeSave(function ()
{
var id = fd.field('ID').value;
var length = 0;
var string = "Bid_x0020_Line_x0020_ID eq " + id + " and Submit ne false";

sp.web.lists.getByTitle("Bid Type Lines").items.filter(string).get().then(function(items)
{
    length = items.length;
    if (length == 2)
    {
        fd.field('Modify').value = false;
        throw Error('Technical and Commercial both are required.');
    }   
});

});

The code is working fine and is returning the count/values which I need but its not changing the value of field Modify and throw Error is not working as well. Is there any way to achieve this.

Hello @Ramiz,

To update a field on the form, you need to add code outside of asynchronous function like this:

fd.spBeforeSave(function (){
    pnp.sp.web.lists.getByTitle('ListName').items.get().then(function(items){
    					length = items.length;
    					return length;
    }).then(function(length){
    	if(length == 3){
    		fd.field('Title').value = 'works';
    		alert('done!')
    	}
    })
});

To show error on the form when submitting the form, you need to add a form validator. Please find more information here

fd.validators.push({
    name: 'MyCustomValidator',
    error: "Custom Error message",
    validate: function(value) {
          pnp.sp.web.lists.getByTitle('ListName').items.get().then(function(items){
    					length = items.length;
    					return length;
          }).then(function(length){
    	     if(length == 3){
    		return false
    	     }
             return true
          })
    }
});

Hi @mnikitina

I tried this but in any case I am receiving the error message. Kindly see the attach image and my code.

var length = 0;
var string = "Bid_x0020_Line_x0020_ID eq " + id + " and Submit ne false";

fd.validators;
fd.validators.push(
{
    name: 'SubmissionValidator',
    error: "Please submit both technical and commercial.",
    validate: function(value) 
    {
        pnp.sp.web.lists.getByTitle("Bid Type Lines").items.filter(string).get().then(function(items)
        {   
			length = items.length;
            return length;
        }).then(function(length)
        {
            alert(length);
	        if(length == 1 || length == 0)
            {   
                alert(false);
		        return false;
	        }
            return true;
        });
    }
});

My condition is if length equal to 0 or 1 then throw error but as you can see in my screenshot its returning length 2 but still the error is showing and I cant submit the form.

@Ramiz,

Please try out this code instead:

var length = 0;
var string = "Bid_x0020_Line_x0020_ID eq " + id + " and Submit ne false";
pnp.sp.web.lists.getByTitle("Bid Type Lines").items.filter(string).get().then(function(items)
{   
    length = items.length;
    return length;
}).then(function(length)
{
    fd.validators.push(
    {
        name: 'SubmissionValidator',
        error: "Please submit both technical and commercial.",
        validate: function(value) 
        {
                alert(length);
                if(length == 1 || length == 0)
                {   
                    alert(false);
                    return false;
                }
                return true;
        }
    });
});

Hi @mnikitina

Thank you for your help. This code works fine but this doesnt refresh since the pnp code is on spRendered it works when I open the form. After opening the form If I receive the error and I fixed by submitting all documents which is a list or library control the length variable still contains value 1 .

I rearranged the code on submit button like this.

var length = 0;
var string = "Bid_x0020_Line_x0020_ID eq " + id + " and Submit ne false";

fd.toolbar.buttons[0].text = "Submit";
fd.toolbar.buttons[0].click = function()
{
    pnp.sp.web.lists.getByTitle("Bid Type Lines").items.filter(string).get().then(function(items)
    {   
        length = items.length;
        return length;
    }).then (function(length)
    {
        if (length == 2)
        {
            fd.field('Submit').value = true;
        }
    });
    fd.save();
    fd.close();
}

And on spBeforeSave

fd.spBeforeSave(function ()
{
if (fd.field('Submit').value == false)
{
throw Error('Please submit both technical and commercial.');
}
});

This works fine for me. I am checking how can I rearrange the code to use validators but thank you for the help. Really appreciated.

1 Like

Hello @Ramiz,

Are you using List or Library control for displaying all related items from the Bid Type Lines list?

Then you can add validation based on the List or Library control values.

Hi @mnikitina

Yes I am using the list or library control to display related items.
Add validation based on list or library control means add event function on list or library control like this

fd.control('SPDataTable0').$on('change', function(changeData)
or
fdfd.control('SPDataTable0').validator?

@Ramiz,

You can add validator that checks the length (count of records) of the List or Library control, for instance:

fd.spRendered(function() {
	
	fd.validators;

	fd.validators.push({
		name: 'SPDataTable validator',
	    error: 'Error message',
	    validate: function() {
	        if (fd.control("SPDataTable0").widget.dataItems().length < 3) {
	            this.error = "Technical and Commercial both are required.";
	            return false;
	        }

	        return true;
	    }
	});

});
1 Like

Hi @mnikitina

Thanks for the help. You did mention above to assign/update value we need to add code outside of asynchronous function

lines.items.filter(myfilter).get().then(function(items)
{
    alert(items.length);
    no = items[0].Title;
    return no;
}).then(function(no)
{
    fd.field('Title').value = 'works';
    alert('done!');
});

When I am saving the form the value appears in the Title field but when the form closes the field disappears and its empty.

Hello @Ramiz,

Under which event are you running the code? spBeforeSave or spRendered?

I am running under spBeforeSave.

@Ramiz,

Try out adding return statment before PnP request and in the end of the function like this:

fd.spBeforeSave(function (){
        return lines.items.filter(myfilter).get().then(function(items)
    {
        alert(items.length);
        no = items[0].Title;
        return no;
    }).then(function(no)
    {
        fd.field('Title').value = 'works';
        alert('done!');
        return true;
    });
});

@mnikitina

This doesnt work as well. However I did a work around. I am using pnp.items.getById(1).update function to update. The only thing is I need an ID for this to work and I can only get the id on fd.spSaved. This is my code.

    fd.spSaved(function (result) 
{
    var id = result.Id;
    generateReferenceNo(id);
    
});

function generateReferenceNo(id) 
{
var number = 0;
var lastNo = '';
var refNo = '';
var bidding = pnp.sp.web.lists.getByTitle("Bidding");

            
            bidding.items.getById(id).update(
            {
                Reference_x0020_No: refNo,
                NoSeries: true
            }); 
}

I would like to know is it possible to create a record when I fill my title field. Actually I am coming from Microsoft Dynamics NAV background and I am trying to make it in same way.
If I put a value in title field is it possible to insert the record and create the ID so that I can use that.

I tried using the change event of field title and put fd.save() there but that closes the form as well.
My requirement is to generate an auto generated number for each record.
Demo

Hello @Ramiz,

You can run PnP request under spSaved event to update the Reference number column. Please see the code example in this post:

And then redirect the user to the edit form:
https://plumsail.com/docs/forms-sp/how-to/redirect-sp-save.html#redirect-to-edit-form