Απόδοση φορμών

Η εμφάνιση των φορμών μπορεί να είναι πολύ διαφορετική. Στην πράξη, μπορούμε να συναντήσουμε δύο άκρα. Από τη μία πλευρά, υπάρχει η ανάγκη να αποδοθούν στην εφαρμογή πολλές φόρμες που είναι οπτικά παρόμοιες σαν δύο σταγόνες νερό, και εκτιμούμε την εύκολη απόδοση χωρίς πρότυπο χρησιμοποιώντας την $form->render(). Αυτή είναι συνήθως η περίπτωση των διαχειριστικών διεπαφών.

Από την άλλη πλευρά, υπάρχουν ποικίλες φόρμες όπου ισχύει: κάθε κομμάτι, ένα πρωτότυπο. Η μορφή τους περιγράφεται καλύτερα με τη γλώσσα HTML στο πρότυπο της φόρμας. Και φυσικά, εκτός από τα δύο αναφερόμενα άκρα, θα συναντήσουμε πολλές φόρμες που κινούνται κάπου στη μέση.

Απόδοση με χρήση Latte

Το σύστημα προτύπων Latte διευκολύνει σημαντικά την απόδοση των φορμών και των στοιχείων τους. Πρώτα θα δείξουμε πώς να αποδίδετε τις φόρμες χειροκίνητα, στοιχείο προς στοιχείο, αποκτώντας έτσι πλήρη έλεγχο του κώδικα. Αργότερα θα δείξουμε πώς μπορεί αυτή η απόδοση να αυτοματοποιηθεί.

Μπορείτε να ζητήσετε τη δημιουργία του σχεδίου του προτύπου Latte της φόρμας χρησιμοποιώντας τη μέθοδο Nette\Forms\Blueprint::latte($form), η οποία θα το εκτυπώσει στη σελίδα του προγράμματος περιήγησης. Στη συνέχεια, αρκεί να επιλέξετε τον κώδικα με κλικ και να τον αντιγράψετε στο έργο σας.

{control}

Ο απλούστερος τρόπος για να αποδοθεί μια φόρμα είναι να γράψετε στο πρότυπο:

{control signInForm}

Μπορείτε να επηρεάσετε την εμφάνιση της φόρμας που αποδίδεται με αυτόν τον τρόπο διαμορφώνοντας τον Renderer και τα μεμονωμένα στοιχεία ελέγχου.

n:name

Ο ορισμός της φόρμας στον κώδικα PHP μπορεί να συνδεθεί εξαιρετικά εύκολα με τον κώδικα HTML. Αρκεί απλώς να προσθέσετε τα χαρακτηριστικά n:name. Είναι τόσο εύκολο!

protected function createComponentSignInForm(): Form
{
	$form = new Form;
	$form->addText('username')->setRequired();
	$form->addPassword('password')->setRequired();
	$form->addSubmit('send');
	return $form;
}
<form n:name=signInForm class=form>
	<div>
		<label n:name=username>Όνομα χρήστη: <input n:name=username size=20 autofocus></label>
	</div>
	<div>
		<label n:name=password>Κωδικός πρόσβασης: <input n:name=password></label>
	</div>
	<div>
		<input n:name=send class="btn btn-default">
	</div>
</form>

Έχετε τον πλήρη έλεγχο της μορφής του τελικού κώδικα HTML. Εάν χρησιμοποιήσετε το χαρακτηριστικό n:name στα στοιχεία <select>, <button> ή <textarea>, το εσωτερικό τους περιεχόμενο θα συμπληρωθεί αυτόματα. Επιπλέον, η ετικέτα <form n:name> δημιουργεί μια τοπική μεταβλητή $form με το αντικείμενο της αποδιδόμενης φόρμας και η κλείνουσα </form> αποδίδει όλα τα μη αποδοθέντα κρυφά στοιχεία (το ίδιο ισχύει και για {form} ... {/form}).

Ωστόσο, δεν πρέπει να ξεχάσουμε να αποδώσουμε τα πιθανά μηνύματα σφάλματος. Και αυτά που προστέθηκαν με τη μέθοδο addError() στα μεμονωμένα στοιχεία (χρησιμοποιώντας {inputError}), και αυτά που προστέθηκαν απευθείας στη φόρμα (τα επιστρέφει η $form->getOwnErrors()):

<form n:name=signInForm class=form>
	<ul class="errors" n:ifcontent>
		<li n:foreach="$form->getOwnErrors() as $error">{$error}</li>
	</ul>

	<div>
		<label n:name=username>Όνομα χρήστη: <input n:name=username size=20 autofocus></label>
		<span class=error n:ifcontent>{inputError username}</span>
	</div>
	<div>
		<label n:name=password>Κωδικός πρόσβασης: <input n:name=password></label>
		<span class=error n:ifcontent>{inputError password}</span>
	</div>
	<div>
		<input n:name=send class="btn btn-default">
	</div>
</form>

Πιο σύνθετα στοιχεία φόρμας, όπως το RadioList ή το CheckboxList, μπορούν να αποδοθούν με αυτόν τον τρόπο ανά μεμονωμένο στοιχείο:

{foreach $form[gender]->getItems() as $key => $label}
	<label n:name="gender:$key"><input n:name="gender:$key"> {$label}</label>
{/foreach}

{label} {input}

Δεν θέλετε να σκέφτεστε για κάθε στοιχείο ποιο στοιχείο HTML να χρησιμοποιήσετε στο πρότυπο, αν <input>, <textarea> κ.λπ.; Η λύση είναι η καθολική ετικέτα {input}:

<form n:name=signInForm class=form>
	<ul class="errors" n:ifcontent>
		<li n:foreach="$form->getOwnErrors() as $error">{$error}</li>
	</ul>

	<div>
		{label username}Όνομα χρήστη: {input username, size: 20, autofocus: true}{/label}
		{inputError username}
	</div>
	<div>
		{label password}Κωδικός πρόσβασης: {input password}{/label}
		{inputError password}
	</div>
	<div>
		{input send, class: "btn btn-default"}
	</div>
</form>

Εάν η φόρμα χρησιμοποιεί μεταφραστή, το κείμενο μέσα στις ετικέτες {label} θα μεταφραστεί.

Ακόμη και σε αυτή την περίπτωση, πιο σύνθετα στοιχεία φόρμας, όπως το RadioList ή το CheckboxList, μπορούν να αποδοθούν ανά μεμονωμένο στοιχείο:

{foreach $form[gender]->items as $key => $label}
	{label gender:$key}{input gender:$key} {$label}{/label}
{/foreach}

Για να αποδώσετε μόνο το <input> στο στοιχείο Checkbox, χρησιμοποιήστε {input myCheckbox:}. Σε αυτή την περίπτωση, διαχωρίζετε πάντα τα χαρακτηριστικά HTML με κόμμα {input myCheckbox:, class: required}.

{inputError}

Εκτυπώνει το μήνυμα σφάλματος για ένα στοιχείο φόρμας, αν υπάρχει. Συνήθως τυλίγουμε το μήνυμα σε ένα στοιχείο HTML για στυλ. Μπορείτε να αποτρέψετε την απόδοση ενός κενού στοιχείου εάν δεν υπάρχει μήνυμα, κομψά με τη χρήση του n:ifcontent:

<span class=error n:ifcontent>{inputError $input}</span>

Μπορούμε να ελέγξουμε την παρουσία σφάλματος με τη μέθοδο hasErrors() και ανάλογα να ορίσουμε την κλάση στο γονικό στοιχείο:

<div n:class="$form[username]->hasErrors() ? 'error'">
	{input username}
	{inputError username}
</div>

{form}

Οι ετικέτες {form signInForm}...{/form} είναι μια εναλλακτική λύση για το <form n:name="signInForm">...</form>.

Αυτόματη απόδοση

Χάρη στις ετικέτες {input} και {label}, μπορούμε εύκολα να δημιουργήσουμε ένα γενικό πρότυπο για οποιαδήποτε φόρμα. Θα επαναλαμβάνει και θα αποδίδει διαδοχικά όλα τα στοιχεία της, εκτός από τα κρυφά στοιχεία, τα οποία αποδίδονται αυτόματα κατά το κλείσιμο της φόρμας με την ετικέτα </form>. Το όνομα της αποδιδόμενης φόρμας θα αναμένεται στη μεταβλητή $form.

<form n:name=$form class=form>
	<ul class="errors" n:ifcontent>
		<li n:foreach="$form->getOwnErrors() as $error">{$error}</li>
	</ul>

	<div n:foreach="$form->getControls() as $input"
		n:if="$input->getOption(type) !== hidden">
		{label $input /}
		{input $input}
		{inputError $input}
	</div>
</form>

Οι χρησιμοποιούμενες αυτοκλειόμενες ζευγαρωτές ετικέτες {label .../} εμφανίζουν τις ετικέτες που προέρχονται από τον ορισμό της φόρμας στον κώδικα PHP.

Αποθηκεύστε αυτό το γενικό πρότυπο, για παράδειγμα, στο αρχείο basic-form.latte και για να αποδώσετε τη φόρμα, αρκεί να το συμπεριλάβετε και να περάσετε το όνομα (ή την παρουσία) της φόρμας στην παράμετρο $form:

{include basic-form.latte, form: signInForm}

Αν θέλετε να παρέμβετε στη μορφή μιας συγκεκριμένης φόρμας κατά την απόδοσή της και, για παράδειγμα, να αποδώσετε ένα στοιχείο διαφορετικά, ο ευκολότερος τρόπος είναι να προετοιμάσετε μπλοκ στο πρότυπο που θα μπορούν στη συνέχεια να αντικατασταθούν. Τα μπλοκ μπορούν επίσης να έχουν δυναμικά ονόματα μπλοκ, οπότε μπορείτε να εισαγάγετε σε αυτά και το όνομα του αποδιδόμενου στοιχείου. Για παράδειγμα:

...
	{label $input /}
	{block "input-{$input->name}"}{input $input}{/block}
...

Για το στοιχείο, π.χ., username, δημιουργείται έτσι το μπλοκ input-username, το οποίο μπορεί εύκολα να αντικατασταθεί χρησιμοποιώντας την ετικέτα {embed}:

{embed basic-form.latte, form: signInForm}
	{block input-username}
		<span class=important>
			{include parent}
		</span>
	{/block}
{/embed}

Εναλλακτικά, μπορείτε να define ολόκληρο το περιεχόμενο του template basic-form.latte ως μπλοκ, συμπεριλαμβανομένης της παραμέτρου $form:

{define basic-form, $form}
	<form n:name=$form class=form>
		...
	</form>
{/define}

Χάρη σε αυτό, η κλήση του θα είναι ελαφρώς απλούστερη:

{embed basic-form, signInForm}
	...
{/embed}

Το μπλοκ αρκεί να εισαχθεί σε ένα μόνο σημείο, στην αρχή του προτύπου της διάταξης:

{import basic-form.latte}

Ειδικές περιπτώσεις

Εάν χρειάζεστε να αποδώσετε μόνο το εσωτερικό μέρος της φόρμας χωρίς τις ετικέτες HTML <form>, για παράδειγμα κατά την αποστολή αποσπασμάτων, αποκρύψτε τις χρησιμοποιώντας το χαρακτηριστικό n:tag-if:

<form n:name=signInForm n:tag-if=false>
	<div>
		<label n:name=username>Όνομα χρήστη: <input n:name=username></label>
		{inputError username}
	</div>
</form>

Η ετικέτα {formContainer} βοηθά στην απόδοση των στοιχείων μέσα σε ένα κοντέινερ φόρμας.

<p>Ποιες ειδήσεις θέλετε να λαμβάνετε:</p>

{formContainer emailNews}
<ul>
	<li>{input sport} {label sport /}</li>
	<li>{input science} {label science /}</li>
</ul>
{/formContainer}

Απόδοση χωρίς Latte

Ο απλούστερος τρόπος για να αποδοθεί μια φόρμα είναι να καλέσετε:

$form->render();

Μπορείτε να επηρεάσετε την εμφάνιση της φόρμας που αποδίδεται με αυτόν τον τρόπο διαμορφώνοντας τον Renderer και τα μεμονωμένα στοιχεία ελέγχου.

Χειροκίνητη απόδοση

Κάθε στοιχείο φόρμας διαθέτει μεθόδους που παράγουν τον κώδικα HTML του πεδίου της φόρμας και της ετικέτας. Μπορούν να τον επιστρέψουν είτε ως συμβολοσειρά είτε ως αντικείμενο Nette\Utils\Html:

  • getControl(): Html|string επιστρέφει τον κώδικα HTML του στοιχείου
  • getLabel($caption = null): Html|string|null επιστρέφει τον κώδικα HTML της ετικέτας, αν υπάρχει

Έτσι, η φόρμα μπορεί να αποδοθεί ανά μεμονωμένο στοιχείο:

<?php $form->render('begin') ?>
<?php $form->render('errors') ?>

<div>
	<?= $form['name']->getLabel() ?>
	<?= $form['name']->getControl() ?>
	<span class=error><?= htmlspecialchars($form['name']->getError()) ?></span>
</div>

<div>
	<?= $form['age']->getLabel() ?>
	<?= $form['age']->getControl() ?>
	<span class=error><?= htmlspecialchars($form['age']->getError()) ?></span>
</div>

// ...

<?php $form->render('end') ?>

Ενώ σε ορισμένα στοιχεία η getControl() επιστρέφει ένα μοναδικό στοιχείο HTML (π.χ. <input>, <select> κ.λπ.), σε άλλα επιστρέφει ένα ολόκληρο κομμάτι κώδικα HTML (CheckboxList, RadioList). Σε αυτή την περίπτωση, μπορείτε να χρησιμοποιήσετε μεθόδους που παράγουν μεμονωμένες εισόδους και ετικέτες, για κάθε στοιχείο ξεχωριστά:

  • getControlPart($key = null): ?Html επιστρέφει τον κώδικα HTML ενός μεμονωμένου στοιχείου
  • getLabelPart($key = null): ?Html επιστρέφει τον κώδικα HTML της ετικέτας ενός μεμονωμένου στοιχείου

Αυτές οι μέθοδοι έχουν το πρόθεμα get για ιστορικούς λόγους, αλλά το generate θα ήταν καλύτερο, επειδή σε κάθε κλήση δημιουργούν και επιστρέφουν ένα νέο στοιχείο Html.

Renderer

Πρόκειται για ένα αντικείμενο που εξασφαλίζει την απόδοση της φόρμας. Μπορεί να οριστεί με τη μέθοδο $form->setRenderer. Ο έλεγχος του περνά όταν καλείται η μέθοδος $form->render().

Εάν δεν ορίσουμε δικό μας renderer, θα χρησιμοποιηθεί ο προεπιλεγμένος renderer Nette\Forms\Rendering\DefaultFormRenderer. Αυτός αποδίδει τα στοιχεία της φόρμας με τη μορφή πίνακα HTML. Η έξοδος μοιάζει κάπως έτσι:

<table>
<tr class="required">
	<th><label class="required" for="frm-name">Όνομα:</label></th>

	<td><input type="text" class="text" name="name" id="frm-name" required value=""></td>
</tr>

<tr class="required">
	<th><label class="required" for="frm-age">Ηλικία:</label></th>

	<td><input type="text" class="text" name="age" id="frm-age" required value=""></td>
</tr>

<tr>
	<th><label>Φύλο:</label></th>
	...

Το αν θα χρησιμοποιηθεί ή όχι πίνακας για τη δομή της φόρμας είναι αμφιλεγόμενο και πολλοί σχεδιαστές ιστοσελίδων προτιμούν άλλη σήμανση. Για παράδειγμα, μια λίστα ορισμών. Θα αναδιαμορφώσουμε λοιπόν τον DefaultFormRenderer έτσι ώστε να αποδώσει τη φόρμα με τη μορφή λίστας. Η διαμόρφωση γίνεται επεξεργαζόμενοι τον πίνακα $wrappers. Ο πρώτος δείκτης αντιπροσωπεύει πάντα την περιοχή και ο δεύτερος το χαρακτηριστικό της. Οι μεμονωμένες περιοχές απεικονίζονται στην εικόνα:

Από προεπιλογή, η ομάδα στοιχείων controls περιβάλλεται από έναν πίνακα <table>, κάθε pair αντιπροσωπεύει μια γραμμή του πίνακα <tr> και το ζεύγος label και control είναι κελιά <th> και <td>. Τώρα θα αλλάξουμε τα περιβάλλοντα στοιχεία. Θα εισαγάγουμε την περιοχή controls σε ένα container <dl>, την περιοχή pair θα την αφήσουμε χωρίς container, το label θα το εισαγάγουμε σε <dt> και τέλος το control θα το περιβάλλουμε με ετικέτες <dd>:

$renderer = $form->getRenderer();
$renderer->wrappers['controls']['container'] = 'dl';
$renderer->wrappers['pair']['container'] = null;
$renderer->wrappers['label']['container'] = 'dt';
$renderer->wrappers['control']['container'] = 'dd';

$form->render();

Το αποτέλεσμα είναι ο ακόλουθος κώδικας HTML:

<dl>
	<dt><label class="required" for="frm-name">Όνομα:</label></dt>

	<dd><input type="text" class="text" name="name" id="frm-name" required value=""></dd>


	<dt><label class="required" for="frm-age">Ηλικία:</label></dt>

	<dd><input type="text" class="text" name="age" id="frm-age" required value=""></dd>


	<dt><label>Φύλο:</label></dt>
	...
</dl>

Στον πίνακα wrappers μπορείτε να επηρεάσετε πολλά άλλα χαρακτηριστικά:

  • προσθήκη κλάσεων CSS σε μεμονωμένους τύπους στοιχείων φόρμας
  • διάκριση μονών και ζυγών γραμμών με κλάση CSS
  • οπτική διάκριση υποχρεωτικών και προαιρετικών στοιχείων
  • καθορισμός αν τα μηνύματα σφάλματος θα εμφανίζονται απευθείας στα στοιχεία ή πάνω από τη φόρμα

Options

Η συμπεριφορά του Renderer μπορεί επίσης να ελεγχθεί ορίζοντας options στα μεμονωμένα στοιχεία της φόρμας. Με αυτόν τον τρόπο μπορείτε να ορίσετε την ετικέτα που θα εκτυπωθεί δίπλα στο πεδίο εισαγωγής:

$form->addText('phone', 'Αριθμός:')
	->setOption('description', 'Αυτός ο αριθμός θα παραμείνει κρυφός');

Εάν θέλουμε να τοποθετήσουμε περιεχόμενο HTML σε αυτό, θα χρησιμοποιήσουμε την κλάση Html

use Nette\Utils\Html;

$form->addText('phone', 'Αριθμός:')
	->setOption('description', Html::el('p')
		->setHtml('<a href="...">Όροι διατήρησης του αριθμού σας</a>')
	);

Το στοιχείο Html μπορεί επίσης να χρησιμοποιηθεί αντί για ετικέτα: $form->addCheckbox('conditions', $label).

Ομαδοποίηση στοιχείων

Ο Renderer επιτρέπει την ομαδοποίηση στοιχείων σε οπτικές ομάδες (fieldsets):

$form->addGroup('Προσωπικά δεδομένα');

Μετά τη δημιουργία μιας νέας ομάδας, αυτή γίνεται ενεργή και κάθε νεοεισερχόμενο στοιχείο προστίθεται ταυτόχρονα και σε αυτήν. Έτσι, η φόρμα μπορεί να κατασκευαστεί με αυτόν τον τρόπο:

$form = new Form;
$form->addGroup('Προσωπικά δεδομένα');
$form->addText('name', 'Το όνομά σας:');
$form->addInteger('age', 'Η ηλικία σας:');
$form->addEmail('email', 'Email:');

$form->addGroup('Διεύθυνση αποστολής');
$form->addCheckbox('send', 'Αποστολή στη διεύθυνση');
$form->addText('street', 'Οδός:');
$form->addText('city', 'Πόλη:');
$form->addSelect('country', 'Χώρα:', $countries);

Ο Renderer αποδίδει πρώτα τις ομάδες και μετά τα στοιχεία που δεν ανήκουν σε καμία ομάδα.

Υποστήριξη για Bootstrap

Στα παραδείγματα θα βρείτε παραδείγματα για το πώς να διαμορφώσετε τον Renderer για Twitter Bootstrap 2, Bootstrap 3 και Bootstrap 4

Χαρακτηριστικά HTML

Για να ορίσετε οποιαδήποτε χαρακτηριστικά HTML για τα στοιχεία της φόρμας, χρησιμοποιούμε τη μέθοδο setHtmlAttribute(string $name, $value = true):

$form->addInteger('number', 'Αριθμός:')
	->setHtmlAttribute('class', 'big-number');

$form->addSelect('rank', 'Ταξινόμηση κατά:', ['τιμής', 'ονόματος'])
	->setHtmlAttribute('onchange', 'submit()'); // υποβολή κατά την αλλαγή


// Για να ορίσετε χαρακτηριστικά για το ίδιο το <form>
$form->setHtmlAttribute('id', 'myForm');

Προδιαγραφή του τύπου του στοιχείου:

$form->addText('tel', 'Το τηλέφωνό σας:')
	->setHtmlType('tel')
	->setHtmlAttribute('placeholder', 'γράψτε το τηλέφωνο');

Η ρύθμιση του τύπου και άλλων χαρακτηριστικών χρησιμεύει μόνο για οπτικούς σκοπούς. Η επαλήθευση της ορθότητας των εισόδων πρέπει να γίνεται στον διακομιστή, πράγμα που εξασφαλίζετε επιλέγοντας το κατάλληλο στοιχείο φόρμας και δηλώνοντας κανόνες επικύρωσης.

Μπορούμε να ορίσουμε χαρακτηριστικά HTML για μεμονωμένα στοιχεία σε λίστες radio ή checkbox με διαφορετικές τιμές για καθένα από αυτά. Παρατηρήστε την άνω και κάτω τελεία μετά το style:, η οποία εξασφαλίζει την επιλογή της τιμής βάσει κλειδιού:

$colors = ['r' => 'κόκκινο', 'g' => 'πράσινο', 'b' => 'μπλε'];
$styles = ['r' => 'background:red', 'g' => 'background:green'];
$form->addCheckboxList('colors', 'Χρώματα:', $colors)
	->setHtmlAttribute('style:', $styles);

Εκτυπώνει:

<label><input type="checkbox" name="colors[]" style="background:red" value="r">κόκκινο</label>
<label><input type="checkbox" name="colors[]" style="background:green" value="g">πράσινο</label>
<label><input type="checkbox" name="colors[]" value="b">μπλε</label>

Για να ορίσετε λογικά χαρακτηριστικά, όπως το readonly, μπορούμε να χρησιμοποιήσουμε τη σύνταξη με ερωτηματικό:

$form->addCheckboxList('colors', 'Χρώματα:', $colors)
	->setHtmlAttribute('readonly?', 'r'); // για πολλαπλά κλειδιά χρησιμοποιήστε έναν πίνακα, π.χ. ['r', 'g']

Εκτυπώνει:

<label><input type="checkbox" name="colors[]" readonly value="r">κόκκινο</label>
<label><input type="checkbox" name="colors[]" value="g">πράσινο</label>
<label><input type="checkbox" name="colors[]" value="b">μπλε</label>

Στην περίπτωση των selectbox, η μέθοδος setHtmlAttribute() ορίζει τα χαρακτηριστικά του στοιχείου <select>. Εάν θέλουμε να ορίσουμε χαρακτηριστικά για μεμονωμένα <option>, χρησιμοποιούμε τη μέθοδο setOptionAttribute(). Λειτουργούν επίσης οι συντάξεις με άνω και κάτω τελεία και ερωτηματικό που αναφέρθηκαν παραπάνω:

$form->addSelect('colors', 'Χρώματα:', $colors)
	->setOptionAttribute('style:', $styles);

Εκτυπώνει:

<select name="colors">
	<option value="r" style="background:red">κόκκινο</option>
	<option value="g" style="background:green">πράσινο</option>
	<option value="b">μπλε</option>
</select>

Πρωτότυπα

Ένας εναλλακτικός τρόπος ορισμού των χαρακτηριστικών HTML συνίσταται στην τροποποίηση του προτύπου από το οποίο παράγεται το στοιχείο HTML. Το πρότυπο είναι ένα αντικείμενο Html και το επιστρέφει η μέθοδος getControlPrototype():

$input = $form->addInteger('number', 'Αριθμός:');
$html = $input->getControlPrototype(); // <input>
$html->class('big-number');            // <input class="big-number">

Με αυτόν τον τρόπο μπορείτε να τροποποιήσετε και το πρότυπο της ετικέτας, το οποίο επιστρέφει η getLabelPrototype():

$html = $input->getLabelPrototype(); // <label>
$html->class('distinctive');         // <label class="distinctive">

Στα στοιχεία Checkbox, CheckboxList και RadioList μπορείτε να επηρεάσετε το πρότυπο του στοιχείου που περιβάλλει ολόκληρο το στοιχείο. Το επιστρέφει η getContainerPrototype(). Στην προεπιλεγμένη κατάσταση, πρόκειται για ένα «κενό» στοιχείο, οπότε δεν αποδίδεται τίποτα, αλλά ορίζοντας του ένα όνομα, θα αποδίδεται:

$input = $form->addCheckbox('send');
$html = $input->getContainerPrototype();
$html->setName('div'); // <div>
$html->class('check'); // <div class="check">
echo $input->getControl();
// <div class="check"><label><input type="checkbox" name="send"></label></div>

Στην περίπτωση των CheckboxList και RadioList μπορείτε να επηρεάσετε και το πρότυπο του διαχωριστή των μεμονωμένων στοιχείων, το οποίο επιστρέφει η μέθοδος getSeparatorPrototype(). Στην προεπιλεγμένη κατάσταση, είναι το στοιχείο <br>. Εάν το αλλάξετε σε ζευγαρωτό στοιχείο, θα περιβάλλει τα μεμονωμένα στοιχεία αντί να τα διαχωρίζει. Και επιπλέον, μπορείτε να επηρεάσετε το πρότυπο του στοιχείου HTML της ετικέτας στα μεμονωμένα στοιχεία, το οποίο επιστρέφει η getItemLabelPrototype().

Μετάφραση

Εάν προγραμματίζετε μια πολύγλωσση εφαρμογή, πιθανότατα θα χρειαστείτε να αποδώσετε τη φόρμα σε διάφορες γλωσσικές εκδόσεις. Το Nette Framework ορίζει για αυτόν τον σκοπό μια διεπαφή για μετάφραση Nette\Localization\Translator. Στη Nette δεν υπάρχει προεπιλεγμένη υλοποίηση, μπορείτε να επιλέξετε ανάλογα με τις ανάγκες σας από διάφορες έτοιμες λύσεις που θα βρείτε στο Componette. Στην τεκμηρίωσή τους θα μάθετε πώς να διαμορφώσετε τον μεταφραστή.

Οι φόρμες υποστηρίζουν την εκτύπωση κειμένων μέσω του μεταφραστή. Τον περνάμε σε αυτές χρησιμοποιώντας τη μέθοδο setTranslator():

$form->setTranslator($translator);

Από αυτή τη στιγμή, όχι μόνο όλες οι ετικέτες, αλλά και όλα τα μηνύματα σφάλματος ή τα στοιχεία των πλαισίων επιλογής μεταφράζονται σε άλλη γλώσσα.

Στα μεμονωμένα στοιχεία της φόρμας, είναι δυνατόν να οριστεί διαφορετικός μεταφραστής ή να απενεργοποιηθεί εντελώς η μετάφραση με την τιμή null:

$form->addSelect('carModel', 'Μοντέλο:', $cars)
	->setTranslator(null);

Στους κανόνες επικύρωσης, περνούν στον μεταφραστή και συγκεκριμένες παράμετροι, για παράδειγμα στον κανόνα:

$form->addPassword('password', 'Κωδικός πρόσβασης:')
	->addRule($form::MinLength, 'Ο κωδικός πρόσβασης πρέπει να έχει τουλάχιστον %d χαρακτήρες', 8);

καλείται ο μεταφραστής με αυτές τις παραμέτρους:

$translator->translate('Ο κωδικός πρόσβασης πρέπει να έχει τουλάχιστον %d χαρακτήρες', 8);

και επομένως μπορεί να επιλέξει τη σωστή μορφή πληθυντικού για τη λέξη χαρακτήρες ανάλογα με τον αριθμό.

Το συμβάν onRender

Λίγο πριν αποδοθεί η φόρμα, μπορούμε να αφήσουμε να κληθεί ο κώδικάς μας. Αυτός μπορεί, για παράδειγμα, να συμπληρώσει τα στοιχεία της φόρμας με κλάσεις HTML για σωστή εμφάνιση. Προσθέτουμε τον κώδικα στον πίνακα onRender:

$form->onRender[] = function ($form) {
	BootstrapCSS::initialize($form);
};
έκδοση: 4.0