špatně generovaný název parametru v odkazu

- saniel
- Člen | 10
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
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>

- leninzprahy
- Člen | 150
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 | 1034
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
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 | 1034
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
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 | 1034
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
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. :-(

- hAssassin
- Člen | 293
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
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 zhandleShowDetailsnepřesuneš doactionShowDetails? 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.