Problém persistentního parametru při zpracování formuláře
- Jarek92
- Člen | 91
Zdravím,
řeším následující problém. Mám výpis položek na stránce, které se
přidávají a mažou AJAXově (metodami handle…). Vše funguje v pořádku,
nicméně mám také implementované stránkování. Pokud chci přejít na
další stránku, obstará to metoda handleMore(), která zvýší aktuální
stránku o 1 a načte další data. Nicméně, pokud jsem např. na stránce
č. 3 a chci přidat novou položku, tak v metodě addBoardFormSucceded je
persistentní parametr nastaven na výchozí hodnotu (1).
BoardPresenter:
const BOARDS_PER_PAGE = 6;
public $paginator;
/** @var int @persistent */
public $page = 1;
public function addBoardFormSucceded(\Nette\Application\UI\Form $form, $values) {
$user = \Model\Entities\Services\UserService::loadFromSession($this->getUser());
if($values->boardId == 0) {
$newBoard = \Model\Entities\Services\BoardService::create($values, $user);
} else {
$newBoard = \Model\Entities\Services\BoardService::loadForUpdate($values->boardId, $values->content);
}
$this->boardFacade->save($newBoard);
if($this->isAjax()) {
if($values->boardId == 0) {
$form->setValues([], TRUE);
$this->redrawControl("addBoard");
} else {
$form->setValues(array("content" => $newBoard->content));
$this->template->edit = true;
$this->redrawControl("editBoard");
}
$this->setupPaginator();
$this->template->boards = $this->boardFacade->findAll($this->getLimit());
$this->redrawControl("boards");
$this->redrawControl("paginator");
} else {
$this->redirect("this");
}
}
public function getLimit() {
return $this->page * self::BOARDS_PER_PAGE;
}
public function setupPaginator() {
$this->paginator->setItemCount($this->boardFacade->getAllCount());
$this->paginator->setPage($this->page);
$this->template->paginator = $this->paginator;
}
public function handleMore() {
if ($this->isAjax()) {
$this->page += 1;
$this->paginator->setPage($this->page);
$this->template->boards = $this->boardFacade->findAll($this->getLimit());
$this->redrawControl("boards");
$this->redrawControl("paginator");
}
else {
$this->redirect("this");
}
}
V jiných metodách mám hodnotu proměnné page aktuální, proč ji nemám také v metodě addBoardFormSucceded?
- Tharos
- Člen | 1030
Budu asi trochu věštit (neposlal jsi úplně celý kód), ale třeba se trefím… :)
Hodnoty persistentních parametrů sice do URL adres přidává Nette automaticky, ale platí, že v URL adresách musí být explicitně přítomné. Jinak se skončí na defaultní hodnotě.
V tvém případě bych tedy zkontroloval, jaká URL je v
action
formuláře addBoardForm
ve vygenerované
šabloně. Tipuji, že v ní ten parametr page
chybí, a proto se
tam ztrácí stav, resetuje se na defaultní hodnotu.
A proč tam chybí? Jelikož pracuješ s AJAXem, můj soukromý tip je, že
ten formulář nemáš správně obalený snippetem (anebo ho neinvaliduješ),
takže se HTML reprezentace toho formuláře při stránkování nepřekresluje
a tím se nemění action
podle aktuální hodnoty
parametru page
. :)
Editoval Tharos (17. 10. 2016 1:29)
- Jarek92
- Člen | 91
Díky moc, pomohlo překreslování snippetu addBoardForm při stránkování (v metodě handleMore). Akorát když se nacházím na poslední stránce a přidám nový příspěvek, tak si po překreslení Paginator myslí, že ještě není na poslední stránce, ale po kliku na „další“ se už zobrazí „žádné další příspěvky“. Ale to bude zřejmě chyba v počítání Paginatoru.
- Jarek92
- Člen | 91
Tak nakonec vyřešeno, přikládám funkční kód, kdyby někdo řešil podobný problém. :)
Díky @Tharos.
BoardPresenter.php
class BoardPresenter extends BasePresenter {
const BOARDS_PER_PAGE = 6;
/** @var int @persistent */
public $page = 1;
private $boardFacade;
private $addBoardForm;
private $paginator;
public function injectBoardFacade(BoardFacade $boardFacade) {
$this->boardFacade = $boardFacade;
}
public function injectAddBoardForm(AddBoardForm $addBoardForm) {
$this->addBoardForm = $addBoardForm;
}
public function createComponentAddBoardForm() {
return $this->addBoardForm->create();
}
public function getLimit() {
return $this->page * self::BOARDS_PER_PAGE;
}
public function setupPaginator() {
if(!isset($this->paginator)) {
$this->paginator = new Paginator($this->boardFacade->getAllCount(), self::BOARDS_PER_PAGE);
$this->paginator->setPage($this->page);
} else {
$this->paginator->setItemCount($this->boardFacade->getAllCount());
}
$this->template->paginator = $this->paginator;
}
public function actionDefault() {
$this->setupPaginator();
try {
$this->template->boards = $this->boardFacade->findAll($this->getLimit());
} catch (EntitiesNotFoundException $ex) {
\Tracy\Debugger::log($ex);
$this->template->boards = null;
} finally {
$this->template->edit = false;
}
}
public function handleUpdate($boardId) {
try {
$board = $this->boardFacade->findOneById($boardId);
$this["addBoardForm"]->setDefaults(array("boardId" => $board->id, "content" => $board->content));
} catch (EntityNotFoundException $ex) {
\Tracy\Debugger::log($ex);
} finally {
if($this->isAjax()) {
$this->redrawControl("editBoard");
} else {
$this->redirect("this");
}
}
}
public function handleDelete($boardId) {
try {
$board = $this->boardFacade->findOneById($boardId);
if($this->user->id == $board->user->id) {
$this->boardFacade->delete($boardId);
$this->template->boards = $this->boardFacade->findAll($this->getLimit());
} else {
$this->flashMessage("K této akci nemáš oprávnění!", "alert-danger");
}
} catch (EntityNotFoundException $ex) {
\Tracy\Debugger::log($ex);
$this->flashMessage("Požadovaný příspěvek nebyl nalezen.", "alert-danger");
} catch (EntitiesNotFoundException $ex) {
\Tracy\Debugger::log($ex);
$this->template->boards = null;
} finally {
$this->setupPaginator();
if($this->isAjax()) {
$this->redrawControl("flashes");
$this->redrawControl("boards");
$this->redrawControl("paginator");
} else {
$this->redirect("this");
}
}
}
public function handleChangeProper($boardId) {
try {
$board = $this->boardFacade->findOneById($boardId);
if(($this->user->isAllowed("ImproperBoard")) && ($this->user->id == $board->user->id)) {
$board->changeProper();
$this->boardFacade->save($board);
$this->template->boards = $this->boardFacade->findAll($this->getLimit());
} else {
$this->flashMessage("K této akci nemáš oprávnění!", "alert-danger");
}
} catch (EntityNotFoundException $ex) {
\Tracy\Debugger::log($ex);
$this->flashMessage("Požadovaný příspěvek nebyl nalezen.", "alert-danger");
} catch (EntitiesNotFoundException $ex) {
\Tracy\Debugger::log($ex);
$this->template->boards = null;
} finally {
if($this->isAjax()) {
$this->redrawControl("flashes");
$this->redrawControl("boards");
} else {
$this->redirect("this");
}
}
}
public function handleMore() {
if ($this->isAjax()) {
$this->page += 1;
$this->paginator->setPage($this->page);
$this->template->boards = $this->boardFacade->findAll($this->getLimit());
$this->redrawControl("paginator");
$this->redrawControl("addBoard");
$this->redrawControl("boards");
}
else {
$this->redirect("this");
}
}
}
AddBoardForm.php
class AddBoardForm extends \Nette\Application\UI\Control {
private $boardFacade;
public function __construct(BoardFacade $boardFacade) {
parent::__construct();
$this->boardFacade = $boardFacade;
}
public function create() {
$form = new Form();
$form->setRenderer(new BootstrapVerticalRenderer());
$form->getElementPrototype()->class("ajax");
$form->addTextArea("content")
->setAttribute("rows", 5)
->setRequired("Zadej prosím text příspěvku.");
$form->addHidden("boardId", 0);
$form->addSubmit("submit");
$form->onSuccess[] = array($this, "addBoardFormSucceded");
return $form;
}
public function addBoardFormSucceded(Form $form, $values) {
$user = UserService::loadFromSession($form->getPresenter()->getUser());
if($values->boardId == 0) {
$newBoard = BoardService::create($values, $user);
} else {
$newBoard = BoardService::loadForUpdate($values->boardId, $values->content);
}
$this->boardFacade->save($newBoard);
if($form->getPresenter()->isAjax()) {
if($values->boardId == 0) {
$form->setValues([], TRUE);
$form->getPresenter()->redrawControl("addBoard");
} else {
$form->setValues(array("content" => $newBoard->content));
$form->getPresenter()->getTemplate()->edit = true;
$form->getPresenter()->redrawControl("editBoard");
}
$form->getPresenter()->setupPaginator();
$form->getPresenter()->getTemplate()->boards = $this->boardFacade->findAll($form->getPresenter()->getLimit());
$form->getPresenter()->redrawControl("boards");
$form->getPresenter()->redrawControl("paginator");
} else {
$form->getPresenter()->redirect("this");
}
}
}