Multiplier: dinamik bileşenler

Etkileşimli bileşenleri dinamik olarak oluşturmak için bir araç.

Tipik bir örnekle başlayalım: bir e-ticaret sitesinde ürün listesi düşünün; her ürün için bir “Sepete ekle” formu istiyorsunuz. Olası bir yaklaşım, tüm listeyi tek bir forma sarmaktır. Ancak çok daha kullanışlı bir yöntemi Nette\Application\UI\Multiplier sunar.

Multiplier, birden fazla bileşen için rahatça bir factory tanımlamanızı sağlar. İç içe bileşenler ilkesiyle çalışır: Nette\ComponentModel\Container'dan kalıtım alan her bileşen başka bileşenler içerebilir.

Dokümantasyondaki bileşen modeli bölümüne bakın.

Multiplier'ın özü, constructor'a verilen bir callback yardımıyla çocuklarını dinamik olarak oluşturabilen bir ebeveyn gibi davranmasıdır. Örneğe bakın:

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

Artık şablonda formu her ürün için kolayca render edebiliriz ve her biri gerçekten benzersiz bir bileşen olacaktır.

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

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

{control} etiketinde verilen argüman şu anlama gelen bir formatı izler:

  1. shopForm bileşenini al.
  2. Ondan $item->id adlı çocuğu al.

1. noktasının ilk çağrısında shopForm bileşeni henüz yoktur, bu yüzden onun factory'si createComponentShopForm çağrılır. Sonra elde edilen bileşen (bir Multiplier örneği) üzerinde, somut form için factory çağrılır; bu da Multiplier'ın constructor'ına verdiğimiz anonim fonksiyondur.

Foreach döngüsünün bir sonraki turunda createComponentShopForm metodu tekrar çağrılmaz (bileşen zaten vardır). Ancak farklı bir çocuk aradığımız için (her turda $item->id farklı olacağından), anonim fonksiyon tekrar çağrılır ve yeni bir form döndürür.

Geriye tek bir şey kalıyor: formun sepete doğru ürünü eklediğinden emin olmak; şu anda form her ürün için aynı. Burada bize Multiplier'ın (ve genel olarak Nette Framework'teki her bileşen factory'sinin) bir özelliği yardımcı olur: her factory, ilk argüman olarak oluşturulan bileşenin adını alır. Multiplier factory'si ayrıca ikinci argüman olarak Multiplier örneğinin kendisini alır. Bizim durumumuzda ilk argüman $item->id olacak, ki tam da ihtiyacımız olan bilgi budur. Yani formun oluşturulmasını biraz değiştirmemiz yeterli:

protected function createComponentShopForm(): Multiplier
{
	return new Multiplier(function (string $itemId) {
		$form = new Nette\Application\UI\Form;
		$form->addInteger('amount', 'Miktar:')
			->setRequired();
		$form->addHidden('itemId', $itemId);
		$form->addSubmit('send', 'Sepete ekle');
		return $form;
	});
}
versiyon: 4.x