Nette\InvalidStateException, AJAX, komponenty a špatné využití snippetu?
- mere.gee
- Člen | 54
Zdravím, tímto dotazem navazuji na toto
vlákno.
Po kliknutí na řádek jisté tabulky volám handleDetails, ve které
vytvářím instanci komponenty NotesList.
public function handleDetails()
{
$idticket = $this->getParameter('idticket');
$notesTable = $this->db->formNotesTable($idticket);
$grid = $this->createGrid('notesg', $notesTable);
new NotesList($grid);
$this->invalidateControl('middle');
}
V NotesList vytvářím další komponentu:
class NotesList extends Nette\Application\UI\Control
{
protected $notesGrid;
public function __construct($grid)
{
parent::__construct();
$this->notesGrid = $grid;
$this->render();
}
public function render()
{
$this->template->setFile(__DIR__.'/NotesList.latte');
$this->template->render();
}
public function createComponentNotesTable()
{
$notes = $this->notesGrid;
$notes->addColumn('idnote', 'idnote');
//atd.
return $notes;
}
}
Tu chci zobrazit v NotesList.latte:
{block middle}
{control notesTable}
{/block}
To dělám proto, abych sem ještě něco mohl vložit.
Blok middle mám podmíněně includenutý v @layout.latte a obaleny
ve snippetu:
{snippet middle}{ifset #middle}{include #middle}{/ifset}{/snippet}
Nette ale přijde v logu se zvláštní zprávou: Component '' is not attached to Nette\Application\UI\Presenter. Takhle to vypadá.
Můj dotaz zní: co dělám špatně? Díky moc :)
P.S.: Jak by se dala jinak vykreslit komponenta podmíněně a AJAXem, až po kliknutí na řádek tabulky (volané jQuery)?
Editoval mere.gee (24. 7. 2013 10:09)
- jiri.pudil
- Nette Blogger | 1032
Podívej se, jakým způsobem inicializuješ NotesTable a jakým NotesList. Jeden z nich je správný, druhý je příčinou tvého problému. (hint)
- mere.gee
- Člen | 54
jiri.pudil napsal(a):
Podívej se, jakým způsobem inicializuješ NotesTable a jakým NotesList. Jeden z nich je správný, druhý je příčinou tvého problému. (hint)
Takhle to je správně?
public function handleDetails()
{
$this->idticket = $this->getParameter('idticket');
$this['notesList'];
$this->invalidateControl('middle');
}
public function createComponentNotesList() {
$notesTable = $this->db->formNotesTable($this->idticket);
$grid = $this->createGrid('notesg', $notesTable);
return new NotesList($grid);
}
- mere.gee
- Člen | 54
S touhle úpravou se to pořád chová stejně. Chybu to začne totiž hlásit až když se volá metoda render() té třídy NotesList a program se pokouší vykreslit příslušný template. Pak asi hledá nějakou bezejmenou komponentu (jakou?), která není „připojená“ na UI\Presenter – což nevím, co znamená. Všechno, co mě napadá, mě vede k tomu prohlásit, že chyba je někde v Nette, ale já pořádně nevím, jak nette funguje, proto se ptám odborníků :)
- mere.gee
- Člen | 54
matej21 napsal(a):
v NotesList nemuzes v konstruktoru volat hned render
A jak mám inicializovat to vykreslení? Ta createComponentNotesTable se zavolá, až když se při vykreslování narazí na {control notesTable}… Mám ty komponenty nějak připojit k presenteru pomocí monitorů , aby věděli, jaký presenter je vykresluje? Nejsem si jistý, že jim rozumím…
- David Matějka
- Moderator | 6445
pockej, rekni, co chces udelat.. cely je to tam nejaky divny a nemuze to fungovat (ten block z komponenty se ti do layoutu dostat nepovede)
- David Matějka
- Moderator | 6445
tak dej do presenteru:
public function handleDetails()
{
$this->idticket = $this->getParameter('idticket');
$this->showNotesList = TRUE;
$this->invalidateControl('middle');
}
public function createComponentNotesList() {
$notesTable = $this->db->formNotesTable($this->idticket);
$grid = $this->createGrid('notesg', $notesTable);
return new NotesList($grid);
}
a do sablony presenteru presun ten snippet z layoutu (nebo ho tam potrebujes?)
{snippet middle}
{default $showNotesList = FALSE}
{if $showNotesList}
{control notesList}
{/if}
{/snippet}
- mere.gee
- Člen | 54
To udělat nemůžu, ten handler volám takhle:
<script>
$('table#dashboard tbody tr').click(function(){
var idticket = $(this).children('td.grid-cell-idticket').text().replace(/\s/g, '');
$.ajax({
url: {link details!},
type: 'GET',
data: { 'idticket' : idticket }
});
});
</script>
Musel bych udělat něco jako: window.location.replace("{link details! … no a jak teď předat ten var idticket?
- David Matějka
- Moderator | 6445
koukni se do nejaky konzole v prohlizeci, na jakou url to posila pozadavek (v chrome F12 a zalozka network); nebo staci pridat k url parametry ?do=details&idticket=123456
kdyz na tu url pudes, tak se to bude chovat stejne, jen to nebude ajaxovy
- David Matějka
- Moderator | 6445
jo, jsem idiot, v handleDetails ma byt samozrejme
public function handleDetails()
{
$this->idticket = $this->getParameter('idticket');
$this->template->showNotesList = TRUE;
$this->invalidateControl('middle');
}
zapomnel jsem na template :)
- David Matějka
- Moderator | 6445
ne, ta tovarnicka musi byt v NotesList, jak vytvaris tu grid? v createGrid?
- mere.gee
- Člen | 54
notesTable JE ten grid
V NotesList.php:
public function createComponentNotesTable()
{
$notes = $this->notesGrid;
$notes->addColumn('idnote', 'idnote');
$notes->setPrimaryKey('idnote');
$notes->addColumn('note_type', 'Typ');
$notes->addColumn('note_subject', 'Předmět');
$notes->addColumn('note_worktime', 'Hodiny');
$notes->addColumn('note_state', 'Stav');
$notes->addColumn('note_priority', 'Priorita');
$notes->addColumn('note_delivery', 'Do', Grido\Components\Columns\Column::TYPE_DATE);
$notes->addColumn('note_created', 'Vytvořeno', Grido\Components\Columns\Column::TYPE_DATE);
return $notes;
}
A obsah NotesList.latte (zatím):
{control notesTable}
Editoval mere.gee (24. 7. 2013 16:20)
- mere.gee
- Člen | 54
Promiň, asi jsem tě špatně pochopil – createGrid je metody BasePresenteru, od kterýho dědí ten presenter, v kterém vytvářím NotesList
public function createComponentNotesList() {
$notesTable = $this->db->formNotesTable($this->idticket);
$grid = $this->createGrid('notesg', $notesTable); //Vytvoří instanci Grido\Grid
return new NotesList($grid);
}
- mere.gee
- Člen | 54
public function createGrid($name, $table)
{
$lang = new Grido\Translations\FileTranslator();
$lang->setLang('cs');
$grid = new Grido\Grid($this, $name);
$grid->setModel($table);
$grid->setTranslator($lang);
return $grid;
}
To by ale mělo být v pořádku, v dřívějších verzích toho programu to fungovalo…
- David Matějka
- Moderator | 6445
no to je spatne, protoze to pripojujes k presenteru pod jmenem notesg, musi
to byt pripojeno k te komponente pod nazvem notesTable.
standardne komponenty nevyzaduji okamzite pripojeni k presenteru, zkus tedy pri
instancovani Grid neposilat $this a $name, at si to nette udela samo
- mere.gee
- Člen | 54
Odezva už je v pořádku… Takže to bude tou invalidací…
default.latte:
{block content}
…
{snippet middle}
{default $showNotesList = FALSE}
{if $showNotesList}
{control notesList}
{/if}
{/snippet}
{/block}
DashboardPresenter.php:
public function handleDetails()
{
$this->idticket = $this->getParameter('idticket');
$this->template->showNotesList = TRUE;
$this->invalidateControl('middle');
}
public function createComponentNotesList() {
$lang = new Grido\Translations\FileTranslator();
$lang->setLang('cs');
$notesTable = $this->db->formNotesTable($this->idticket);
$grid = new Grido\Grid();
$grid->setModel($notesTable);
$grid->setTranslator($lang);
return new NotesList($grid);
}
A <script src=„{$basePath}/js/nette.ajax.js“></script> v layoutu… A ano, mám to až za ajaxem a je to inicializované v main.js… Co nesedí?
Editoval mere.gee (24. 7. 2013 17:49)
- mere.gee
- Člen | 54
Dobrá, už to funguje jak má! Jsem ti hrozně moc vděčný, Matěji… Chyba byla v tom, že jsem tady místo $.nette.ajax psal $.ajax…
<script>
$('table#dashboard tbody tr').click(function(){
var idticket = $(this).children('td.grid-cell-idticket').text().replace(/\s/g, '');
$.nette.ajax({
url: {link details!},
type: 'GET',
data: { 'idticket' : idticket }
});
});
</script>
Jaký je v tomhle případě rozdíl, když volám $.nette.ajax a $.ajax? Ve zpracování té odpovědi?
- Vojtěch Dobeš
- Gold Partner | 1316
$.ajax()
je prostá obyčejná metoda jQuery. Vytvoří ajaxový
požadavek. Její API je zde: http://api.jquery.com/jQuery.ajax/.
Metoda $.nette.ajax()
je metodou doplňku, a prakticky dělá to
samé, co výše zmíněná starší sestra, až na to, že do vytvořeného
requestu zahookuje všechny registrované extenze.
- mere.gee
- Člen | 54
vojtech.dobes napsal(a):
$.ajax()
je prostá obyčejná metoda jQuery. Vytvoří ajaxový požadavek. Její API je zde: http://api.jquery.com/jQuery.ajax/.Metoda
$.nette.ajax()
je metodou doplňku, a prakticky dělá to samé, co výše zmíněná starší sestra, až na to, že do vytvořeného requestu zahookuje všechny registrované extenze.
Ale já jsem žádné extenze neregistroval… Takže některé vytváří automaticky?