DefaultFormRenderer::renderControl() – neuplatnění wrapperu při Html description

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Ondřej Bouda
Člen | 2
+
0
-

Zdravím vývojáře a rád bych se zeptal, jestli je nějaký (a příp. jaký) důvod, proč DefaultFormRenderer při renderování elementu neuplatňuje "control description" wrapper, pokud je description zadáno jako Html objekt. Konkrétně mířím na tento kus metody DefaultFormRenderer::renderControl():

$description = $control->getOption('description');
if ($description instanceof Html) {
	$description = ' ' . $control->getOption('description');

} elseif (is_string($description)) {
	$description = ' ' . $this->getWrapper('control description')->setText($control->translate($description));

} else {
	$description = '';
}

Mohla by vzniknout nějaká cesta, jak předat objekt, který by se vyrenderoval podobně jako se to děje s Html objekty, ale navíc byl obalen wrapperem jako ostatní, textově zadané descriptions?

Rád bych totiž formuláře rozšířil kromě description vstupních prvků i o nějakou rozšířenou nápovědu k danému prvku (např. v description řeknu, že se zadává datum a čas, v této rozšířené nápovědě bych uvedl, v jakém formátu datum a čas očekávám – nechci zabíjet místo na stránce tím, že bych nápovědu rovnou zobrazil jako description, ale zároveň ji chci nabídnout).

Jako nejelegantnější mi přišlo pro tento účel volat setOption('description', new HelpDescription('zadejte datum a cas', 'Format zadani je ...')), kde HelpDescription by dědila po Html a rovnou by vytvořila např. SPAN element s textovým obsahem ‚zadejte datum a cas‘ a title atributem ‚Format zadani je …‘ (a případně nějakou CSS třídou pro zvýraznění, že zde nápověda je). Tím ale přicházím o zabalení celého elementu do standardního wrapperu. Musel bych tak objektu HelpDescription předat i renderer, ze kterého by si vysosal, čím se má ještě obalit, což mi nepřipadá už tak elegantní, protože pokud se wrapper ve formuláři změní až po definici prvků, tohoto prvku se to už nedotkne a bude zabalovat stále starým wrapperem (jediné místo, kde vysosat wrapper, je totiž konstruktor třídy HelpDescription – nemůže si vzít jen referenci a wrapper vyhodnotit líně až při renderování, protože DefaultFormRenderer rozpoznává jen Html objekty a ty mají render() metodu finální a jako obsah akceptují jen hotové řetězce nebo jiné Html objekty, takže nemůžu změnit vykreslování description objektu, aby si vzalo z formuláře wrapper až při vykreslení – musí být už vyrenderovaný předem – rovnou při definici vstupního prvku – a pak když se wrapper změní, tohoto prvku se to už nedotkne).

Alternativou je použít vlastní renderer – podědit po DefaultFormRendereru a zkopírovat tělo metody renderControl s pouze drobnou změnou – rozpoznávání HelpDescription objektů, které by se standardně obalily jako ostatní, textově zadané description. To je ale o hubu – když se změní implementace renderControl, může se to rozbít.

Nebylo by na to nějaké koncepční řešení? Třeba obalovat i Html description wrapperem? Nebo rozšířit DefaultFormRenderer o detekci i jiných renderovatelných objektů, které by se tak mohly renderovat líně?