š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 | 1032
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 | 1032
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
User
s
Presenter
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 | 1032
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 zhandleShowDetails
nepř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.