ConvetionalRenderer – Latte pomocník pro ruční renderování formuláře + Tw Bootstrap

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Filip Procházka
Moderator | 4668
+
0
-

Makro {input} vyžaduje přítomnost proměnné $_form, protože přijímá pouze cestu k prvku (proto tam mám lookupPath)

Pokud bys to chtěl napsat ještě lépe tak použij moje nová makra a bude to fungovat „samo“ :)

<div id="modalForm" class="modal hide" role="dialog" aria-labelledby="myModalLabel" aria-hidden="false">
{snippet modalForm}{if $showForm}
    {form $form}
        <div class="modal-header">
                <a class="close" data-dismiss="modal" aria-hidden="false">&times;</a>
                <h3 id="myModalLabel">{$formLabel}</h3>
        </div>
        <div class="modal-body">
        {form errors}
        {group "body"}
        </div>
        <div class="modal-footer">
        {foreach $form->getGroup('controls')->controls as $control}
                {input $control->lookupPath('Nette\Forms\Form')}
        {/foreach}
        </div>
    {/form}
{/if}{/snippet}
</div>
Honza Marek
Člen | 1664
+
0
-

Dá se zrušit třída form-horizontal?

Filip Procházka
Moderator | 4668
+
0
-

Ta by se tam měla přidávat jako default – tedy zrušíš ji tak, že tam dáš jinou form- třídu :)

Tomáš Jablonický
Člen | 115
+
0
-

Ahoj,

při použití tohoto rendereru jsem si všiml docela vysokého času … vykreslení formuláře klasickou metodou trvá něco do 100 ms ale formulář vykreslený pomocí Bootrstap Twitteru trvá trojnásobek (300 ms někdy skoro 400) – což už je trochu brzda.

Nešlo by to trochu optimalizovat?

Filip Procházka
Moderator | 4668
+
0
-

Mně vykreslení celé stránky trvá kolem 100ms. Nebude chyba jinde?

Každopádně nějaké optimalizace by se snad udělat daly.

Editoval HosipLan (6. 10. 2012 14:12)

David Ďurika
Člen | 328
+
0
-

pise mi to Unknown macro {pair} a mam pocit ze som ten addon implementoval spravne…
{$form->render($form[‚control-name‘])} mi fungue spravne

v com je problem ? dakujem

voda
Člen | 561
+
0
-

Smazal jsi cache?

Filip Procházka
Moderator | 4668
+
0
-

Pokud {pair} není obaleno do {form}, tak nebude fungovat. Což je napsané v „dokumentaci“ pluginu.

Editoval HosipLan (9. 10. 2012 16:58)

David Ďurika
Člen | 328
+
0
-

mam to obalene vo {form} tu je zablona:

<?php
{form phraseEditForm, class => 'row'}
	<div class="control-group span3">
		{label phraseType /}
		{input phraseType}
	</div>
	<div class="control-group span3">
		{label sourceLanguage /}
		{input sourceLanguage}
	</div>
	<div class="control-group span3">
		<label for="frmeditForm-source_languages"><b>Translation status</b></label>
		{$form->render($form['corrected'])}
		{pair ready}
		{* {$form->render($form['ready'])} toto funguje *}
	</div>
{/form}
?>
LeonardoCA
Člen | 296
+
0
-

Hosiplan: chybí mi v dokumentaci možnost vyrenderovat samostatný control – ne jako pair, je nějaká jednoduchá cesta?

Filip Procházka
Moderator | 4668
+
0
-

Co takhle klasické {input} ?

LeonardoCA
Člen | 296
+
0
-

to mi nedošlo a ne, díky

Editoval LeonardoCA (10. 10. 2012 13:10)

Felix
Nette Core | 1196
+
0
-

achtan napsal(a):

a co ten moj problem ? https://forum.nette.org/…tw-bootstrap?p=2

Vyreseno, nesmime zapominat na

Kdyby\Extension\Forms\BootstrapRenderer\DI\RendererExtension::register($configurator);

Editoval Felix (15. 10. 2012 9:33)

David Ďurika
Člen | 328
+
0
-

problem s CheckboxList-om
hlasi to http://grab.by/gZEI
ked vypnem bootsrapRenderer tak vsetko ide OK

Filip Procházka
Moderator | 4668
+
0
-

@achtan: jediné co můžu udělat, tak dát tam výjimku s „tuto implementaci checkboxlistu psalo prasátko, stahni si tohle “.

David Ďurika
Člen | 328
+
0
-

@HosipLan dik teraz to uz ide!

LeonardoCA
Člen | 296
+
0
-

@Hosiplan – trochu jsem zkoušel renderování profilovat a optimalizovat, používám 2× zanořený Replikátor a i poměrně jednoduchý formulář (asi 15 inputů v různých containerech + tlačítka) se mi renderuje cca 200–300ms.

Já se k tomu budu vracet až za delší dobu tak zase jen pár nápadů:

  • bez využití cache renderování znatelně urychlí použití jedné šablony místo dvou a hodí se to i proto, že se tak dá toho více přesunout do inicializace a nemusí se volat opakovaně v render
  • template si držím přímo v rendereru ať se nemusí opakovaně inicializovat při volání každého makra
  • přemýšlím jak omezit počet interního volání getControl() protože to mi při zapnutém XDebugExtension trvá cca 2ms a pro jeden prvek se volá 3× a pak renderovávání jednoho prvku trvá cca 8–17 ms v závislosti na tom jestli renderuji i label. Ono vlastně jsem si ještě trochu více přepsal inicializaci a povedlo se mi to snížit z původních cca 45ms na prvek bez cashování. (pořád jde o custom rendering při generování celého formuláře se to chová jinak)

Teď už nevím co všechno jsem měnil, ale jelikož to ještě není doladěné a čas není tak tu hodím akorát náznak: https://gist.github.com/4047257

Bez předání template v parametru to je v mém případě takřka nepoužitelné, čas roste takřka lineárně s počtem prvků a hravě jsem se tak dostal na jednotky sekund. Protože jsem chtěl všechny formuláře configurovat přes config.neon tak jim template předávám takto:

factories:
    bootstrapRenderer:
        class: Kdyby\Extension\Forms\BootstrapRenderer\BootstrapRenderer (@presenterAccessor::cloneTemplate())

PresenterAccessor si získává presenter od application za běhu, ale ještě se mi to stále nelíbí.

Editoval LeonardoCA (9. 11. 2012 19:54)

Filip Procházka
Moderator | 4668
+
0
-

Dělám na velkém refaktringu, stay tuned.

LeonardoCA
Člen | 296
+
0
-

Bezva. Ještě přihodím jeden poznatek. Pořád hledám optimální cestu definování formulářů a tak jsem zkoušel různé přístupy. Při použití mírně upravených továrniček z Venne se spouštělo volání beforeRender při každém generování containeru místo jen při generování formuláře a pak se celý formulář vygeneroval tolikrát, kolik bylo vložených containerů replikátorem. Zase jen při custom renderingu.

Příčinu jsem neobjevil, bylo to už trochu moc cizích kódů najednou čas krátký a je možné, že jsem tam zanesl nějakou chybu – ale když jsem přepl na default renderer tak ten formulář vykreslil správně akorát si neporadil s bootstrap specifickými makry.

Matúš Matula
Člen | 257
+
0
-

Ahoj,

nejako sa mi nedari zaregistrovat latte makra, v bootstrap.php mam nasledovny riadok

<?php
Kdyby\BootstrapFormRenderer\DI\RendererExtension::register($configurator);
?>

hned po zaregistrovani RobotLoadera

<?php
$configurator->createRobotLoader()
            ->addDirectory(APP_DIR)
            ->addDirectory(LIBS_DIR)
            ->register();
?>

ale pri pouziti custom makra to hodi
Nette\Latte\CompileException - There are unclosed macros in ..

nejake napady?

Filip Procházka
Moderator | 4668
+
0
-

Určitě neuškodí si doplněk zkusit aktualizovat.

Matúš Matula
Člen | 257
+
0
-

Sry, zabudol som napisat, ze som si prave stiahol najnovsiu verziu z githubu..

Edit: Aby nedoslo k nedorozumeniu, tu najnovsiu verziu som mal od zaciatku, len som to zabudol napisat v prispevku. Takze stale to nefunguje..

Edit2: Vyzera to, ze stacilo zmazat cache :-) Sorry za false report.

Editoval Matúš Matula (28. 1. 2013 16:20)

MartinitCZ
Člen | 580
+
0
-

Ahoj,
používám tento doplněk a addDynamic() a narazil jsem na jeden problém.

Je možnost addDynamic() obalit nějakým div a případně jak?? Potřeboval bych totiž tuto část odsadit od zbytku formuláře.
Zkoušel jsem addGroup(), ale to bohužel není ono.

Děkuji.

Šaman
Člen | 2659
+
0
-

Ahoj, nechceš to ještě rozšířit o podporu ikon? Mě konkrétně by se to hodilo na kalendář, ale využití by se našlo častěji.

Představoval bych si to tak, že formulářovému prvku nastavím ->setOption('prepend-icon', 'icon-pencil'); a ono mi to správně vlepí ikonu do formu nebo do tlačítka.

Editoval Šaman (6. 2. 2013 6:38)

enumag
Člen | 2118
+
0
-

@Šaman: Jenom takto bys ale nemohl použít tyhle ikony, ne?

Filip Procházka
Moderator | 4668
+
0
-

Prepend umíme

$input->setOption('input-prepend', Html::el('i')->class('icon-pencil'));

Ale vylepšíme, vytvoříš mi issue, prosím?

darthcz
Člen | 113
+
0
-

achtan napsal(a):

problem s CheckboxList-om
hlasi to http://grab.by/gZEI
ked vypnem bootsrapRenderer tak vsetko ide OK

Mám úplně stejný problém, nemáte nějakou implementaci checkboxlist, u které to funguje? Zkoušel jsem i https://raw.github.com/…kboxList.php a bohužel pořád to samé :-/

Problém je, že checkboxlist vrací z funkce getControl($key) string, ale renderer očekává pole objektů Nette\Utils\Html…

Další problém je, že pokud dám checkboxlistu NULL nebo array(), tak se mi stejný prvek vykreslí dvakrát. Jednou ve skupině a jednou mimo skupinu. Se zadanými parametry místo NULL se vykreslí správně. S klasickým renderem vše funguje správně.

$this->addGroup('Propagace');

$this->addCheckboxList('features', 'Metody propagace', NULL);

Editoval darthcz (7. 2. 2013 5:52)

enumag
Člen | 2118
+
0
-

Zkus MultiOption list z nextras, funguje mi bez problémů. ;-)

Zbirek
Člen | 4
+
0
-

Zdravím, nevím si rady s naprostou banalitou. Nedaří se mi zaregistrovat Latte makra … Přikládám bootstrap.php. Používám aktuální verzi Sandboxu

<?php
use Nette\Forms\Container,
    Nette\Forms\Controls;



// Load Nette Framework or autoloader generated by Composer
require __DIR__ . '/../libs/autoload.php';


$configurator = new Nette\Config\Configurator;



// Enable Nette Debugger for error visualisation & logging
//$configurator->setDebugMode(TRUE);
$configurator->enableDebugger(__DIR__ . '/../log');

// Enable RobotLoader - this will load all classes automatically
$configurator->setTempDirectory(__DIR__ . '/../temp');
$configurator->createRobotLoader()
	->addDirectory(__DIR__)
	->addDirectory(__DIR__ . '/../libs')
	->register();

// Create Dependency Injection container from config.neon file
$configurator->addConfig(__DIR__ . '/config/config.neon');
$configurator->addConfig(__DIR__ . '/config/config.local.neon', $configurator::NONE); // none section

$container = $configurator->createContainer();

Kdyby\BootstrapFormRenderer\DI\RendererExtension::register($configurator);

return $container;

?>

Díky za každou radu

duskohu
Člen | 778
+
0
-

@Zbirek Zaregistroval si len Extension, macro musis zaregistrovat v templatePrepareFilters.
Skus nieco taketo do BasePresentru:

public function templatePrepareFilters($template) {
    $latte = $this->getContext()->createNette__Latte();
    \Kdyby\BootstrapFormRenderer\Latte\FormMacros::install($latte->compiler);
    $template->registerFilter($latte);
}

Edit: Odporucam pozriet: Registrace macra

Editoval duskohu (21. 3. 2013 10:33)

Zbirek
Člen | 4
+
0
-

Aha, už vím … díky moc pomohlo!

Filip Procházka
Moderator | 4668
+
0
-

Makro se registruje samo od sebe (v extension), ale pokud hackuješ Latte\Engine a přidáváš tam makra v presenteru, tak se to do něj z containeru nedostane.

duskohu
Člen | 778
+
0
-

Ahoj, Chcel by som sa spytat ci je moznost zmenit zakladnu sablonu, chcel by som zmenit class ControlError , kedze Description ma rovnaky class a pri error message mi naformatuje aj Description.

Filip111
Člen | 244
+
0
-

Ahoj, šel by BootstrapFormRenderer zaregistrovat pomocí neonu nebo v rámci nějaké jiné Extension?

Jde mi o to, že používám vlastní Cms jako Extension a přidávat řádek
Kdyby\BootstrapFormRenderer\DI\RendererExtension::register($configurator);
do mnoha bootstrapů se mi nechce.

Filip Procházka
Moderator | 4668
+
0
-

Pokud používáš vývojové Nette, tak stačí

extensions:
	twBootstrapRenderer: Kdyby\BootstrapFormRenderer\DI\RendererExtension
Filip111
Člen | 244
+
0
-

Perfektní…

až na to, že mi to nefunguje. Nahradil jsem verzi 2.0.5 za dev, přidal definici v neonu,
a začalo mi to házet chybu v presenteru, že $this->context->cms neexistuje.

Tedy vůbec se nezaregistrovalo původní rozšíření registrované v bootstrapu:

$configurator->onCompile[] = function ($configurator, $compiler) {
	$compiler->addExtension('cms', new CmsExtension);
};

Ještě jsem ho zkoušel přesunout do neonu

extensions:
	cms: CmsExtension
	#twBootstrapRenderer: Kdyby\BootstrapFormRenderer\DI\RendererExtension

ale to taky nepomůže.
Není k tomu někde nějaký info? Na fóru jsem nic(moc) nenašel a nechci tím zaplácnout tenhle topic.
Vůbec se mi nyní nedaří zaregistrovat jakékoliv extension.

enumag
Člen | 2118
+
0
-

@Filip111: Trochu si pleteš pojmy. V DIC ($this->context) jsou služby, nikoli extensions. Extension má pouze říct DI kontejneru, jaké služby má obsahovat – a tyto služby v něm pak najdeš. Extension by služby vždy mělo prefixovat takže výsledný název služby bude „cms.sluzba“ a dostal by ses k ní přes $this->context->{"cms.sluzba"}. Také zvaž použití inject místo context.

Editoval enumag (15. 4. 2013 21:17)

bazo
Člen | 620
+
0
-

v starsich verziach sa registruju sluzby pod nazvom extension. preto si mal v $context->cms nejaky objekt. v dev to uz nastastie nefunguje

Filip111
Člen | 244
+
0
-

O injectu vím, zatím se mi nechtělo všechno přepisovat.

Nevím, jestli mi něco neuteklo nebo jsem to jen špatně popsal, ale mám např. extension CmsExtension, ta má vlastní konfigurák cms.neon a v něm jsou definované služby, např.:

services:
	cms.catalogFilter:
		class: web123\Filters\CatalogFilter
		...
	cms.contentFilter
		class: ...
		...

K těmto službám pak v presenteru přistupuji např. pomocí $this->context->cms->catalogFilter
To je dobře nebo špatně (když pominu absenci injectu)?
Nyní po použítí dev verze vůbec nejsou načtené služby schované pod $this->context->cms.

enumag
Člen | 2118
+
0
-

To je špatně protože v 2.1 už není nested accessor. Správně je to takhle (jak jsem už psal):

$this->context->{'cms.catalogFilter'}
Quinix
Člen | 108
+
0
-

Dá se nějak přidat suffix k labelům (:), případně k povinným polím formuláře (*)?

enumag
Člen | 2118
+
0
-

@Quinix

label:after { content: ':' }

Ta * u povinných podobně, na to už přijdeš jistě sám.

Editoval enumag (23. 4. 2013 13:20)

t0x1c
Člen | 151
+
0
-

Zdravím. Mám problem když chci renderovat jednoduchý formulář s kodem v presenteru:

protected function createComponentServerForm() {
    $form = new UI\Form;
    $form->setRenderer(new BootstrapRenderer($this->createTemplate()));
    $form->addSelect('sluzba', 'Mám zájem o', array(
        'cs16' => 'Counter-Strike 1.6 - 10 slotů',
        'mc' => 'Minecraft+Bukkit - 5 slotů',
        'tekkit' => 'Tekkit - 5 slotů',
        'csgo' => 'CS:GO - 10 slotů'
    ))
            ->addRule(UI\Form::FILLED, "Toto pole je povinné!");
    $form->addSubmit('submit', 'Mám zájem o server')
            ->setAttribute('class', 'btn btn-large btn-warning')
            ->setAttribute('style', ''); //style
    $form->onSuccess[] = $this->serverFormSubmitted;
    return $form;
}

a v template

<div style="width: auto;height: auto;margin-left: auto;margin-right: auto">
{form serverForm}
{control $form errors}
{$form->render('errors')}
{$form->render('controls')}
{$form->render('buttons')}
{/form}
</div>

udělá mi to toto
http://www.imagehosting.cz/…s/bugsis.jpg
Už se s tim ser* skoro hodinu a ne a ne to fungovat u jinych formulářu mi to fungovalo normálně když jsem přidal např:

{form registraceForm}
       {control $form errors}
       {$form->render('errors')}
           {/form}

ale u tohoto když to přidam takhle mimo mi to udělá mezi tim selectem a buttonem nesmyslnou mezeru velkou asi na výšku 300 px.. viz. http://www.imagehosting.cz/…znzvu4ko.jpg V čem je chyba? Díky

Editoval t0x1c (22. 5. 2013 21:00)

Filip Procházka
Moderator | 4668
+
0
-

To vypadá, že se tam někde špatně uzavírá nějaký div.

Btw, není tohle {control $form errors} zbytečné?

t0x1c
Člen | 151
+
0
-

Jj je :D Ale neřeší to můj problem :P

Filip Procházka
Moderator | 4668
+
0
-

Nechceš se v tom zkusit porejpat a zjistit kde se ti blbě uzavírají ty tagy? :)

Co vyrenderuje tohle?

-----
<div style="width: auto;height: auto;margin-left: auto;margin-right: auto">
-----
{form serverForm}
-----
{$form->render('errors')}
-----
{$form->render('controls')}
-----
{$form->render('buttons')}
-----
{/form}
-----
</div>
-----
n.u.r.v.
Člen | 485
+
0
-

Ahoj, stáhl jsem si twitter bootstrap a celou jeho složku (bootstrap) jsem dal do složky „projekt/www/“.

A teď jsem tu pročítal toto vlákno a mám v tom pěkný guláš – prosím o radu, jak používat/vykreslovat bootstrap formuláře? Kam co musím zaregistrovat/napsat, případně co ještě stáhnout?

např. můj přihlašovací formulář v SignPresenter.php:

protected function createComponentSignInForm() {
        $form = new Form();
        //$form->setAction('pages/login.php');
        $form->setMethod('POST');
        $form->addText('email', 'E-mail:')
                ->setRequired('Zadejte prosím Váš e-mail!')
                ->setAttribute('name', 'username')
                ->addRule(Form::EMAIL, "Vložený e-mail je ve špatném formátu!");
        $form->addPassword('password', 'Heslo:')
                ->setRequired('Vyplňte heslo')
                ->setAttribute('onkeyup', 'passwordStrength(this.value);')
                ->setAttribute('id', 'pass')
                ->setAttribute('name', 'password');
        $form->addSubmit('send', 'Přihlásit!');
        $form->onSuccess[] = $this->signInFormSubmitted;


        return $form; // vykreslí formulář

a latte in.latte:

{var $robots = noindex}

{block #content}

<h1 n:block=title>Administrace - příhlášení</h1>

{control signInForm}

Chápu dobře, že stačí do config.neon umístit toto (to se mi zdá nějak moc jednoduché):

extensions:
    twBootstrapRenderer: Kdyby\BootstrapFormRenderer\DI\RendererExtension

Moc děkuji za radu…

enumag
Člen | 2118
+
0
-

@n.u.r.v.dokumentaci jsi četl?

Btw. tohle funguje myslím jen ve 2.1:

extensions:
    twBootstrapRenderer: Kdyby\BootstrapFormRenderer\DI\RendererExtension

Editoval enumag (19. 6. 2013 12:44)

n.u.r.v.
Člen | 485
+
0
-

Ahá, takže až takto jednoduše…už to asi funguje…Takže stačilo stáhnout z github ten boostraprenderer a nakopírovat složku kdyby do libs…díky