Vlastni FormRenderer a stale sa pouziva DefaultFormRenderer
- steelbull
- Člen | 241
Šaman napsal(a):
Na tomto nic špatného není, jen ty závorky jsou zbytečné. Chyba bude jinde.
Novy objekt sa vytvori, ale ani funkcia init() sa nezavola :-(
<?php
/**
* This file is part of the Nextras community extensions of Nette Framework
*
* @license New BSD License
* @link https://github.com/nextras/forms
* @author Jan Skrasek
*/
namespace TestUI\Helpers;
use Nette\Forms\Rendering\DefaultFormRenderer;
use Nette\Forms\Controls;
use Nette\Forms\Form;
use Nette;
use Nette\Utils\Html;
/**
* FormRenderer for Bootstrap 3 framework.
* @author Jan Skrasek
* @author David Grudl
*/
class Bs3FormRenderer extends DefaultFormRenderer
{
/** @var Controls\Button */
public $primaryButton = NULL;
/** @var bool */
private $controlsInit = FALSE;
public function __construct()
{
$this->wrappers['controls']['container'] = NULL;
$this->wrappers['pair']['container'] = 'div class=form-group';
$this->wrappers['pair']['.error'] = 'has-error';
$this->wrappers['control']['container'] = 'div class=col-sm-9';
$this->wrappers['label']['container'] = 'div class="col-sm-3 control-label"';
$this->wrappers['control']['description'] = 'span class=help-block';
$this->wrappers['control']['errorcontainer'] = 'span class=help-block';
}
public function init() {
die();
}
public function renderBegin()
{die();
$this->controlsInit();
return parent::renderBegin();
}
public function renderEnd()
{die();
$this->controlsInit();
return parent::renderEnd();
}
public function renderBody()
{die();
$this->controlsInit();
return parent::renderBody();
}
public function renderControls($parent)
{die();
$this->controlsInit();
return parent::renderControls($parent);
}
public function renderPair(Nette\Forms\IControl $control)
{die();
$this->controlsInit();
return parent::renderPair($control);
}
public function renderPairMulti(array $controls)
{die();
$this->controlsInit();
return parent::renderPairMulti($controls);
}
public function renderLabel(Nette\Forms\IControl $control)
{die();
$this->controlsInit();
return parent::renderLabel($control);
}
public function renderControl(Nette\Forms\IControl $control)
{die();
$this->controlsInit();
return parent::renderControl($control);
}
private function controlsInit()
{die();
if ($this->controlsInit) {
return;
}
$this->controlsInit = TRUE;
$this->form->getElementPrototype()->addClass('form-horizontal');
foreach ($this->form->getControls() as $control) {
if ($control instanceof Controls\Button) {
$markAsPrimary = $control === $this->primaryButton || (!isset($this->primary) && empty($usedPrimary) && $control->parent instanceof Form);
if ($markAsPrimary) {
$class = 'btn btn-primary';
$usedPrimary = TRUE;
} else {
$class = 'btn btn-default';
}
$control->getControlPrototype()->addClass($class);
} elseif ($control instanceof Controls\TextBase || $control instanceof Controls\SelectBox || $control instanceof Controls\MultiSelectBox) {
$control->getControlPrototype()->addClass('form-control');
} elseif ($control instanceof Controls\Checkbox || $control instanceof Controls\CheckboxList || $control instanceof Controls\RadioList) {
if ($control->getSeparatorPrototype()->getName() !== NULL) {
$control->getSeparatorPrototype()->setName('div')->addClass($control->getControlPrototype()->type);
} else {
$control->getItemLabelPrototype()->addClass($control->getControlPrototype()->type . '-inline');
}
}
}
}
}
- steelbull
- Člen | 241
Jj, ukazkove, toto mam spravne. Poslem cely control… Vybral som nejaky z kratsich formularov.
<?php
use Nette\Application\UI,
Nette\Forms\Form,
App\Model;
class BrandFormFactory extends UI\Control {
private $instance;
private $context;
private $translator;
/**
* Constructor
* @param instance $instance
* @param string $callback
* @param \Kdyby\Translation\Translator $translator
* @param \Nette\Database\Context $context
*/
function __construct($instance, \Kdyby\Translation\Translator $translator, \Nette\Database\Context $context) {
$this->instance = $instance;
$this->context = $context;
$this->translator = $translator;
}
/**
* Create form
*/
function createComponentForm() {
// Create new instance
$form = new UI\Form;
// Tu som nastavil Renderer a nic :-(
$form->setRenderer(new \AgileUI\Helpers\Bs3FormRenderer);
$form->method = 'post';
$form->getElementPrototype()->addAttributes(array('id' => 'BrandForm', 'class' => 'ajax'));
$form->addText('title', $this->translator->translate('brands.form.title'))
->setAttribute('class', 'form-control')
->setRequired($this->translator->translate('brands.form.please_insert_the_title'));
$form->addText('description', $this->translator->translate('brands.form.description'))
->setAttribute('class', 'form-control');
$form->addHidden('id');
$form->addProtection();
/*
Mimochodom, ako riesite Callbacky? Ked to mam takto, mam plny presenter callbackov, co nie je velmi cool
*/
$form->onSuccess[] = array($this->instance, 'BrandFormSuccess');
$form->onError[] = callback($this->instance, 'BrandFormError');
return $form;
}
/**
* Render
*/
function render() {
$template = $this->template;
$template->setFile(__DIR__ . '/templates/BrandFormFactory.latte');
$template->render();
}
}
/**
* Form interface
*/
interface IBrandFormFactory {
/**
* @return BrandFormFactory
*/
function create($instance);
}
- jiri.pudil
- Nette Blogger | 1032
Komponenta by neměla záviset na tom, že presenter implementuje nějaké konkrétní metody. Já mám zpracování formuláře přímo v té komponentě a stejně tak v ní mám vlastní událost, kterou právě při tom zpracování vyvolám, a obsluhu si na ni navěsím až v presenteru. Viz můj článek
- steelbull
- Člen | 241
jiri.pudil napsal(a):
Komponenta by neměla záviset na tom, že presenter implementuje nějaké konkrétní metody. Já mám zpracování formuláře přímo v té komponentě a stejně tak v ní mám vlastní událost, kterou právě při tom zpracování vyvolám, a obsluhu si na ni navěsím až v presenteru. Viz můj článek
Jj, velmi pekne dakujem za tento pohlad. Sam som nad nim rozmyslal a tiez sa mi nepaci, ze mam v presenteri mnozsto metod na osetrenie formulara. Ale uvazoval som nad tym, ze budem chciet formular pouzit niekolko krat ako standardny formular a niekolko krat ako jaxovy modal window. A v tychto pripadoch budem vzdy redirectovat niekam inam.
Aj ked na druhej strane, target, kam presmerovat by bolo efektnejsie osetrit asi setterom, ci? Napada Ta ine riesenie?
- steelbull
- Člen | 241
Lexi napsal(a):
Presun radek
$form->setRenderer(new \AgileUI\Helpers\Bs3FormRenderer);
Az nakonec toho jak mas nadefinovany formular, tesne nad
return $form;
nebo callbacky, pisni jestli ti to pomohmo.
Nepomohlo:
$form->onSuccess[] = array($this->instance, 'BrandFormSuccess');
$form->onError[] = callback($this->instance, 'BrandFormError');
// Set renderer
$form->setRenderer(new \AgileUI\Helpers\Bs3FormRenderer());
//Return rendered Form
return $form;
- steelbull
- Člen | 241
Lexi napsal(a):
Presun radek
$form->setRenderer(new \AgileUI\Helpers\Bs3FormRenderer);
Az nakonec toho jak mas nadefinovany formular, tesne nad
return $form;
nebo callbacky, pisni jestli ti to pomohmo.
A skusal som aj pred callbacky aj za a nejde. Potom som skusal callbacky dat prec, ale tiez nepomohlo.
Editoval steelbull (27. 6. 2015 19:24)
- steelbull
- Člen | 241
David Matějka napsal(a):
zeptam se znovu, jak ten formular vykreslujes v latte?
Vykreslujem ho takto:
{form form}
<div class="form-group col-md-6">
{label 'title' /}
{input 'title'}
<span class="form-error-message">{inputError 'title'}</span>
</div>
/*
.
.
.
.
*/
{/form}
Editoval steelbull (27. 6. 2015 19:05)
- Šaman
- Člen | 2666
steelbull napsal(a):
David Matějka napsal(a):
zeptam se znovu, jak ten formular vykreslujes v latte?
Vykreslujem ho takto:
{form form} {/form}
No, když ho vykresluješ ručně, tak se samozřejmě renderer neprojeví.
Můžeš ho nechat buď vykreslit rendererem {control fooForm}
,
nebo ručně pomocí latte makra {form}{/form}
. :D
- steelbull
- Člen | 241
:-( ano, ale DefaultRenderer sa stale pouziva. Preto ma ani nenapadlo, ze custom renderer nemozem pouzit. V tomto pripade potrebujem hromadne nastavit class pre vsetky napr. selectboxy a pouzit vlastny renderer vidim ako useful future. Bolo by to urcite lepsie, ako pri kazdej polozke formulara vzdy nastavovat setAttribute.
Šaman napsal(a):
steelbull napsal(a):
David Matějka napsal(a):
zeptam se znovu, jak ten formular vykreslujes v latte?
Vykreslujem ho takto:
{form form} {/form}
No, když ho vykresluješ ručně, tak se samozřejmě renderer neprojeví. Můžeš ho nechat buď vykreslit rendererem
{control fooForm}
, nebo ručně pomocí latte makra{form}{/form}
. :D
- Šaman
- Člen | 2666
Zkus to rozchodit na ukázkovém formuláři na čistém sandboxu (nebo spiš
web-project
u) a pošli odkaz na zdrojáky. Někde máš zakopanou
chybu. A bude se špatně hledat, když nám ukazuješ zdrojáky po kouskách.
Chyb tam teda máš víc, třeba komponenta není továrna, ale to jsou věci
související s čitelností, ne s funkčností.
A jinak nehledáš teda spíš tohle?
- steelbull
- Člen | 241
Prave ze mam ako tovarnicku, Interface som neposielal. Obsahuje jednu metodu Create a Commenty v spravnom tvare. Komponentu mam zaregistrovanu v config neon a injectnutu do presentera. Vsetko funguje, len set Renderer nie. Zavesim zdrojak na GIThub.
Este budem mat asi viac otazok na formulare, ale zavesim do samostatnych vlakien.
- Šaman
- Člen | 2666
Já mluvil o tomhle class BrandFormFactory extends UI\Control
.
Tohle není továrna, je to komponenta – potomek Control
(která
obsahuje továrničku na formulář, ale to už je interní věc té
komponenty).
Jinak na tu otázku kam psát obsluhu událostí formuláře, tak do té komponenty.
Ale není problém si udělat opravdu jen továrnu na formulář (bez
komponenty) a obsluhu
mít také v ní.
Ale těm navěšeným callbackům v presenteru se úplně nevyhneš, protože většinou až presenter umí zpracovat flashmessage a hlavně rozhodnout, kam přesměrovat. Nemluvím teď o triviálním přesměrování na ten samý formulář, ale třeba po registraci chci nejspíš zobrazit jinou stránku – detail nového uživatele, nebo třeba výzvu k potvrzení registrace odkazem v emailu apod. Já mám nejčastěji zpracování dat u formuláře, ale přesměrování a flashmessage navěšuji až v presenteru (nebo komponentě).
Editoval Šaman (28. 6. 2015 9:05)
- steelbull
- Člen | 241
…a vytvorit vlastne setteri a v presenteri v createComponent setSuccessFlasMessage() a setSuccessRedirectTarget() je bad practise?
Šaman napsal(a):
Já mluvil o tomhle
class BrandFormFactory extends UI\Control
. Tohle není továrna, je to komponenta – potomekControl
(která obsahuje továrničku na formulář, ale to už je interní věc té komponenty).Jinak na tu otázku kam psát obsluhu událostí formuláře, tak do té komponenty.
Ale není problém si udělat opravdu jen továrnu na formulář (bez komponenty) a obsluhu mít také v ní.Ale těm navěšeným callbackům v presenteru se úplně nevyhneš, protože většinou až presenter umí zpracovat flashmessage a hlavně rozhodnout, kam přesměrovat. Nemluvím teď o triviálním přesměrování na ten samý formulář, ale třeba po registraci chci nejspíš zobrazit jinou stránku – detail nového uživatele, nebo třeba výzvu k potvrzení registrace odkazem v emailu apod. Já mám nejčastěji zpracování dat u formuláře, ale přesměrování a flashmessage navěšuji až v presenteru (nebo komponentě).