You are viewing limited content. For full access, please sign in.

Question

Question

Forms Designer - How do you prevent negative currencies in a currency field?

asked on May 9 Show version history

I can not find anything in the designer that allows me to set this.

I tried this script but for some reason it is unreliable, sometimes working and sometimes not.

  $(document).ready(function() {
    $('.finalTotal input').attr('min',0)
  })

There is no errors in the console and if you check the field it does not show the attribute in many cases where users can still put negative values in the field.

What is the simplest way to make a positive value only currency field?

Update: I just realized it must be breaking on read-only fields as this field is read only. But why? The limitation should still be there.

0 0

Replies

replied on May 9

Under Advanced, you can enable range limiting with a minimum value of 0:

1 0
replied on May 9

Oh I am in version 11 with this environment and I don't see this. Maybe it is a feature of 12?

What version are you in?

0 0
replied on May 9

Darn! I'm on Cloud, but this isn't a new feature as far as I can remember.

Do you have the option in number fields by any chance?

0 0
replied on May 9

Yea I see it in Cloud. I also checked Version 12 On-Prem and I don't see it. I can do it for any other non currency number on the general tab and it looks like the screenshot below. Only currency does not allow me to set a range in the editor. The option exists because we can access it with JS, but it is not shown and the JS is not reliable.

For example we want to prevent submitting a form with a total as a negative value but the total field is populated as a total of other fields so the field itself is read only.

0 0
replied on May 9

Check the Advanced tab on the Currency field.  This is from the latest Forms 11 

1 0
replied on May 9

You could also set up a field rule to hide the submit button when the total field is less than 0, if that's an option for you?

Weird you're not seeing range limiting under Advanced though.

0 0
replied on May 9

Seems the range on currency fields is only in the modern designer, all these forms are in Classic.

If I hide the submit button I also need to show a message near the field, which would work but not as clean as just limiting the range to above 0.

I guess there are custom solutions, but not sure why the min attribute is breaking on me on read only fields.

0 0
replied on May 9

Hi @████████, try this JS code. It is for Classic Form. Let me know if help. 

 

$(document).on('ready.lfForm refresh-view.lfForm', function () {
  $('#Field75')                       // change to your selector
    .attr({
      'data-parsley-pattern' : '^\\$?(0|[1-9]\\d*)(\\.\\d{1,2})?$',
      'data-parsley-pattern-message' : 'Amount must be zero or positive'
    });
});

 

1 0
replied one day ago

Tried this alternative attribute today without any luck either. I narrowed down the working vs non-working scenarios and found that forms which use the .val().change() method to set the total from JS do not work, while forms that use calculations to set the total do work.

As a workaround I am setting the maximum value on the input fields that the user enters in a way so that they can not create a negative total. This way they can still write JS to total when needed. Some forms use calculations for simpler calculations and some us JS for more complex calculations.

So when applying min and/or max attributes for a field it always works if the user has direct access to the field, but not when using .change() in JS to set a total.

readonly or not does not matter.

0 0
replied one day ago

Try this other way: 

Create a Custom HTML object near your field. with this code inside: 

<!-- Error container for the currency field -->
<span id="err1" class="currency-error" style="display:none;"></span>

You can customize the id="err1" by any number you want. I prefer to put the same number as the input field. I need the alert, that way I never lose track. 

Keep the ID you put there, because you need to put the same in the JS code I will share next. 

$(document).ready(function () {

  const $currency = $('#Field1');           // <- update ID if needed.
  const $error    = $('#err1');

  // ------------- core validation -------------
  function validateCurrency() {
    let val = parseFloat($currency.val());

    // Treat empty or non-numeric as zero
    if (isNaN(val)) { val = 0; }

    if (val < 0) {
      // Show visual error
      $currency.addClass('invalid-negative');
      $error.text('Amount cannot be negative.').show();
      return false;                          // invalid
    } else {
      // Clear error state
      $currency.removeClass('invalid-negative');
      $error.hide();
      return true;                           // valid
    }
  }

  // ------------- event hooks -------------
  // 1) Manual typing
  $(document).on('input change', '#Field75', validateCurrency);

  // 2) Scripted changes (.val(), calculations, etc.)
  //    Laserfiche can rebuild the input; validate every 300 ms as backup.
  setInterval(validateCurrency, 300);

  // 3) Final safety net on submit
  $('form').on('submit', function (e) {
    if (!validateCurrency()) {
      e.preventDefault();                    // block submit
      alert('Currency value cannot be negative. Please correct it.');
    }
  });

});

Then using this CSS:

/* Red border when the value is invalid */
.invalid-negative {
  border-color: #d9534f !important;
}

/* Style for the inline error message */
.currency-error {
  color: #d9534f;
  font-size: 0.85rem;
  margin-left: 6px;
}

I tried it and it works for me. Let me know. 

-----

(Optional)

Another approach to prevent users type "-" in the input field. Replace my #Field1 by your input Field field id: 

$(document).on('keydown', '#Field1', function (e) {
  if (e.key === '-' || e.keyCode === 189) {
    e.preventDefault();           // prevents the “-” sign from being typed from the keyboard
  }
});

0 0
replied one day ago

This looks similar to using a field rule that displays a message and hides the submit button. But setting the maximum value on fields that can produce a negative number is cleaner. You have no custom HTML objects and the message appears directly under the field.

Users can produce a negative number by entering only positive numbers in currency fields. For example when entering the amount to use from a gift card.

If I apply $100 against my gift balance and it reduces the total below 0. That is why on these fields we are setting the max attribute so that the total is always above 0.

0 0
replied one day ago

Now I understand your scenario better. At first, it wasn't entirely clear to me, which is why I was giving you a different solution for a different problem. Sorry for not understanding from the start.
The code I'm about to give you was saved from another project for something similar that was once used. That project is no longer active, but I saved the JavaScript. Take a look and see if you can get some use out of it.

 

// -----------------------------------------------------------------------------
// Prevent “Gift Card Used” from creating a negative Total
// -----------------------------------------------------------------------------

$(document).ready(function () {

  const $subtotal = $('#Field10');   // Sub-total of the order
  const $gift     = $('#Field11');   // Amount of gift-card applied
  const $total    = $('#Field12');   // Calculated Total (read-only)

  /**
   * Recalculate limits, validate the gift-card field,
   * and update the Total so it can never drop below 0.
   */
  function syncLimits() {
    const subVal  = parseFloat($subtotal.val()) || 0;
    const giftVal = parseFloat($gift.val())     || 0;

    // 1) Update Parsley’s max rule on the Gift-Card field
    $gift.attr({
      'data-parsley-max'         : subVal,
      'data-parsley-max-message' : 'Cannot exceed order total'
    });

    // 2) Force Parsley to validate immediately
    $gift.parsley().validate();

    // 3) Recalculate the Total and clamp it to ≥ 0
    const newTotal = Math.max(0, subVal - giftVal);
    $total.val(newTotal.toFixed(2));   // show two decimal places
  }

  // --------------------------- Event hooks ---------------------------

  // Re-sync whenever the user edits Sub-total or Gift-Card fields
  $(document).on('input', '#Field10, #Field11', syncLimits);

  // Safety net: re-sync every 300 ms in case the form rebuilds inputs
  setInterval(syncLimits, 300);

  // Final guard: block form submission if the Gift-Card value is invalid
  $('form').on('submit', function (e) {
    if (!$gift.parsley().isValid()) {
      e.preventDefault();            // stop the submit
    }
  });

  // Initial run on page load
  syncLimits();
});

 

0 0
replied one day ago

It seems the data-parsley attributes are what do not trigger on a change() event for some reason. Only when users work with the field. This is why it does not work for read-only total fields that are calculated with a script.

0 0
You are not allowed to follow up in this post.

Sign in to reply to this post.