Require field based on value in another field (ktl)

I have a form that allows a user to respond to a request using a multiple-choice field called ‘Response’ with values of “confirm” or “object”. In both cases I allow the user to add comments in a short text field that is also on the form.

What I want to do is require the notes field if the Response value is “object”.

There isn’t a native way to do this in Knack that I know of, other than to have three versions of the notes field - one required, one not required and one that will get the values from the other two based on record rules. I’ll do this if I have to but I would rather not have three fields doing the work of one.

Fortunately, the Knack Toolkit Library has this feature and my app already uses KTL for other things. Great! Unfortunately, when I try to use the _req keyword nothing happens. The text doesn’t even hide itself from display like it is supposed to. I have set the “formPreValidation” setting to true, so that shouldn’t be the issue.

Any suggestions? Getting _req to work would be my preference, but if someone knows another way to do this that is simple and reliable then that would be OK also.

Thanks!

I have progressed somewhat on this front but still need help.

Currently, if I use the _req keyword in the relevant view description the field does become required, so the keyword is functioning. The problem is this…

If I use ktlCond to require a condition, it acts as if the condition statement is just another list of fields to require.

For example, I have a view called ‘Respond’ which contains a ‘Notes’ field and a ‘NotesOld’ field:

_req=Notes, [ktlCond, has, test, NotesOld, Respond]

This makes the Notes field required, but also makes the NotesOld field required. It doesn’t matter what I type in the NotesOld field. Both fields are always required.

I suspect that my misunderstanding is in the use of ktlCond, because if I switch out the keyword to _hf I get the following:

_hf=Notes, [ktlCond, has, test, NotesOld, Respond]

Hides both the Notes field and the NotesOld field.

I would greatly appreciate any insight into why this might be gong on.

Hi @Kevin7 - this is more a KTL question than Knack, it should really be posted on KTLs GitHub page. However, I have copied it to a colleague who is far more capable on KTL than myself. Hopefully he will jump in on this thread and see if he can offer some advice. :smiling_face_with_sunglasses:

Thanks for helping out! I did just post it to GitHub a minute ago. I’ve never done that before and it hadn’t occurred to me until now to do so. Still, as important as the KTL is to Knack development I expect it would still be of use for the solution to be findable here if there is one.

Hi @Kevin7 - I had a reply back from Amanda Mower this evening, her partner, Craig Winnall “has raised an issue around using ktlCond on a form input. He’ll reply on the forum tomorrow” - stay tuned :wink:

Craig just messaged me to say he has replied to your post on GitHub :+1::man_technologist:

Update:

It seems that there are two things to consider when using ktlCond with _req in a form. 1) When using the _req keyword you can only use ktlCond feature with fields in a details view, not a form view. 2) You should enclose the field name to be required in brackets. For example::

_req=[Notes], [ktlCond, has, test, Project Name, Project Details]

This requires the Notes field on the form if the Project Name field on the Project Details view contains the string “test”.

Naturally, this negates the objective of having a form that dynamically adapts to the user’s input. I don’t see a way to make this work currently, ktl or otherwise.

The only solution that I have been able to come up with is to have two separate pages accessed by edit record action links–one for “object” and one for “confirm”–where the Notes field is required for the Object page and optional for the Confirm page.

This is a lot of design just to require one field in one condition, but I don’t see any way around it without using JavaScript and/or CSS that is beyond my skill set. If someone comes up with a more elegant solution I would love to hear it. Otherwise I think this is going to be the final design.

Thanks to Carl and Craig (on GitHub) for your assistance!

Kevin, this is a solution in javascript that you should be able to adapt to your circumstances easily. You can see it in a sandbox here:

You need to change the view and field information to match your case, and update the message to what you would like it to say. PM me if you need help getting this to work.
if you are using a different input (like checkbox instead of dropdown) it will need adjustment.

$(document).on('knack-view-render.view_116', function () {
  const dropdown = $('#view_116-field_204');
  const textInput = $('#field_203');
  const label = $('#kn-input-field_203 label');

  function updateAsterisk() {
    const selected = dropdown.val();
    if (selected === "Object") {
      if (!label.find('.kn-required').length) {
        label.append('<span class="kn-required"> *</span>');
      }
    } else {
      label.find('.kn-required').remove();
    }
  }

  updateAsterisk();
  dropdown.on('change', updateAsterisk);

  $('form').off('submit.validateObjection').on('submit.validateObjection', function (evt) {
    const reason = dropdown.val();
    const explanation = textInput.val()?.trim();

    if (reason === "Object" && !explanation) {
      evt.preventDefault();
      evt.stopImmediatePropagation();

      $('form .kn-message.is-error').remove();
      $('form').prepend(`
        <div class="kn-message is-error">
          <a class="close delete"></a>
          <span class="kn-message-body">
            <p><strong>An objection explanation is required when you select 'Object'.</strong></p>
          </span>
        </div>
      `);

      textInput.css('border', '1px solid red').focus();
      return false;
    }
  });
});

I received your DM, thanks @Kevin7

Here is an updated solution that will work with radio buttons, as shown below. You can play with this in my sandbox: Knack (for the next few days at least)

The code for this is below. Just change the view, field numbers, and the message that you want to display:

$(document).on('knack-view-render.view_116', function () {
  const radios = $('input[name="view_116-field_204"]');
  const textInput = $('#field_203');
  const label = $('#kn-input-field_203 label');

  function updateAsterisk() {
    const selected = radios.filter(':checked').val();
    if (selected === "Object") {
      if (!label.find('.kn-required').length) {
        label.append('<span class="kn-required"> *</span>');
      }
    } else {
      label.find('.kn-required').remove();
    }
  }

  updateAsterisk();
  radios.on('change', updateAsterisk);

  $('form').off('submit.validateObjection').on('submit.validateObjection', function (evt) {
    const selected = radios.filter(':checked').val();
    const explanation = textInput.val()?.trim();

    if (selected === "Object" && !explanation) {
      evt.preventDefault();
      evt.stopImmediatePropagation();

      $('form .kn-message.is-error').remove();
      $('form').prepend(`
        <div class="kn-message is-error">
          <a class="close delete"></a>
          <span class="kn-message-body">
            <p><strong>An objection explanation is required when you select 'Object'.</strong></p>
          </span>
        </div>
      `);

      textInput.css('border', '1px solid red').focus();
      return false;
    }
  });

  // 🧹 Clear error and red border as user starts typing
  textInput.on('input', function () {
    $(this).css('border', '');
    $('form .kn-message.is-error').remove();
  });
});