špatně generovaný název parametru v odkazu

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

Ahoj,

v latte šabloně komonenty UserControl mám následující link na akci presenteru UsersPresenter:

<a n:href="users:showDetails user_id => $user->id"> .... </a>

to vygeneruje tuto adresu:

http://localhost/Mop/users/?-user_id=1&do=showDetails

Když na takový odkaz kliknu, Nette zahlásí ‚Invalid parameter name '-user_id‘.

S PHP a Nette teprve začínám, ale přijde mi, že pomlčka před názvem parametru by tam neměla být.

Nahradil jsem řádek 916 v Nette\Application\UI\Presenter.php což problém vyřešilo:

- $prefix = $component->getUniqueId() . self::NAME_SEPARATOR;
+ $prefix = $component->getUniqueId();
+ if ($prefix != NULL) $prefix = $prefix . self::NAME_SEPARATOR;

Nevím, jestli je to ta správná oprava, nebo je vše v pořádku a já používám Nette špatně.

S pozdravem,
Saniel

Nette 2.0.5
PHP 5.3.10

Twista
Člen | 48
+
0
-

saniel napsal(a):

mel pro to mit v bootstrapu vytvorenou routu,napr.

$container->router[] = new Route('<presenter>/<action>[/<user_id>]', 'Homepage:default');

nebo, pokud mas defaultni routy, zkus zmenit parametr user_id na id,tedy

<a n:href=" users:showDetails id => $user->id"> .... </a>
saniel
Člen | 10
+
0
-

Dík za odpověď. Tvůj návrh můj problém řeší. Tedy do doby, kdy budu chtít předat nějaký parametr a nedávat ho do routy. Principielně si myslím, že by mělo fungovat předávání parametru i mimo routu.

Twista
Člen | 48
+
0
-

saniel napsal(a):

mas podle me chybu nekde v komponentne(zkus sem hodit kod komponenty),
pridavani parametru i bez routy funguje (jen to vypada blbe)

leninzprahy
Člen | 150
+
0
-

Název toho parametru je „<název komponenty>-<název parametru>“

Z toho co píšeš to skoro vypadá že ta komponenta nemá název, což je celkem divné…

Jak vypadá komponenta a jak jí připojuješ?

jiri.pudil
Nette Blogger | 1028
+
0
-

Nepomohlo by tohle?

<a href="{plink users:showDetails user_id => $user->id}"> .... </a>

Odkaz z komponenty totiž lze vést pouze na signál komponenty. V tomto případě na signál komponenty ‚users‘ (díky té části před dvojtečkou), která ale v tvé UserControl neexistuje – odtud prázdné místo před pomlčkou v parametru.

plink je makro, které vytvoření odkazu deleguje až na presenter.

Editoval jiri.pudil (22. 11. 2012 15:20)

saniel
Člen | 10
+
0
-

Zadne extra pripojovani neprovadim krome automatickeho volani createComponent…

Tohle je presenter na ktery se v sablone odkazuju.

class UsersPresenter extends BasePresenter
{
	/** @var UserControl */
	private $userComponent;

	protected function startup()
	{
		parent::startup();
	}

	public function renderDefault()
	{
		if (isset($this->userComponent)) $this->payload->response = $this->userComponent->getAjaxResponse();
	}

	public function handleShowDetails($user_id)
	{
		$this->invalidateControl('details-window');
	}

	public function handleEditUser($user_id)
	{
		$this->invalidateControl('edit-window');
	}

	public function createComponentUser()
	{
		if (array_key_exists('user_id', $this->params)) $user_id = $this->params['user_id'];
		else $user_id = NULL;

		if (isset($this->userComponent)) {
			$this->userComponent->setUserId($user_id);
		}
		else $this->userComponent = new UserControl(
				$this->context->userRepository,
				$this->context->userRoleRepository,
				$this->context->contactRepository,
				$user_id);
		return $this->userComponent;
	}

}

Sablona se renderuje v teto komponente (zamerne jsem smazal kod nekterych funkci abych vypis skratil):

class UserControl extends Nette\Application\UI\Control
{
	private $user_id;
	private $ajax_response;
	/** @var UserRepository */
	private $userRepo;
	/** @var UserRoleRepository */
	private $userRoleRepo;
	/** @var ContactRepository */
	private $contactRepo;

	/** @var boolean */
	private $noUserFormDefaults;

    public function __construct(
			UserRepository $a_userRepo,
			UserRoleRepository $a_userRoleRepo,
			ContactRepository $a_contactRepo,
			$a_user_id=NULL)
    {
        parent::__construct(); // vždy je potřeba volat rodičovský konstruktor
		$this->userRepo = $a_userRepo;
		$this->userRoleRepo = $a_userRoleRepo;
		$this->contactRepo = $a_contactRepo;
		$this->user_id = $a_user_id;
		$this->noUserFormDefaults = true;
    }

	public function setUserId($a_user_id)
	{
	}

	public function getAjaxResponse()
	{
	}

	public function render()
	{
		$this->template->render();
	}

	public function renderList()
	{
		$this->template->setFile(__DIR__ . '/user-list.latte');
		$this->template->users = $this->userRepo->getAll();
		$this->template->render();
	}

    public function renderDetails()
    {
		$this->template->setFile(__DIR__ . '/user-details.latte');

		if ($this->user_id != NULL)
		{
			$user = $this->userRepo->getById($this->user_id);
			$contacts = $this->contactRepo->getAllOfUser($user);
		}
		else
		{
			$user = new User;
			$contacts = array();
		}

		$this->template->user = $user;
		$this->template->contacts = $contacts;
		$this->template->render();
    }

	public function renderEdit()
	{
		if (isset($this->user_id))
		{
			$this->noUserFormDefaults = false;
			$this->template->setFile(__DIR__ . '/user-edit.latte');
			$this->template->render();
		}
	}

	public function createComponentUsers()
	{
		return new UsersPresenter();
	}

	protected function createComponentUserForm()
    	{
	}


    public function userFormSubmitted(Form $form)
    {
    }

}
jiri.pudil
Nette Blogger | 1028
+
0
-

A jak tak koukám, showDetails není akce, ale signál presenteru, tudíž:

<a href="{plink users:showDetails! user_id => $user->id}"> .... </a>
saniel
Člen | 10
+
0
-

ono kdyz UserComponent generuje odkaz na sebe

<a n:href="showDetails user_id => $user->id"> .... </a>

tak je nazev spravne parametru spravne:

http://localhost/Mop/users/?user-user_id=1&do=user-showDetails

BTW:
presenter se jmenuje UsersPresenter
a komponenta UserControl
Vzhledem k tomu ze Presenter a `Control se casto vynechava, tak je mnohdy rozdil jen v jednom s, takze to pak muze mast. Budu muset pro presenter vymyslet lepsi jmeno.

jiri.pudil
Nette Blogger | 1028
+
0
-

ono kdyz UserComponent generuje odkaz na sebe, tak je nazev parametru spravne

Jistěže. Jak jsem napsal výše, komponenty mohou generovat odkazy pouze na komponenty, nikoliv na presentery.

n:href = {link} – pokud to použiješ v komponentě, vytváří se odkaz na signál komponenty, případně subkomponenty (to je ta část před dvojtečkou – v UserControl se marně hledá subkomponenta, která se jmenuje „users“). Pokud chceš z komponenty vytvořit odkaz na presenter, musíš použít {plink}.

saniel
Člen | 10
+
0
-

no jo, plink to resi! Uz jsem ho zkoumal, ale asi jsem se do toho nejak zamotal, ze se mi to nepodarilo.

Diky!

saniel
Člen | 10
+
0
-

Dik za vysvetleni

saniel
Člen | 10
+
0
-

Takze tohle vlakno bych mel ted asi smazat, coz?

leninzprahy
Člen | 150
+
0
-

Nemazat, co když bude někdo řešit stejný problém…

saniel
Člen | 10
+
0
-

hmm, tak porad to nejede jak ma :-(

Tohle my vygeneruje stranku jen po ten odkaz. Odkaz a vse za nim uz chybi.

<a href="{plink users:showDetails! user_id => $user->id}"> .... </a>

Kdyz odstranim vykricnik tak se odkaz vygeneruje. V presenteru prejmenuju funkci handleShowDetails na actionShowDetails. Ta se po kliku na odkaz zavola, ale i kdyz v ni volam $this->invalidateControl(), tak se mi nevygeneruje odpoved, ale server odpovi 500.

Jsem z toho uplne jelen. :-(

saniel
Člen | 10
+
0
-

jeste dodam, ze

<a href="{plink users:showDetails user_id => $user->id}"> .... </a>

vygeneruje

http://localhost/Mop/users/show-details?user_id=1

Po kliknuti na odkaz se v presenteru UsersPresenter zavola actionShowDetails(), ale k handleShowDetails() uz nedojde.

hAssassin
Člen | 293
+
0
-

saniel > logicky, neboť signály lze volat jen z aktuální komponenty/presenteru. Resp. nelze volat signál z cizího presenteru. Mezi presentery můžeš přecházet pouze mezi pohledy/akcema. Přečti si v dokumentaci něco o životním cyklu presenteru a o routování. Jinak makro {plink} skutečně volá akci příslušného presenteru, ale do signálu už nevlezeš. Moc jsem ten kód z handleShowDetails nepřesuneš do actionShowDetails? To by mělo fungovat, ne?

saniel
Člen | 10
+
0
-

hAssassin napsal(a):

saniel > logicky, neboť signály lze volat jen z aktuální komponenty/presenteru. Resp. nelze volat signál z cizího presenteru. Mezi presentery můžeš přecházet pouze mezi pohledy/akcema. Přečti si v dokumentaci něco o životním cyklu presenteru a o routování. Jinak makro {plink} skutečně volá akci příslušného presenteru, ale do signálu už nevlezeš. Moc jsem ten kód z handleShowDetails nepřesuneš do actionShowDetails? To by mělo fungovat, ne?

Aha, chápu. Takže to že se snažím odkazovat na signál nadřazené, či úpně nesouvisející komponenty je mimo architekturu Nette. Z toho, co jsem si v dokumentaci přečetl jsem tohle nepochopil. Toš popřemýšlím jak svou aplikaci postavit jinak, v souladu s Nette.

Přesunout kód do actionShowDetails pro mě nefunguje, protože tam nemůžu invalidovat snippet.