Změna renderování checkboxu uvnitř Label
- ajda2
- Člen | 66
Zdravím Vás,
narazil jsem na menší problém při tvorbě „vlastního“ rendereru pro
formuláře.
Mým cílem je změnit výchozí vykreslování checkboxu uvnitř labelu na
tento tvar:
<label for="checkbox-id">
<input type="checkbox" name="active" id="checkbox-id">
<span class="nejaka-trida">TENTO SPAN CHCI VLOŽIT VČETNĚ TŘÍDY</span>
Label checkboxu
</label>
Za tímto účelem jsem si vytvořil vlastní renderer, který dědí od https://api.nette.org/…enderer.html
abych nemusel začínat na zelené louce.
Přetížil jsem metodu renderControl
, abych v ní vložil do
labelu svůj kýžený span.
Zde jsem právě narazil na problém.
<?php
$el = $control->getControl();
if ($el instanceof Html && $el->getName() === 'input') {
$el->class($this->getValue("control .$el->type"), TRUE);
}
return $body->setHtml($el . $description . $this->renderErrors($control));
?>
Konkrétně volání metody getControl()
způsobí, že
veškeré mnou vložené HTML elementy do Labelu jsou nenávratně ztraceny,
protože se nastaví HTML obsah docela brutálním způsobem napřímo pomocí
metody setHtml
jako řetězec a není jej možné poté snadno
editovat, protože veškerý obsah je řetězec.
Viz https://api.nette.org/…box.php.html#…
Nenapadá někoho prosím nějaké jednoduché řešení, jak vložit
nějaký HTML obsah dovnitř Label za samotný checkbox?
Řešením by nejspíš bylo změnit drastické vkládání HTML obsahu skrze
metodu setHtml
a nahradit ji insert
, nebo
add
, ale vytvářet vlastní checkBox třídu a vlastní Form,
který jej bude používat mi přijde zbytečně pracné.
Předem děkuji za pomoc a rady.
Editoval ajda2 (30. 6. 2016 8:36)
- Oli
- Člen | 1215
Jde změnit nějak líp renderování checkboxu (selectu, radio listu)?
Potřeboval bych kvůli material designu například aby v checkboxu input nebyl
obalenej labelem. Renderer jsem si napsal, ale do něj jde z Control\Checkbox
už hotovej řetězec
<label><input/></label>
.
To by znamenalo napsat vlastní implementaci
Control\Checkbox
u a UI\Form
. Pokud bych chtěl ale
použít jinej form, musel bych to definovat znovu, takže vlastně bych měl
udělat i vlastní Form\Form
a Forms\Container
.
Není to trochu zbytečné? Neexistuje nějaký parametr, něco, který by zajistil, že se input nebude obalovat do label?
EDIT:
Jak to tak bývá, sotva se zeptám, najdu řešení. Checkbox i radio list
mají metodu getControlPart
a getLabelPart
. Takže pak
stačí v renderControl něco takového:
if ($control instanceof Nette\Forms\Controls\Checkbox)
{
$el = $control->getControlPart();
} else {
$el = $control->getControl();
}
Editoval Oli (15. 11. 2016 8:29)
- steelbull
- Člen | 241
@Oli Presne to isté by som potreboval aj ja, vyriešil si to nejako?
Oli napsal(a):
Jde změnit nějak líp renderování checkboxu (selectu, radio listu)?
Potřeboval bych kvůli material designu například aby v checkboxu input nebyl obalenej labelem. Renderer jsem si napsal, ale do něj jde z Control\Checkbox už hotovej řetězec
<label><input/></label>
.To by znamenalo napsat vlastní implementaci
Control\Checkbox
u aUI\Form
. Pokud bych chtěl ale použít jinej form, musel bych to definovat znovu, takže vlastně bych měl udělat i vlastníForm\Form
aForms\Container
.Není to trochu zbytečné? Neexistuje nějaký parametr, něco, který by zajistil, že se input nebude obalovat do label?
EDIT:
Jak to tak bývá, sotva se zeptám, najdu řešení. Checkbox i radio list mají metodu
getControlPart
agetLabelPart
. Takže pak stačí v renderControl něco takového:if ($control instanceof Nette\Forms\Controls\Checkbox) { $el = $control->getControlPart(); } else { $el = $control->getControl(); }
Editoval steelbull (25. 2. 2018 10:20)
- steelbull
- Člen | 241
@Oli Ja potrebujem vyrenderovať toto:
<input type="checkbox" id="1" class="k-checkbox" checked="checked">
<label class="k-checkbox-label" for="1">Rear side airbags</label>
Oli napsal(a):
Jde změnit nějak líp renderování checkboxu (selectu, radio listu)?
Potřeboval bych kvůli material designu například aby v checkboxu input nebyl obalenej labelem. Renderer jsem si napsal, ale do něj jde z Control\Checkbox už hotovej řetězec
<label><input/></label>
.To by znamenalo napsat vlastní implementaci
Control\Checkbox
u aUI\Form
. Pokud bych chtěl ale použít jinej form, musel bych to definovat znovu, takže vlastně bych měl udělat i vlastníForm\Form
aForms\Container
.Není to trochu zbytečné? Neexistuje nějaký parametr, něco, který by zajistil, že se input nebude obalovat do label?
EDIT:
Jak to tak bývá, sotva se zeptám, najdu řešení. Checkbox i radio list mají metodu
getControlPart
agetLabelPart
. Takže pak stačí v renderControl něco takového:if ($control instanceof Nette\Forms\Controls\Checkbox) { $el = $control->getControlPart(); } else { $el = $control->getControl(); }
- jurajkovac
- Člen | 2
Tu je riešenie, ak sa nájde niekto ďalší, kto potrebuje vykresľovať checkbox/radio button a label za sebou.
1. Jednoduchá, ale pracnejšia cesta: low-level
rendering
Namiesto prostého {control myForm}
si všetko
vymenujem ručne:
{form myForm}
{input choices:itemA}{label choices:itemA /}
{input choices:itemB}{label choices:itemB /}
...
{/form}
Samozrejme je možné to zabaliť do cyklu a vymenovať automaticky:
{form myForm}
{foreach $form['choices']->items as $key => $label}
{input choices:$key}{label choices:$key /}
{/foreach}
{/form}
2. Náročnejšia, ale udržateľnejšia cesta: custom
renderer
Vytvorím si vlastný form renderer, ktorý zdedí všetky schopnosti od
DefaultFormRenderer
, avšak pre radio buttons a checkboxy bude
uplatňovať vlastnú logiku vykresľovania.
Vytvorím si teda novú triedu ako extension
Nette\Forms\Rendering\DefaultFormRenderer
a úplne stačí, aby
obsahovala jedinú metódu: renderControl()
Ideálne skopírovať ju kompletne z DefaultFormRendereru a len v nej
ošetríme konkrétne prípady pre RadioList a Checkbox:
class myFormRenderer extends Nette\Forms\Rendering\DefaultFormRenderer
public function renderControl(Nette\Forms\IControl $control) {
...
$control->setOption('rendered', true);
// Is this an instance of a RadioList or Checkbox?
if ($control instanceof Nette\Forms\Controls\Checkbox || $control instanceof Nette\Forms\Controls\RadioList) {
// Create an empty Html container object
$el = Html::el();
// Get all the child items
$items = $control->getItems();
// For each child item, add the appropriate control part and label part after one another
foreach($items as $key => $item) {
$el->addHtml($control->getControlPart($key));
$el->addHtml($control->getLabelPart($key));
}
// For all other control types, revert to default functionality
} else {
$el = $control->getControl();
}
...
}
Snáď to pomôže každému, kto potrebuje použiteľný
input[type=radio]+label
CSS selektor.
Poďakovanie patrí @Oli, ktorý ma priviedol na správnu stopu.
- steelbull
- Člen | 241
jurajkovac napsal(a):
Tu je riešenie, ak sa nájde niekto ďalší, kto potrebuje vykresľovať checkbox/radio button a label za sebou.
1. Jednoduchá, ale pracnejšia cesta: low-level rendering
Namiesto prostého{control myForm}
si všetko vymenujem ručne:{form myForm} {input choices:itemA}{label choices:itemA /} {input choices:itemB}{label choices:itemB /} ... {/form}
Samozrejme je možné to zabaliť do cyklu a vymenovať automaticky:
{form myForm} {foreach $form['choices']->items as $key => $label} {input choices:$key}{label choices:$key /} {/foreach} {/form}
2. Náročnejšia, ale udržateľnejšia cesta: custom renderer
Vytvorím si vlastný form renderer, ktorý zdedí všetky schopnosti odDefaultFormRenderer
, avšak pre radio buttons a checkboxy bude uplatňovať vlastnú logiku vykresľovania.Vytvorím si teda novú triedu ako extension
Nette\Forms\Rendering\DefaultFormRenderer
a úplne stačí, aby obsahovala jedinú metódu:renderControl()
Ideálne skopírovať ju kompletne z DefaultFormRendereru a len v nej ošetríme konkrétne prípady pre RadioList a Checkbox:class myFormRenderer extends Nette\Forms\Rendering\DefaultFormRenderer public function renderControl(Nette\Forms\IControl $control) { ... $control->setOption('rendered', true); // Is this an instance of a RadioList or Checkbox? if ($control instanceof Nette\Forms\Controls\Checkbox || $control instanceof Nette\Forms\Controls\RadioList) { // Create an empty Html container object $el = Html::el(); // Get all the child items $items = $control->getItems(); // For each child item, add the appropriate control part and label part after one another foreach($items as $key => $item) { $el->addHtml($control->getControlPart($key)); $el->addHtml($control->getLabelPart($key)); } // For all other control types, revert to default functionality } else { $el = $control->getControl(); } ... }
Snáď to pomôže každému, kto potrebuje použiteľný
input[type=radio]+label
CSS selektor.
Poďakovanie patrí @Oli, ktorý ma priviedol na správnu stopu.
- ten prvý prípad je pre mňa príliš zložitý, pretože tých checkboxov mám v množstve formulárov veľa. A potrebujem unifikované riešenie, ktoré potrebujem implementovať do viacerých projektov.
- ten druhý spôsob je pre mňa nepoužiteľný, pretože formulár renderujem nasledovne a pri manuálnom renderovaní sa FormRenderer neuplatňuje:
FormControl:
$form->addCheckbox('fin_soft_saving', $t->trans('project.form.fin_soft_saving'));
$form->addCheckbox('fin_ematrix', $t->trans('project.form.fin_ematrix'))
->setRequired(false);
Výsledok:
<div class="row">
<div class="col-md-3">
<label for="frm-form-form-fin_soft_saving"><input name="fin_soft_saving" id="frm-form-form-fin_soft_saving" type="checkbox">Soft saving?</label>
<span class="form-error-message"></span>
</div>
<div class="col-md-3">
<label for="frm-form-form-is_checked_by_CD"><input name="is_checked_by_CD" id="frm-form-form-is_checked_by_CD" type="checkbox">Overené CD?</label>
<span class="form-error-message"></span>
</div>
<div class="col-md-3">
<label for="frm-form-form-fin_ematrix"><input name="fin_ematrix" id="frm-form-form-fin_ematrix" type="checkbox">E-matica?</label>
<span class="form-error-message"></span>
</div>
</div>
- jurajkovac
- Člen | 2
steelbull napsal(a):
2. ten druhý spôsob je pre mňa nepoužiteľný, pretože formulár renderujem nasledovne a pri manuálnom renderovaní sa FormRenderer neuplatňuje:
A ako vyzerá kód v Latte?