Conditional "required" uniform frontend form

I’am trying to set fields to required when checkbox is clicked (or the other way round). I followed this topic: https://forum.getkirby.com/t/required-fields-if-unchecked-uniform/8576

$rules = rules([
        ....
        "title_en" => ["required"],
        "subtitle_en" => ["required"],
        "teaser_en" => ["required"],
        "text_en" => ["required"],
...


and then before instatiating the form object:

$lang = get("lang");

      $language = is_array($lang) && in_array("en", $lang) ? "true" : "false";
      if ($language === false) {
        $notRequired = ["title_en", "subtitle_en", "teaser_en", "text_en"];
        foreach ($rules as $name => $r) {
          if (in_array($name, $notRequired)) {
            array_shift($r["rules"]);
          }
        }
      }

but get("lang") doesn’t get any value.
And I can’t get $form->old("Lang") before instantiating $form

Or is there a better way to handle this problem?

I’m missing some context, I guess, but this condition will never be met, because you assign strings to your $language variable instead of Boolean values. Should be

$language = is_array($lang) && in_array("en", $lang) ? true : false;

You are right, but still when I dump “get(“lang”)” in the controller I get nothing.

I guess that’s supposed to be the name of a field. But unfortunately, you don’t provide enough context to allow a guess where this is going wrong.

"seminar-form" => function ($page, $pages, $kirby) {
      $data = $kirby->controller("site", compact("page", "pages", "kirby"));

      $trainers = $data["trainers"]->children()->pluck("id");

      $blueprint = blueprint("pages/seminar");
      $categories = $blueprint->field("categories")["options"];
      $currencies = $blueprint->field("currencies")["options"];
      $categoriesKeys = array_keys($categories);
      $rules = rules([
        "from" => ["required", "date", "minDate", "maxDate"],
        "to" => ["required", "date", "minDate", "maxDate"],
        "start" => ["required", "time"],
        "end" => ["required", "time"],
        "reg_deadline" => ["required", "date", "dateBefore"],
        "units" => ["required", "integer"],
        "max_participant" => ["required", "integer"],
        "lang" => ["required", "*.in" => [["de", "en", "nl"]]],
        "title" => ["required"],
        "subtitle" => ["required"],
        "teaser" => ["required"],
        "text" => ["required"],
        "title_en" => ["required"],
        "subtitle_en" => ["required"],
        "teaser_en" => ["required"],
        "text_en" => ["required"],
        "categories" => ["required", "*.in" => [$categoriesKeys]],
        "management" => ["required", "in" => [$trainers]],
        "trainers" => ["*.in" => [$trainers]],
        "forward" => ["required", "in" => [["url", "mail"]]],
        "reg_email" => ["email"],
        "reg_tel" => [],
        "reg_extern" => ["url"],
        "reg_extern_tel" => [],
        "reg_extern_email" => [],
        "format" => ["required", "in" => [["online", "live"]]],
        "location" => [],
        "loc_name" => [],
        "loc_street" => [],
        "loc_plz" => [],
        "loc_city" => [],
        "loc_country" => [],
        "loc_tel" => [],
        "loc_email" => [],
        "loc_web" => [],
        "cost_per_day" => [],
        "price" => ["required"],
        "price_member" => ["required"],
        "currencies" => ["required", "in" => [$currencies]],
        "price_text" => [],
        "early_bird" => [],
        "price_early_bird_member" => [],
        "price_early_bird" => [],
        "early_bird" => [],
        "early_bird_deadline" => ["dateBefore"],
      ]);
      $lang = get("lang");

      $language = is_array($lang) && in_array("en", $lang) ? true : false;
      if ($language === false) {
        $notRequired = ["title_en", "subtitle_en", "teaser_en", "text_en"];
        foreach ($rules as $name => $r) {
          if (in_array($name, $notRequired)) {
            array_shift($r["rules"]);
          }
        }
      }

      $form = new Form($rules);
      if ($kirby->request()->is("POST")) {
        $form->action(SubmitAction::class, [
          "page" => $page,
        ]);
      }
      return array_merge($data, [
        "form" => $form,
        "categories" => $categories,
        "currencies" => $currencies,
        "language" => $language,
        "lang" => $lang,
      ]);
    },
  ],

I have this in my plugin index.php and I try to conditionaly require some fields that are needed if e.g. the language checkbox include english for input:

or…

Maybe a problem with your checkboxes, instead of the screenshot, the form code for the language field would be more useful

$lang = $form->old('lang');
$en = is_array($lang) && in_array('en', $lang) ? true : false;

this are the chexkboxes fields:

<div class="form-element w-50">
	<div class="form-element w-full-p">
		<span>Sprachen / languages</span><br>

		<input class="checkbox" id="de" name="lang[]" type="checkbox" value="de" checked="checked" }}>
		<label for="de">Deutsch / german</label><br>

		<input  onClick="javascript: $('.english').toggleClass('visible'); $('.english.visible input').prop('required', true); $('.english:not(.visible) input').prop('required', false)" class="checkbox" id="en" name="lang[]" type="checkbox" value="en" {{ e($en, 'checked="checked"')  }}>
		<label for="en">Englisch / english</label><br>
		
		<input class="checkbox" id="nl" name="lang[]" type="checkbox" value="nl" {{ e(is_array($lang) && in_array('nl', $lang), 'checked="checked"')  }}>
		<label for="nl">Niederländisch / dutch</label>
		
		@if ($error = $form->error('lang'))
			<span class="error display-inline-block">{!! implode('<br>', $error) !!}</span>
		@endif
	</div>
</div>

and this works fine:

<div class="form-element {{ e($en, 'visible')  }} english w-full">
	<label for="subtitle_en">Untertitel engl.</label><span class="char-count align-left is-small is-red" id="subtitle_feedback_en"></span>
	<input class="w-full-p" id="subtitle_en" name="subtitle_en" type="text" maxlength="150" value="{{ $form->old('subtitle_en')}}" >

	@if ($error = $form->error('subtitle_en'))
		<span class="error">{!! implode('<br>', $error) !!}</span>
	@endif
</div>

the input fields for the english data is shown up if “en” is clicked and the form was send and maybe some further more requried fields weren’t filled yet.

But I get the $lang variable with $form->old('lang').
With get('lang') in the controller I get nothing. The problem is, that I want to get the lang data before I instantiate the $form variable $form = new Form($rules); in order to conditionaly shift the $notRequired array from $rules.

I got it.
Indeed I missed to say, that I use the uniform plugin. That why the rules comes in the $kirby->request()-body().

My solutuon now is:

$lang = $kirby
  ->request()
  ->body()
  ->get("lang");
$language = is_array($lang) && in_array("en", $lang) ? true : false;
if ($language === false) {
  $notRequired = ["title_en", "subtitle_en", "teaser_en", "text_en"];
  foreach ($rules as $name => $r) {
    if (in_array($name, $notRequired)) {
      unset($rules[$name]);
    }
  }
}