Multiplikator: Dinamične komponente

Orodje za dinamično ustvarjanje interaktivnih komponent

Začnimo s tipičnim problemom: imamo seznam izdelkov na spletni strani e-trgovine in vsak izdelek želimo opremiti z obrazcem Dodaj v košarico. Eden od načinov je, da celoten seznam zapakiramo v en sam obrazec. Priročnejši način je uporaba Nette\Application\UI\Multiplier.

Funkcija Multiplier vam omogoča, da določite tovarno za več sestavnih delov. Temelji na načelu vgnezdenih komponent – vsaka komponenta, ki podeduje od Nette\ComponentModel\Container, lahko vsebuje druge komponente.

Oglejte si model komponent v dokumentaciji.

Multiplier nastopa kot starševska komponenta, ki lahko dinamično ustvari svoje otroke z uporabo povratnega klica, posredovanega v konstruktorju. Oglejte si primer:

protected function createComponentShopForm(): Multiplier
{
	return new Multiplier(function () {
		$form = new Nette\Application\UI\Form;
		$form->addInteger('amount', 'Amount:')
			->setRequired();
		$form->addSubmit('send', 'Add to cart');
		return $form;
	});
}

V predlogi lahko prikažemo obrazec za vsak izdelek – in vsak obrazec bo dejansko edinstvena komponenta.

{foreach $items as $item}
	<h2>{$item->title}</h2>
	{$item->description}

	{control "shopForm-$item->id"}
{/foreach}

Argument, posredovan oznaki {control}, pravi:

  1. pridobi komponento shopForm
  2. in vrni njenega otroka $item->id

Med prvim klicem 1. komponenta shopForm še ne obstaja, zato se za njeno ustvarjanje pokliče metoda createComponentShopForm. Nato se pokliče anonimna funkcija, ki je Multiplierju posredovana kot parameter, in ustvari se obrazec.

V naslednjih iteracijah foreach se metoda createComponentShopForm ne kliče več, ker komponenta že obstaja. Ker pa se sklicujemo na drugega otroka ($item->id se med iteracijami spreminja), se ponovno pokliče anonimna funkcija in ustvari se nov obrazec.

Zadnja stvar je zagotoviti, da obrazec dejansko doda pravi izdelek v košarico, saj so v trenutnem stanju vsi obrazci enaki in ne moremo razlikovati, katerim izdelkom pripadajo. Za to lahko uporabimo lastnost Multiplierja (in na splošno vsake metode tovarne komponent v Nette Framework), da vsaka metoda tovarne komponent kot prvi argument prejme ime ustvarjene komponente. V našem primeru je to $item->id, kar je natanko tisto, kar potrebujemo za razlikovanje posameznih izdelkov. Vse, kar morate storiti, je, da spremenite kodo za ustvarjanje obrazca:

protected function createComponentShopForm(): Multiplier
{
	return new Multiplier(function ($itemId) {
		$form = new Nette\Application\UI\Form;
		$form->addInteger('amount', 'Amount:')
			->setRequired();
		$form->addHidden('itemId', $itemId);
		$form->addSubmit('send', 'Add to cart');
		return $form;
	});
}
različica: 4.0