contributte / forms-multiplier

:repeat: Form multiplier & replicator for Nette Framework

Home Page:https://contributte.org/packages/contributte/forms-multiplier.html

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Soft limits on number of copies

jtojnar opened this issue · comments

I have a registration for a team race, which allows the teams consisting of two to five people. For this, the minCopies and maxCopies parameters work great. But now I also want to allow a special race category that only admits pairs.

The form has a category SelectBox, to which I attached a validation rule to prevent submitting the form with too many participants than the category allows. But I would still like to disable adding more copies than allowed for the category. Only I cannot just change the maxCopies or it would also hide the “Add” button, preventing adding a member even after changing the category back.

Would a PR adding a feature to support this be accepted?

What about this solution?

$multiplier->onCreateComponents[] = function (Multiplier $multiplier): void {
	$form = $multiplier->getForm();

	if ($form->isSubmitted() && iterator_count($multiplier->getContainers()) >= 3) {
		$form->addError('Max limit of participants for this category reached.');
	}
};

If form is not valid new copy is not added.

Oh, looks like that will run before new copies are added, and that will happen only if the form is valid, which is disrupted by adding the error. Thanks, that does work great.

Now I just need to have the equivalent thing for removing team members. If I am reading the code right, I need to somehow prevent the remove action to be triggered before

foreach ($resolver->getValues() as $number => $_) {
, since otherwise the ComponentResolver will remove the copy without any way to prevent it. But it needs to happen after the form is attached to be able to get the category from the form.

Apparently, your suggestion will prevent the form from being submitted. I needed something like this horror:

$multiplier->onCreateComponents[] = function (Multiplier $multiplier): void {
	$form = $multiplier->getForm();

	if (!$form->isSubmitted()) {
		return;
	}

	// 🙀
	$multiplierReflection = new \ReflectionClass(Multiplier::class);
	$httpData = $multiplierReflection->getProperty('httpData');
	$httpData->setAccessible(true);
	$values = $multiplierReflection->getProperty('values');
	$values->setAccessible(true);
	$resolver = new \Contributte\FormMultiplier\ComponentResolver($httpData->getValue($multiplier), $values->getValue($multiplier), $multiplier->getMaxCopies(), $multiplier->getMinCopies());

	$count = iterator_count($multiplier->getContainers());

	if ($resolver->isCreateAction() && $count >= 3) {
		$form->addError('Max limit of participants for this category reached.');
	}
};