Zdvojené renderovanie FormControl

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

Mám problém so zdvojeným renderovaním vlastného FormControl. Prvý sa ukáže na svojom mieste a druhý (vrátane tabulky) na konci formu pred CSRF tokenom.

<?php
class GMapsControl extends NFormControl
{

    /** @var Html  container element template */
    protected $container;
    protected $gmapsdiv;

    protected $latId = null;
    protected $longId = null;
    protected $enableAddress = false;
    protected $mestomcastId = null;
    protected $streetId = null;
    protected $numberId = null;
    protected $homeLat = null;
    protected $homeLong = null;

    /**
    * @param  string  label
    */
    public function __construct($label = NULL)
    {
        parent::__construct($label);
        $this->gmapsdiv = NHtml::el('div');
        $this->gmapsdiv->class[] = 'gmaps';
        //$this->gmapsdiv->setText('bu');
        $this->container = NHtml::el();
    }

    public static function addGMapsControl(NForm $form, $name, $label)
    {
        return $form[$name]=new self($label);
    }

    protected function updateRel()
    {
        $this->gmapsdiv->rel = json_encode(array(
                                    'address' => $this->enableAddress,
                                    'latId' => $this->latId,
                                    'lngId' => $this->longId,
                                    'mestomcastId' => $this->mestomcastId,
                                    'streetId' => $this->streetId,
                                    'numberId' => $this->numberId,
                                    'homeLat' => $this->homeLat,
                                    'homeLng' => $this->homeLong,
                                ));
    }

    public function setAddress($bool)
    {
        $this->enableAddress = $bool;
    }
    public function setAddressElements($mestomcast, $street, $number)
    {
        $this->mestomcastId = $mestomcast;
        $this->streetId = $street;
        $this->numberId = $number;
        $this->enableAddress = true;
        $this->updateRel();
    }

    public function setCoordElements($lat, $long)
    {
        $this->latId = $lat;
        $this->longId = $long;
        $this->updateRel();
    }

    public function setHome($lat, $long)
    {
        $this->homeLat = $lat;
        $this->homeLong = $long;
        $this->updateRel();
    }

    public function getControl()
    {
        //dump('getcontrol');
        //dump(debug_backtrace());
        $container = clone $this->container;
        $container->add($this->gmapsdiv);

        return $container;
    }
?>
<?php
// BasePresenter
protected function startup()
{
    parent::startup();
    ...
    NFormContainer::extensionMethod('addGMapsControl', 'GMapsControl::addGMapsControl');
    ...
}
?>
<?php
// tvorba formu
$form->addGMapsControl('gmaps', 'Poloha:');
$form['gmaps']->setAddressElements($form['mestomcast']->getHtmlId(), $form['ulica']->getHtmlId(), $form['cislo']->getHtmlId());
$form['gmaps']->setCoordElements($form['lat']->getHtmlId(), $form['long']->getHtmlId());
$form['gmaps']->setHome(48.743, 19.313); // stred slovenska
?>

Control vloží <div class="gmaps"></div> na ktorý sa cez JS vložia mapy aj s ich obsluhou. getControl() sa zavolá 2×. PswdInput sa zobrazí normálne, čiže predpokladám chybu v mojom kóde. Používam najnovšie Nette 1.0 prefixed na PHP 5.3 (vývoj aplikácie začal na 5.2). Prosím o pomoc, ďakujem.

Ešte ma napadá… ako donútiť aby sa ‚rel‘ neescapovalo? Teraz to riešim v JS – vymením entity za úvodzovky.

Editoval OndroNR (4. 9. 2010 14:28)

westrem
Člen | 398
+
0
-

No jedine co sa mi v tvojom kode nepozdava je to klonovanie, mas na to nejaky explicitny dovod?

	$container = clone $this->container;
$container->add($this->gmapsdiv);

K tomu rel atributu, nepomoze obalit ho prazdnym Html::el() kontajnerom?

OndroNR
Člen | 8
+
0
-

klonovanie – prebral som to z addonu Captcha.. ked tam priamo dam $container = NHtml::el(); tak sa nič nezmení. Nepomôže ani priamo vrátiť control return $this->gmapsdiv;

rel – buď neviem ako to spraviť alebo to nepomôže

<?php
	// žiadna zmena, setText tiež nič nezmení
        $rel = NHtml::el();
        $rel->add(json_encode(array(
                                    'address' => $this->enableAddress,
                                    'latId' => $this->latId,
                                    'lngId' => $this->longId,
                                    'mestomcastId' => $this->mestomcastId,
                                    'streetId' => $this->streetId,
                                    'numberId' => $this->numberId,
                                    'homeLat' => $this->homeLat,
                                    'homeLng' => $this->homeLong,
                                )));
        $this->gmapsdiv->rel = $rel;
?>
westrem
Člen | 398
+
0
-

Uz ma napadlo kde mas chybu. Vid tento riadok Treba tomu controlu nastavit ze bol rendered, inak to Form nevie a preto este dodatocne vykresli na konci formulara pred CSRF.

K tomu neescapovanemu rel, tam som myslel setHtml, nie add ani setText, tie sa obe escapuju.

OndroNR
Člen | 8
+
0
-

Ďakujem, nastaviť rendered pomohlo :)

Ani setHtml nepomôže. Control sám escapuje aj data atribúty aj normálne atribúty :( a tú podivnú formu JSON čo robí nette-rules neprejde cez jQuery parser, ani validátor :( Už sa v tom strácam, teraz som zistil, že to funguje aj bez relstr.replace('&quot;', '"'); pričom v HTML zdrojáku je " a pri alert($(this).attr('rel')); to vypíše neescapované. Prevádza to jQuery naspäť na použiteľnú formu automaticky?

Matúš Matula
Člen | 257
+
0
-

Necital som to cele, ale k tomu escapovaniu ma napadlo, ci nemas prave na mysli nette feature context-sensitive escaping, pozri napr. do dokumentacie