Dynamické přidávání různých prvků

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
jEhLa
Člen | 70
+
0
-

Dobrý den,
potřeboval bych udělat dynamický formulář. Kde by se pomocí tlačítek (Přidej text, Přidej textarea, Přidej select) přidávali další elementy podle vybraného typu. Formulář již ale může obsahovat přednastavené prvky získané z DB.

Potřebuji například, aby když kliknu na Přidej text, byly do formuláře do containeru přidány dva prvky text, jeden s názvem name a další label. Pokud kliknu na tlačítko Přidej select, tak potřebuji přidat tři prvky text (name,label,values).

public function actionInputs( $page_id ){
	$this->page_id = $page_id;

	$form = $this['inputsForm'];
	if(!$form->isSubmitted()){
		$this->getSession('values')->remove();
	}

	if($this->getSession('values')->inputs == null){
		//načtu položky z DB, prozatím testuji na nastaveném poli
		$inputs = array(
			array('id'=>1,'name'=>'name','label'=>'Název','input'=>'text'),
			array('id'=>2,'name'=>'email','label'=>'Email','input'=>'text'));
	}
	else {
		$inputs = $this->getSession('values')->inputs;
	}

	$inputsContainer = $form['inputs'];
	foreach ($inputs as $key => $input){
		if(!isset($inputsContainer[$key])){
			$container = $inputsContainer->addContainer($key);
			$container->currentGroup = $container->getForm()->addGroup(  ucwords( $input['input'] ), FALSE);
			$container->addHidden('id');
			$container->addHidden('input');
			$container->addText('name','Název:');
			$container->addText('label','Label:');
			switch($input['input']){
				case 'text':
					//přidat prvky potřebné pro tento typ
					break;

				case 'textarea':
					//přidat prvky potřebné pro tento typ
					break;
			}
		}
		//$container->setDefaults($input);
	}
	$inputsContainer->setDefaults($inputs);

}
public function renderInputs( $page_id ){
	$content = $this->model->getContentById( $page_id );
	$this->template->content = $content->fetch();
}

protected function createComponentInputsForm() {
	$form = new \App\Components\Form;

	$inputs = $form->addContainer('inputs');

	$form->addSubmit('send', 'Uložit')
		->onClick[] = $this->inputsFormSuccess;

	$form->addSubmit('addText', 'Přidat text')
		->onClick[] = $this->addTextInput;
	$form->addSubmit('addTextarea', 'Přidat textarea')
		->onClick[] = $this->addTextareaInput;

	return $form;
}
public function inputsFormSuccess( $button ){
	$values = $button->getForm()->getValues(true);
	\Nette\Diagnostics\Debugger::dump($values['inputs']);
}
public function addTextInput( $button ){
	$this->getSession('values')->remove();
	$values = $button->getForm()->getValues(true);

	$values['inputs'][] = array('id'=>'0','input'=>'text','name'=>'a','label'=>'b');
	$this->getSession('values')->inputs = $values['inputs'];
	$this->actionInputs($this->page_id);
}
public function addTextareaInput( $button ){
	//přidá pole array('id'=>'0','input'=>'textarea','name'=>'a','label'=>'b');
}

Vím že je to šíleně zbastlený (to opětovné volání actionInputs() se mi vůbec nelíbí), ale vrtám se vtom už třetí den a tohle je zatím jediný způsob, který dělá alespoň trochu co chci. Zkoušel jsem použít i Replicator, ale u něj jsem zase nevěděl jak rozlišovat jaké prvky budu chtít použít.

Tento příklad je funkční při prvním přidání nové položky. Ale nevím proč, nedochází k nastavení její výchozí hodnoty (původní položky nastaveny jsou). Takže při dalším pokusu o přidání jiného prvku to havaruje, protože předchozí položka nemá nastavený ‚input‘ a už se vše špatně vykresluje.

A to jsem ještě vůbec neřešil to, jak se budou položky mazat.

Nějaké nápady jak by se toto dalo řešit?

jEhLa
Člen | 70
+
0
-

Ještě ukázka co obsahuje proměnná $inputs.

Načtení stránky:
array (2)
0 => array (4)
id => 1
name => "name" (4)
label => "Název" (6)
input => "text" (4)
1 => array (4)
id => 2
name => "email" (5)
label => "Email" (5)
input => "text" (4)

První přidání:
array (3)
0 => array (4)
id => "1"
input => "text" (4)
name => "name" (4)
label => "Název" (6)
1 => array (4)
id => "2"
input => "text" (4)
name => "email" (5)
label => "Email" (5)
2 => array (4)
id => "0"
input => "text" (4)
name => "a"
label => "b"

Druhé přidání:
array (4)
0 => array (4)
id => "1"
input => "text" (4)
name => "name" (4)
label => "Název" (6)
1 => array (4)
id => "2"
input => "text" (4)
name => "email" (5)
label => "Email" (5)
2 => array (4)
id => ""
input => ""
name => ""
label => ""
3 => array (4)
id => "0"
input => "text" (4)
name => "a"
label => "b"
matopeto
Člen | 395
+
+1
-

Osobne mam v jednom projekte takto:

Mam replikator, ktory pridava prvky, kde prvok obahuje selectbox s vyberom typu a na zaklade condition a toggle sa zobrazuju jednotlive ostatne polozky (v sablone su vyrenderovane ale pre jednotlive typy su skryte)

<?php

$replicator = $properties->addDynamic('items', function (Container $container) {
			$toggleNamePreffix = sprintf(\Nette\Forms\Controls\BaseControl::$idMask, $container->lookupPath(NULL));

			$container->currentGroup = $container->form->addGroup("Form item");

			$types = array(
				'input' => "Input",
				'textarea' => "Text area",
				'checkbox' => "Ckeckbox",
				'selectbox' => "Selectbox",
				'radiolist' => "Radio list",
				'checkboxlist' => "Checkbox list",
				'hidden' => "Hidden",
				'submit' => "Submit",
			);
			$container->addSelect('type', 'Type', $types)
				->addCondition(Form::IS_IN, array('selectbox', 'radiolist', 'checkboxlist'))
				->toggle($toggleNamePreffix . "-toggle-items")
				->elseCondition()
				->toggle($toggleNamePreffix . "-toggle-value");

			$container->addText('label', 'Label')->setRequired("Title must not be empty.");

			$container->addText('name', 'Name')->setRequired("Name is required");

			$container->addText('value', 'Default value')
				->setOption('id', $toggleNamePreffix . "-toggle-value");

			$container->addTextArea('items', 'Items')
				->setOption('id', $toggleNamePreffix . "-toggle-items");

			$container->addSubmit('remove', 'Delete item')
				->setAttribute('class', 'buttonLight')
				->addRemoveOnClick();
		}, 1);

		/** @var \Kdyby\Replicator\Container $replicator */
		$replicator->addSubmit('add', 'Add item')
			->setAttribute('class', 'buttonLight')
			->addCreateOnClick(TRUE);


?>
jEhLa
Člen | 70
+
0
-

Díky za tip. Sice to není taky úplně ideální, ale účel by to splnit mohlo.