vnořené komponenty a práce s parametry

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

Čau kluci,

chtěl bych se podělit s problémem, který u mě nastal při upgradu na Nette 2.0.10.

V presenteru vytvářim komponentu Jedna která obsahuje komponentu Druha
Presenter

public function createComponentJedna() {
	return $this->context->createJedna();
}

V komponentě Prvni mam tovarnicku na komponentu Druha

public function createComponentDruha() {
	return new \MyComponents\Druha();
}

Druha.php

public function handleAdd($id) {
	dump($id);
}

druha.latte

<a href="{link add! id => $sticker->id}">add</a>

vydím, že link se vytvoří správně: ?prvni-druha-id=54&do=prvni-druha-add. Handler se zavola ale proměnna $id je NULL. Ve verzi 2.0.6 mi toto všechno projde a proměnná se naplní správně. Dělám něco v zásadě špatně?

Majkl578
Moderator | 1364
+
0
-

Můžeš ukázat i kód komponent?

vojty
Člen | 19
+
0
-
<?php
namespace Chief\Components;

use \Nette\Utils\Html;
use \Chief\ORM\Facade;
use \Chief\Translator;

class FileBrowser extends \Nette\Application\UI\Control
{

    /** @var \Nette\Application\UI\Presenter $presenter */
    protected $presenter;

    /** @var Translator $translator */
    protected $translator;

    /** @var FileBoxSet */
    protected $fileBoxSet;

    /** @var Object $orm */
    protected $orm;


    /**
     * @param Translato $translator
     * @param Object $orm
     */
    function __construct($translator, $orm)
    {
        $this->translator = $translator;
        $this->orm = $orm;
        $this->monitor('\Nette\Application\UI\Presenter');
    }

    /**
	 * @param \Nette\Application\UI\Presenter $presenter
	 */
	protected function attached($presenter)
	{
		parent::attached($presenter);

        if ($presenter instanceof Presenter) {
            $this->presenter = $presenter;

            if ($presenter->isAjax()) {
                $this->invalidateControl();
            }
        }
    }

    /**
     * Render
     */
    public function render()
    {
        $template = $this->createTemplate();
        $template->count = $this->getFiles();
        $template->setTranslator($this->translator);
        $template->info = $this->orm->fileFacade->loadInfo();
        $template->setFile(dirname(__FILE__) . '/fileBrowser.latte');
        $template->render();
    }

    /**
     * Get files
     */
    protected function getFiles()
    {
        $paginator = $this['paginator']->getPaginator();
        $count = $this->orm->fileFacade->countByStickers($this['stickers']->getSelected());
        $paginator->itemCount = $count;
        $files = $this->orm->fileFacade->loadByStickers($this['stickers']->getSelected(), null, null, $paginator->itemsPerPage, $paginator->offset);
        $this['fileBoxSet']->SetFiles($files);

        return $count;
    }

    /**
     * @return VisualPaginator
     */
    public function createComponentPaginator() {
        $pg = new \VisualPaginator();
        $pg->paginator->itemsPerPage = 40;
        return $pg;
    }

    /**
     * @return FileBoxSet
     */
    public function createComponentFileBoxSet() {
        return $this->fileBoxSet;
    }

    /**
     * @return Stickers
     */
    public function createComponentStickers() {

        $s = new \Chief\Components\Stickers($this->translator);
        $s->setStickerTypes(array(1)); // set file sticker type
        $s->setDataSource($this->orm->stickerFacade);

        // set callback
        $browser = $this;
        $s->setMyCallback(function($selected) use ($browser) {
            $browser['paginator']->page = $browser['paginator']->paginator->page = 1;
        });

        return $s;
    }

    /**
     * @param FileBoxSet $fbs
     */
    public function setFileBoxSetComponent($fbs)
    {
        $this->fileBoxSet = $fbs;
    }

    /**
     * @return FileBoxSet
     */
    public function getFileBoxSetComponent()
    {
        return $this->fileBoxSet;
    }

}
namespace Chief\Components;

use \Nette\Application\UI\Presenter;
use \Nette\Utils\Html;

use \Chief\ORM\Facade;
use \Chief\Translator;

class Stickers extends \Nette\Application\UI\Control
{
	/** @persistent array */
    public $selected = array();

    /** @var Facade\StickerFacade $stickerFacade */
    protected $stickerFacade;

    /** @var Translator $translator */
    protected $translator;

    /** @var array $stickerTypes */
    protected $stickerTypes = array();

    /** @var array $stickers */
    protected $stickers;

    /** @var string $orderBy */
    protected $orderBy = null;

    /** @var calback $myCallback */
    protected $myCallback;

    /** @var string $stickerTemplate */
    protected $stickerTemplate = 'stickers.latte';

    /**
     * @param \VisualPaginator $paginator
     */
    function __construct(Translator $translator)
    {
        $this->monitor('\Nette\Application\UI\Presenter');
        $this->translator = $translator;
    }

    /**
     * @param Presenter $controler
     * @return type
     */
    protected function attached($controler)
    {
		parent::attached($controler);
		if(!$controler instanceof Presenter) return;

		if($controler->isAjax()) {
			$this->invalidateControl('stickers');
		}
    }

    public function render()
    {
        $template = $this->createTemplate();
        $template->setTranslator($this->translator);
        $template->stickers = $this->getStickers();
        $template->selected = $this->getSelected();
        $template->setFile(dirname(__FILE__) . '/' . $this->getStickerTemplate());
        $template->render();
    }

    /**
     * @param Facade\StickerFacade $source
     * @return Stickers
     */
    public function setDataSource(Facade\StickerFacade $source)
    {
        $this->stickerFacade = $source;
        return $this;
    }

    /**
     * @return Facade\StickerFacade
     */
    public function getDataSource()
    {
        return $this->stickerFacade;
    }

    /**
     * Get stickers
     * @return array
     */
    public function getStickers()
    {
        foreach($this->stickerTypes as $type) {
            $criteria['stickerType'] = $type;
        }
        return $this->stickerFacade->loadBy($criteria, $this->orderBy);
    }


    /**
     * Add sticker
     * @param int $id
     */
    public function handleAdd($id)
    {
        if (!in_array($id, $this->selected)) {
            $this->selected[$id] = $id;
        }
        if ($this->myCallback) $this->callSelectedCallback($this->selected);
    }

    /**
     * Remove sticker
     * @param int $id
     */
    public function handleRemove($id)
    {
        if (in_array($id, $this->selected)) {
            unset($this->selected[$id]);
            $this->template->selected = $this->selected;
        }

        if ($this->myCallback) $this->callSelectedCallback($this->selected);
    }

    /**
     * Callback
     * @param array $selected
     * @return callback
     */
	private function callSelectedCallback($selected)
	{
        if(is_callable($this->myCallback)){
            return call_user_func($this->myCallback, $selected);
        }
        return $this->myCallback;
	}

    /**
     * Set callback
     * @param type $callback
     */
    public function setMyCallback($callback)
    {
        $this->myCallback = $callback;
    }

    /**
     * Get sticker types
     * @return array
     */
    public function getStickerTypes()
    {
        return $this->stickerTypes;
    }

    /**
     * @param array $types
     * @return Stickers
     */
    public function setStickerTypes(array $types)
    {
        $this->stickerTypes = $types;
        return $this;
    }

    /**
     * Get selected
     * @return array
     */
    public function getSelected()
    {
        return $this->selected;
    }

    /**
     * @param array $selected
     * @return Stickers
     */
    public function setSelected(array $selected)
    {
        $this->selected = $selected;
        return $this;
    }

    public function getStickerTemplate() {
        return $this->stickerTemplate;
    }

    public function setStickerTemplate($stickerTemplate) {
        $this->stickerTemplate = $stickerTemplate;
    }

}
norbe
Backer | 405
+
0
-

Zkus nahradit $this->monitor('\Nette\Application\UI\Presenter') za parent::__construct()

Majkl578
Moderator | 1364
+
0
-

norbe napsal(a):

Zkus nahradit $this->monitor('\Nette\Application\UI\Presenter') za parent::__construct()

V 2.0.10 už není třeba volat rodičovský konstruktor. Nicméně ten monitor je špatně a nedává smysl nastavovat ho ručně. :)

vojty
Člen | 19
+
0
-

Díky, odstranil jsem rucni nastaveni monitoru a jede.

Tomáš Brchaň
Člen | 13
+
0
-

Ahoj všem, objevil jsem podobný problém, ovšem s formuláři.
Na základě https://blog.nette.org/…-and-pure-js jsem chtěl měnit jiný select box (vše ve vnořené komponentě). Nicméně mi to nebere hodnotu $value v handleru.

Když napíši:
<a href="{link companyChange! value => 3}">change</a>
vygeneruje se mi správně odkaz ?prvniKomponenta-druhaKomponenta-value=3&do=prvniKomponenta-druhaKomponenta-companyChange a vše funguje, jak má.

Ale select, resp. js z návodu vytvoří ?do=prvniKomponenta-druhaKomponenta-companyChange$value=3

A v tomto případě mi handleCompanyChange($value) vrátí $value = NULL.

Kde je chyba? Je to problém js kódu, Nette nebo prostě moje, že ten parametr musím tahat jinak?

Zatím jsem to vyřešil přes js, ale má někdo lepší nápad než tento?

<script>
	var link = '{link {$link}! value => "changeMe"}';
	link = link.replace("&amp;", "&");
	$('#{$control["barterParticipantForm"][$input]->htmlId}').on('change', function() {
		var value = $(this).val();
		var url = link.replace("changeMe", value);
		$.nette.ajax({
			type: 'GET',
			url: url
		});
	});
</script>

Editoval Tomáš Brchaň (31. 5. 2013 11:06)