Nette Documentation Preview

syntax
Multiplicador: Componentes dinâmicos
************************************

Uma ferramenta para a criação dinâmica de componentes interativos .[perex]

Vamos começar com um problema típico: temos uma lista de produtos em um site de comércio eletrônico e queremos acompanhar cada produto com um formulário *add to cart*. Uma das maneiras é envolver toda a lista em um único formulário. Uma maneira mais conveniente é usar [api:Nette\Application\UI\Multiplier].

O multiplicador permite definir uma fábrica para múltiplos componentes. Ele se baseia no princípio de componentes aninhados - cada componente herdado de [api:Nette\ComponentModel\Container] pode conter outros componentes.

Veja o [modelo dos componentes |components#Components in Depth] na documentação. .[tip]

O multiplicador posa como um componente pai que pode criar dinamicamente seus filhos usando a callback passada no construtor. Veja o exemplo:

```php
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;
	});
}
```

No modelo podemos apresentar um formulário para cada produto - e cada formulário será de fato um componente único.

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

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

Argumento passado para `{control}` tag diz:

1. obter um componente `shopForm`
2. e devolver seu filho `$item->id`

Durante a primeira chamada de **1.** o componente `shopForm` ainda não existe, portanto o método `createComponentShopForm` é chamado para criá-lo. Uma função anônima passada como parâmetro para o Multiplicador, é então chamada e um formulário é criado.

Nas iterações subsequentes do `foreach` o método `createComponentShopForm` não é mais chamado porque o componente já existe. Mas como fazemos referência a outra criança (`$item->id` varia entre iterações), uma função anônima é chamada novamente e uma nova forma é criada.

A última coisa é garantir que o formulário realmente acrescente o produto correto ao carrinho porque no estado atual todos os formulários são iguais e não podemos distinguir a que produtos eles pertencem. Para isso, podemos usar a propriedade de Multiplicador (e em geral de qualquer método de fábrica de componentes em Nette Framework) que cada método de fábrica de componentes recebe o nome do componente criado como o primeiro argumento. Em nosso caso, isso seria `$item->id`, que é exatamente o que precisamos para distinguir os produtos individuais. Tudo o que precisamos fazer é modificar o código para criar o formulário:

```php
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;
	});
}
```

Multiplicador: Componentes dinâmicos

Uma ferramenta para a criação dinâmica de componentes interativos

Vamos começar com um problema típico: temos uma lista de produtos em um site de comércio eletrônico e queremos acompanhar cada produto com um formulário add to cart. Uma das maneiras é envolver toda a lista em um único formulário. Uma maneira mais conveniente é usar Nette\Application\UI\Multiplier.

O multiplicador permite definir uma fábrica para múltiplos componentes. Ele se baseia no princípio de componentes aninhados – cada componente herdado de Nette\ComponentModel\Container pode conter outros componentes.

Veja o modelo dos componentes na documentação.

O multiplicador posa como um componente pai que pode criar dinamicamente seus filhos usando a callback passada no construtor. Veja o exemplo:

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;
	});
}

No modelo podemos apresentar um formulário para cada produto – e cada formulário será de fato um componente único.

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

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

Argumento passado para {control} tag diz:

  1. obter um componente shopForm
  2. e devolver seu filho $item->id

Durante a primeira chamada de 1. o componente shopForm ainda não existe, portanto o método createComponentShopForm é chamado para criá-lo. Uma função anônima passada como parâmetro para o Multiplicador, é então chamada e um formulário é criado.

Nas iterações subsequentes do foreach o método createComponentShopForm não é mais chamado porque o componente já existe. Mas como fazemos referência a outra criança ($item->id varia entre iterações), uma função anônima é chamada novamente e uma nova forma é criada.

A última coisa é garantir que o formulário realmente acrescente o produto correto ao carrinho porque no estado atual todos os formulários são iguais e não podemos distinguir a que produtos eles pertencem. Para isso, podemos usar a propriedade de Multiplicador (e em geral de qualquer método de fábrica de componentes em Nette Framework) que cada método de fábrica de componentes recebe o nome do componente criado como o primeiro argumento. Em nosso caso, isso seria $item->id, que é exatamente o que precisamos para distinguir os produtos individuais. Tudo o que precisamos fazer é modificar o código para criar o formulário:

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;
	});
}