Vice inputu formulare jako jedna komponenta
- kocourPB
- Člen | 47
Zdravim,
aktualne riesim jeden use-case, kedy sa nam vo viacerych formularoch opakuju 3 stejne inputy. Z tychto troch opakujucich inputov by som chcel vytvorit samostatnu komponentu, ktora by mala vlastnu classu napr. SameInputsComponent (extend mozna z \Nette\Forms\Controls\BaseControl ? … nevim) a mala by vlastnu latte sablonu, kde by boli manualne vykreslene tieto inputy.
Vo formularu by som zavolal nieco ako:
$form->addComponent($this->sameInputComponentFactory->create(), ...);
Hladal som nejaky priklad na fore, ale nic podobne som nenasiel. Riesili ste niekto podobny use-case? Ak ano, tak ako? Diky za rady. :)
- kocourPB
- Člen | 47
Ahoj,
tak nakoniec som zo seba vymacknul toto funkcne riesenie. Snad to niekoho inspiruje, pripadne pomoze. ;)
ScheduleComponent.php
<?php
declare(strict_types=1);
use Nette\Forms\Controls\BaseControl;
use Nette\Utils\ArrayHash;
interface IScheduleFormComponent
{
/** @return ScheduleFormComponent */
function create();
}
class ScheduleComponent extends BaseControl
{
/** @var string */
protected $formContainerName;
/**
* @param \Form $form
*/
public function attached($form)
{
$formContainer = $form->addContainer($this->formContainerName);
$formContainer->addCheckbox('isNonstop', _('Vždy'));
/** @var array $schedule */
$schedule = $form[$this->formContainerName];
$dayArray = explode(',', _('PO, ÚT, ST, ČT, PÁ, SO, NE'));
for ($dayOfWeek = 0; $dayOfWeek < 7; $dayOfWeek++) {
$dayName = 'days_' . $dayOfWeek;
$formContainer->addCheckbox($dayName, trim($dayArray[$dayOfWeek]));
$startName = 'start_' . $dayOfWeek;
$formContainer->addText($startName, _('Od:') . ' ', 5, 5)
->setHtmlAttribute('class', 'schedule-input-start')
->addConditionOn($schedule[$dayName], \Form::EQUAL, true)
->addRule(\Form::PATTERN, _('Zadejte prosím čas "Od" ve formátu 00:00.'), '^\d{1,2}:\d{2}$');
/** @var BaseControl $from */
$from = $formContainer[$startName];
$from->getControlPrototype()->id('schedule_start_' . $dayOfWeek);
$endName = 'end_' . $dayOfWeek;
$formContainer->addText($endName, _('Do:') . ' ', 5, 5)
->setHtmlAttribute('class', 'schedule-input-end')
->addConditionOn($schedule[$dayName], \Form::EQUAL, true)
->addRule(\Form::PATTERN, _('Zadejte prosím čas "Do" ve formátu 00:00.'), '^\d{1,2}:\d{2}$');
/** @var BaseControl $to */
$to = $formContainer[$endName];
$to->getControlPrototype()->id('schedule_end_' . $dayOfWeek);
}
parent::attached($form);
}
public function getControl()
{
$latte = new \Latte\Engine;
$template = new \Nette\Bridges\ApplicationLatte\Template($latte);
$template->setFile(__DIR__ . '/ScheduleComponent.latte');
$template->caption = $this->caption;
$form = $this->getForm();
$template->form = $form;
$template->formContainerName = $this->formContainerName;
$control = \Nette\Utils\Html::el('span');
$control->setHtml($template->__toString());
return $control;
}
public function setCaption(string $caption): ScheduleFormComponent
{
$this->caption = $caption;
return $this;
}
public function setFormContainerName(string $formContainerName): ScheduleFormComponent
{
$this->formContainerName = $formContainerName;
return $this;
}
}
ScheduleComponent.latte
<tr class="conditions">
<td class="form_td_label"><label>Spustit:</label></td>
<td>
{$form[$formContainerName]['isNonstop']->control}
{$form[$formContainerName]['isNonstop']->label}
</td>
</tr>
<tr n:for="$i=0; $i < 7; $i++" class="conditions schedule_row">
<td></td>
<td>
<span class='schedule_days'>
{$form[$formContainerName]['days_'.$i]->control}
{$form[$formContainerName]['days_'.$i]->label}
</span>
{$form[$formContainerName]['start_'.$i]->label}
{$form[$formContainerName]['start_'.$i]->control}
{$form[$formContainerName]['end_'.$i]->label}
{$form[$formContainerName]['end_'.$i]->control}
</td>
</tr>
config.neon
services:
- IScheduleFormComponent
pouzitie v existujucom formularu napr. v presenteru
class CalendarPresenter {
/** @var IScheduleFormComponent @inject */
public $scheduleFormComponent;
// ...
protected function createComponentEditForm()
{
$form = new Form;
// ...
$scheduleComponent = $this->scheduleFormComponent->create()
->setFormContainerName('schedule')
->setCaption('Rozvrh');
$form->addComponent($scheduleComponent, 'scheduleComponent');
// ...
return $form;
}
// ...
}
edit: upravene s vyuzitim tovarny/factory ;o)
Editoval kocourPB (14. 3. 2019 15:58)
- Roman Halaxa
- Člen | 60
kocourPB napsal(a):
Ahoj,
tak nakoniec som zo seba vymacknul toto funkcne riesenie. Snad to niekoho inspiruje, pripadne pomoze. ;)
ScheduleComponent.php
<?php declare(strict_types=1); use Nette\Forms\Controls\BaseControl; use Nette\Utils\ArrayHash; class ScheduleComponent extends BaseControl { /** @var string */ protected $formContainerName; public function __construct(string $formContainerName, $caption = null) { $this->formContainerName = $formContainerName; parent::__construct($caption); } /** * @param \Form $form */ public function attached($form) { $formContainer = $form->addContainer($this->formContainerName); $formContainer->addCheckbox('isNonstop', _('Vždy')); /** @var array $schedule */ $schedule = $form[$this->formContainerName]; $dayArray = explode(',', _('PO, ÚT, ST, ČT, PÁ, SO, NE')); for ($dayOfWeek = 0; $dayOfWeek < 7; $dayOfWeek++) { $dayName = 'days_' . $dayOfWeek; $formContainer->addCheckbox($dayName, trim($dayArray[$dayOfWeek])); $startName = 'start_' . $dayOfWeek; $formContainer->addText($startName, _('Od:') . ' ', 5, 5) ->setHtmlAttribute('class', 'schedule-input-start') ->addConditionOn($schedule[$dayName], \Form::EQUAL, true) ->addRule(\Form::PATTERN, _('Zadejte prosím čas "Od" ve formátu 00:00.'), '^\d{1,2}:\d{2}$'); /** @var BaseControl $from */ $from = $formContainer[$startName]; $from->getControlPrototype()->id('schedule_start_' . $dayOfWeek); $endName = 'end_' . $dayOfWeek; $formContainer->addText($endName, _('Do:') . ' ', 5, 5) ->setHtmlAttribute('class', 'schedule-input-end') ->addConditionOn($schedule[$dayName], \Form::EQUAL, true) ->addRule(\Form::PATTERN, _('Zadejte prosím čas "Do" ve formátu 00:00.'), '^\d{1,2}:\d{2}$'); /** @var BaseControl $to */ $to = $formContainer[$endName]; $to->getControlPrototype()->id('schedule_end_' . $dayOfWeek); } parent::attached($form); } public function getControl() { $latte = new \Latte\Engine; $template = new \Nette\Bridges\ApplicationLatte\Template($latte); $template->setFile(__DIR__ . '/ScheduleComponent.latte'); $template->caption = $this->caption; $form = $this->getForm(); $template->form = $form; $template->formContainerName = $this->formContainerName; $control = \Nette\Utils\Html::el('span'); $control->setHtml($template->__toString()); return $control; } }
ScheduleComponent.latte
<tr class="conditions"> <td class="form_td_label"><label>Spustit:</label></td> <td> {$form[$formContainerName]['isNonstop']->control} {$form[$formContainerName]['isNonstop']->label} </td> </tr> <tr n:for="$i=0; $i < 7; $i++" class="conditions schedule_row"> <td></td> <td> <span class='schedule_days'> {$form[$formContainerName]['days_'.$i]->control} {$form[$formContainerName]['days_'.$i]->label} </span> {$form[$formContainerName]['start_'.$i]->label} {$form[$formContainerName]['start_'.$i]->control} {$form[$formContainerName]['end_'.$i]->label} {$form[$formContainerName]['end_'.$i]->control} </td> </tr>
pouzitie v existujucom formularu
protected function createComponentEditForm() { $form = new Form; // ... $form->addComponent(new ScheduleComponent('schedule', 'Kalendar'), 'scheduleComponent'); // ... return $form; }
Děkuji za sdílení :D Nakopnul jsi mě správným směrem jak k inputu přiřadit vlastní šablonu tak aby to renderer špatně nepobral. Už jsem to teda udělal tak že jsem ke svému inputu dal složku se závistlostmi a řeším to celé v javascriptu ale i tak, to se do budoucna bude hodit až budu vytvářet jiný :D