Nette Documentation Preview

syntax
Πολλαπλασιαστής: Δυναμικά στοιχεία
**********************************

Ένα εργαλείο για τη δυναμική δημιουργία διαδραστικών στοιχείων .[perex]

Ας ξεκινήσουμε με ένα τυπικό πρόβλημα: έχουμε μια λίστα προϊόντων σε έναν ιστότοπο ηλεκτρονικού εμπορίου και θέλουμε να συνοδεύσουμε κάθε προϊόν με μια φόρμα *προσθήκης στο καλάθι*. Ένας τρόπος είναι να τυλίξουμε ολόκληρη τη λίστα σε μια ενιαία φόρμα. Ένας πιο βολικός τρόπος είναι να χρησιμοποιήσουμε το [api:Nette\Application\UI\Multiplier].

Ο πολλαπλασιαστής σας επιτρέπει να ορίσετε ένα εργοστάσιο για πολλαπλά στοιχεία. Βασίζεται στην αρχή των εμφωλευμένων συστατικών - κάθε συστατικό που κληρονομεί από το [api:Nette\ComponentModel\Container] μπορεί να περιέχει άλλα συστατικά.

Δείτε το [μοντέλο συστατικών |components#Components in Depth] στην τεκμηρίωση. .[tip]

Το Multiplier παριστάνει το γονικό συστατικό το οποίο μπορεί να δημιουργήσει δυναμικά τα παιδιά του χρησιμοποιώντας το callback που περνάει στον κατασκευαστή. Βλέπε παράδειγμα:

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

Στο πρότυπο μπορούμε να αποδώσουμε μια φόρμα για κάθε προϊόν - και κάθε φόρμα θα είναι πράγματι ένα μοναδικό συστατικό.

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

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

Το επιχείρημα που περνάει στην ετικέτα `{control}` λέει:

1. `shopForm`
2. και να επιστρέψει το παιδί του `$item->id`

Κατά την πρώτη κλήση της **1.** το συστατικό `shopForm` δεν υπάρχει ακόμη, οπότε καλείται η μέθοδος `createComponentShopForm` για τη δημιουργία του. Στη συνέχεια καλείται μια ανώνυμη συνάρτηση που περνά ως παράμετρος στον Πολλαπλασιαστή και δημιουργείται μια φόρμα.

Στις επόμενες επαναλήψεις του `foreach` η μέθοδος `createComponentShopForm` δεν καλείται πλέον επειδή το συστατικό υπάρχει ήδη. Επειδή όμως αναφερόμαστε σε ένα άλλο παιδί (`$item->id` μεταβάλλεται μεταξύ των επαναλήψεων), καλείται ξανά μια ανώνυμη συνάρτηση και δημιουργείται μια νέα φόρμα.

Το τελευταίο πράγμα είναι να διασφαλίσουμε ότι η φόρμα προσθέτει πράγματι το σωστό προϊόν στο καλάθι, διότι στην τρέχουσα κατάσταση όλες οι φόρμες είναι ίδιες και δεν μπορούμε να διακρίνουμε σε ποια προϊόντα ανήκουν. Για αυτό μπορούμε να χρησιμοποιήσουμε την ιδιότητα του Multiplier (και γενικά κάθε μεθόδου εργοστασίου συστατικών στο Nette Framework) ότι κάθε μέθοδος εργοστασίου συστατικών λαμβάνει ως πρώτο όρισμα το όνομα του συστατικού που δημιουργήθηκε. Στην περίπτωσή μας αυτό θα ήταν το `$item->id`, το οποίο είναι ακριβώς αυτό που χρειαζόμαστε για να διακρίνουμε τα επιμέρους προϊόντα. Το μόνο που χρειάζεται να κάνετε είναι να τροποποιήσετε τον κώδικα για τη δημιουργία της φόρμας:

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

Πολλαπλασιαστής: Δυναμικά στοιχεία

Ένα εργαλείο για τη δυναμική δημιουργία διαδραστικών στοιχείων

Ας ξεκινήσουμε με ένα τυπικό πρόβλημα: έχουμε μια λίστα προϊόντων σε έναν ιστότοπο ηλεκτρονικού εμπορίου και θέλουμε να συνοδεύσουμε κάθε προϊόν με μια φόρμα προσθήκης στο καλάθι. Ένας τρόπος είναι να τυλίξουμε ολόκληρη τη λίστα σε μια ενιαία φόρμα. Ένας πιο βολικός τρόπος είναι να χρησιμοποιήσουμε το Nette\Application\UI\Multiplier.

Ο πολλαπλασιαστής σας επιτρέπει να ορίσετε ένα εργοστάσιο για πολλαπλά στοιχεία. Βασίζεται στην αρχή των εμφωλευμένων συστατικών – κάθε συστατικό που κληρονομεί από το Nette\ComponentModel\Container μπορεί να περιέχει άλλα συστατικά.

Δείτε το μοντέλο συστατικών στην τεκμηρίωση.

Το Multiplier παριστάνει το γονικό συστατικό το οποίο μπορεί να δημιουργήσει δυναμικά τα παιδιά του χρησιμοποιώντας το callback που περνάει στον κατασκευαστή. Βλέπε παράδειγμα:

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

Στο πρότυπο μπορούμε να αποδώσουμε μια φόρμα για κάθε προϊόν – και κάθε φόρμα θα είναι πράγματι ένα μοναδικό συστατικό.

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

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

Το επιχείρημα που περνάει στην ετικέτα {control} λέει:

  1. shopForm
  2. και να επιστρέψει το παιδί του $item->id

Κατά την πρώτη κλήση της 1. το συστατικό shopForm δεν υπάρχει ακόμη, οπότε καλείται η μέθοδος createComponentShopForm για τη δημιουργία του. Στη συνέχεια καλείται μια ανώνυμη συνάρτηση που περνά ως παράμετρος στον Πολλαπλασιαστή και δημιουργείται μια φόρμα.

Στις επόμενες επαναλήψεις του foreach η μέθοδος createComponentShopForm δεν καλείται πλέον επειδή το συστατικό υπάρχει ήδη. Επειδή όμως αναφερόμαστε σε ένα άλλο παιδί ($item->id μεταβάλλεται μεταξύ των επαναλήψεων), καλείται ξανά μια ανώνυμη συνάρτηση και δημιουργείται μια νέα φόρμα.

Το τελευταίο πράγμα είναι να διασφαλίσουμε ότι η φόρμα προσθέτει πράγματι το σωστό προϊόν στο καλάθι, διότι στην τρέχουσα κατάσταση όλες οι φόρμες είναι ίδιες και δεν μπορούμε να διακρίνουμε σε ποια προϊόντα ανήκουν. Για αυτό μπορούμε να χρησιμοποιήσουμε την ιδιότητα του Multiplier (και γενικά κάθε μεθόδου εργοστασίου συστατικών στο Nette Framework) ότι κάθε μέθοδος εργοστασίου συστατικών λαμβάνει ως πρώτο όρισμα το όνομα του συστατικού που δημιουργήθηκε. Στην περίπτωσή μας αυτό θα ήταν το $item->id, το οποίο είναι ακριβώς αυτό που χρειαζόμαστε για να διακρίνουμε τα επιμέρους προϊόντα. Το μόνο που χρειάζεται να κάνετε είναι να τροποποιήσετε τον κώδικα για τη δημιουργία της φόρμας:

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