Cutom Validation Doesn't Work Depending on Input Method

Hello,

I am working on a public form and I am running into an issue where the validation I set up only works if I manually enter in a value but not when it is automatically filled in.

The form will be used to make purchase requests. The user is meant to enter in the total cost of their requests, and we need the value they enter to be compared to the budget in our system. To make this work, I have added a drop down that is connected to an excel document where they select their system, and in the excel document there is a budget associated with each system. With JavaScript I then pull the value of the budget and pass it into a variable (or another hidden currency field). From this point more JavaScript compares the pulled budget value with the total cost value they entered and if the cost is over budget, it triggers a validator so they cannot submit the form.

I got nearly all of this to work. The drop down correctly grabs the budget associated with the system they select and dumps the value into either a variable or a field.

The issue I am running into is that the validation does not work when the value is auto entered based on their selection, but it works perfectly fine if I manually enter it in the currency field.

Does anyone have any idea why this happens? Thank you in advance.

Code:

fd.rendered(function() {

var SelectedSystem = fd.field('SystemSelect');
SelectedSystem.$on('change', function(value) {
    var SystemData = SelectedSystem.selectedItem;
    if (SystemData) {
        fd.field('HiddenBudget').value = SystemData.SystemBudget;
    } else {
        fd.field('HiddenBudget').value = null
    }
});

fd.field('BoqPrice').addValidator({
    name: 'Over Budget',
    error: 'your BOQ Total Price is Over Budget.',
    validate: function(value) {
        if (fd.field('HiddenBudget').value < value) {
            return false;
        }
        return true;
    }
});

});

@UIS_IT,

It seems the issue you're encountering is related to the timing of the validation logic in your Plumsail Form. When the budget value is auto-filled by selecting an option in the dropdown, the validator for the BoqPrice field does not trigger automatically because it only triggers on manual input by default.

To address this, you need to ensure that the validation runs not only when the user manually enters a value but also when the HiddenBudget field is auto-filled. Here's an enhanced version of your code that should resolve the issue:

fd.rendered(function() {

    var SelectedSystem = fd.field('SystemSelect');
    var HiddenBudget = fd.field('HiddenBudget');
    var BoqPrice = fd.field('BoqPrice');

    SelectedSystem.$on('change', function(value) {
        var SystemData = SelectedSystem.selectedItem;
        if (SystemData) {
            HiddenBudget.value = SystemData.SystemBudget;
        } else {
            HiddenBudget.value = null;
        }
        // Trigger validation after the budget is auto-filled
        BoqPrice.validate();
    });

    BoqPrice.addValidator({
        name: 'Over Budget',
        error: 'Your BOQ Total Price is Over Budget.',
        validate: function(value) {
            if (HiddenBudget.value < value) {
                return false;
            }
            return true;
        }
    });

    // Run the validation when the form is loaded in case values are pre-filled
    fd.rendered(function() {
        BoqPrice.validate();
    });

});

Explanation:

  1. Trigger Validation on Change: The BoqPrice.validate(); is called right after the HiddenBudget value is set. This ensures that if the HiddenBudget is updated due to the selection change, the BoqPrice validator will run immediately.
  2. Initial Validation: The BoqPrice.validate(); within the fd.rendered function ensures that the BoqPrice field is validated when the form is initially loaded, covering cases where the budget might already be set.

Hi @UIS_IT,

You can force validation after changing the field value with this line:

fd.field('FieldName').validate();

Thank you for the reply! I attempted to integrate your code but the same issue still persists. I also kept your code the same but changed all of the BOQPrice.validate(); to fd.field(BoqPrice).validate(); but it still didn't work.

One positive is that the final validation that runs when the form is loaded does correctly validate the values, even if they were auto filled. They still do not properly validate if it is auto entered before reloading, however. Thank you again for your help!

Thank you for your assistance! After integrating this code it unfortunately still did not work. Do you have any other suggestions?

@UIS_IT

It sounds like the core issue is that the validator isn't triggering correctly when the value is auto-filled, despite running properly on form load.

fd.rendered(function() {
    var SelectedSystem = fd.field('SystemSelect');
    var HiddenBudget = fd.field('HiddenBudget');
    var BoqPrice = fd.field('BoqPrice');

    // Function to trigger validation with a small delay
    function triggerValidation() {
        setTimeout(function() {
            BoqPrice.validate();
        }, 100); // 100ms delay to ensure values are set
    }

    // Update HiddenBudget and trigger validation when system changes
    SelectedSystem.$on('change', function() {
        var SystemData = SelectedSystem.selectedItem;
        HiddenBudget.value = SystemData ? SystemData.SystemBudget : null;
        triggerValidation(); // Validate after updating budget
    });

    // Validate BoqPrice against HiddenBudget
    BoqPrice.addValidator({
        name: 'Over Budget',
        error: 'Your BOQ Total Price is Over Budget.',
        validate: function(value) {
            return HiddenBudget.value >= value;
        }
    });

    // Initial validation on form load
    triggerValidation();

    // Re-validate BoqPrice when its value changes
    BoqPrice.$on('change', triggerValidation);
});

Explanation of the Updated Code:

  1. Manual Validation Trigger (triggerValidation): A function triggerValidation is introduced to centralize the validation logic. This function is called every time we want to ensure the validation runs, particularly after HiddenBudget or BoqPrice changes.
  2. Change Listeners:
  • The SelectedSystem field change triggers an update to the HiddenBudget and then calls triggerValidation to check if the BoqPrice is within the budget.
  • The BoqPrice field itself is now also monitored for changes. If the user modifies it (manually or through any other script), the validation runs again.
  1. Synchronization: By explicitly triggering validation after any relevant field is updated, we ensure that any changes (manual or automatic) are immediately validated.
  2. 100ms Delay: Added a setTimeout with a 100ms delay before triggering the BoqPrice.validate() to ensure that the HiddenBudget value is fully set before validation runs.

Try these adjustments and let us know how it goes.

Thank you for the help! It is so close. It now correctly sees if the item is over or under budget, but if it is over budget and then they adjust the boq price to be below the budge the validator does not correctly see the value was changes and still says it is over budget despite the change. Any ideas on what to do? Thank you again!

Hi @UIS_IT,

Try updating @TN.DVS's code like this:

fd.rendered(function() {
    var SelectedSystem = fd.field('SystemSelect');
    var HiddenBudget = fd.field('HiddenBudget');
    var BoqPrice = fd.field('BoqPrice');

    // Function to trigger validation with a small delay
    function triggerValidation() {
        setTimeout(function() {
            BoqPrice.validate();
        }, 100); // 100ms delay to ensure values are set
    }

    // Update HiddenBudget and trigger validation when system changes
    SelectedSystem.$on('change', function() {
        var SystemData = SelectedSystem.selectedItem;
        HiddenBudget.value = SystemData ? SystemData.SystemBudget : null;
        triggerValidation(); // Validate after updating budget
    });

    // Update HiddenBudget and trigger validation when BOQ price changes
    BoqPrice.$on('change', function() {
        var SystemData = SelectedSystem.selectedItem;
        HiddenBudget.value = SystemData ? SystemData.SystemBudget : null;
        triggerValidation(); // Validate after updating budget
    });


    // Validate BoqPrice against HiddenBudget
    BoqPrice.addValidator({
        name: 'Over Budget',
        error: 'Your BOQ Total Price is Over Budget.',
        validate: function(value) {
            return HiddenBudget.value >= value;
        }
    });

    // Initial validation on form load
    triggerValidation();

    // Re-validate BoqPrice when its value changes
    BoqPrice.$on('change', triggerValidation);
});
1 Like

@IliaLazarevskii Thank you for sharing the updated code. The approach you've provided should indeed do the trick, particularly in ensuring that the validation runs correctly when changes occur.

However, just a small note—if the HiddenBudget is intended to remain constant once set by the system selection, there could be a potential for unexpected behavior by reassigning it when the BoqPrice changes. If @UIS_IT notices any issues or needs further adjustments, we'd be happy to help refine the logic to ensure everything works as hoped.

2 Likes

Hi @TN.DVS, @UIS_IT

I had the impression that HiddenBudget should always correspond to the current value of SystemData. If it's not the case, then the code should be adjusted like so:

BoqPrice.$on('change', function() {
    triggerValidation(); // Validate without updating budget
});
2 Likes

Thank you both for your help! There is one issue remaining. It seems to think every value is too high now, including if the hidden budget value is empty. I have attached some examples.
I really appreciate all of your assistance. I have tried adjusting the code myself, specifically the validator, but run into the same or other issues.

PS- Ignore the disable field, I was using that for testing but it has since been deleted and the same issues persist