AJAX – překreslení komponenty
- MartinVolenec
- Člen | 36
Dobrý den,
píšu si komponentu, která drží údaje o písničce. Je třeba, aby byla
viditelná až po kliknutí na odkaz.
Když uživatel klikne, nahrají se data z databáze a poté chci pomocí AJAXU
vykreslit.
Komponenta:
<?php
namespace App\Components;
use Nette\Application\UI\Control;
use Nette\Database\Connection;
class MusicPlayer extends Control {
/** @var Connection */
private $database;
/** Link to music file */
private $odkaz;
/** Name of song */
private $jmenoPisne;
/** Text of song */
private $text;
public function __construct(Connection $database) {
parent::__construct();
$this->database = $database;
}
private function setSongFromDatabase($songId) {
$song = $this->database->query('SELECT * FROM texty2 WHERE id = ?;', $songId)->fetch();
$this->odkaz = $song->link;
$this->jmenoPisne = $song->jmenoPisne;
$this->text = $song->text;
}
public function render() {
$template = $this->createTemplate();
$template->setFile(__DIR__ . '/musicPlayer.latte');
$template->odkaz = $this->odkaz;
$template->jmenoPisne = $this->jmenoPisne;
$template->text = $this->text;
$template->render();
}
public function handleShowSong($songId) {
$this->setSongFromDatabase($songId);
$this->redrawControl();
}
}
?>
Presenter:
<?php
namespace App\Presenters;
use Nette\Application\Responses\FileResponse;
use Nette\Database\Connection;
class MusicPresenter extends BasePresenter {
/** @var Connection */
protected $database;
/** @var App\Components\MusicPlayer */
private $musicPlayer;
public function __construct(Connection $database) {
parent::__construct();
$this->database = $database;
$this->musicPlayer = new \App\Components\MusicPlayer($database);
}
public function renderDefault() {
$sql = 'SELECT * FROM texty2 WHERE album_id = ?;';
$this->template->album1 = $this->database->query($sql, 1);
$sql = 'SELECT * FROM texty2 WHERE album_id = ?;';
$this->template->album2 = $this->database->query($sql, 2);
}
public function handleClick($songId) {
$this->musicPlayer->handleShowSong($songId);
}
protected function createComponentMusicPlayer() {
return $this->musicPlayer;
}
}
?>
Latte sablony komponenty:
<div id="txtHint" class="container text-center">
{snippet musicPlayerContent}
<p>{$text|noescape}</p>
<div class="item audio-mrg">
<audio id="beep-one" controls="controls" preload="auto">
<source src='{$basePath}/media/kazdej-je-rad-mezi-svymi/{$odkaz|noescape}.mp3'>
</audio>
</div>
{/snippet}
</div>
V šabloně příslušného presenteru je komponenta vložena pomocí
{control musicPlayer}.
Odkaz, který spustí AJAX:
<li><a n:href="click! $song->id" class="ajax">{$song->jmenoPisne}</a></li>
Pokud třídu ajax vymažu, vše funguje jak má, avšak bez AJAXU a
načítá se celá stránka.
Avšak s třídou ajax se data z DB načtou a nastaví, nicméně se nic
nevykreslí.
Děkuji za pomoc.
- Zuben45
- Člen | 268
zkusil bych:
public function handleClick($songId)
{
$this->musicPlayer->handleShowSong($songId);
$this['musicPlayer']->redrawControl(); // redraw component
}
protected function createComponentMusicPlayer()
{
$musicPlayer = $this->musicPlayer;
$musicPlayer->redrawControl();
return $musicPlayer;
}
Editoval Zuben45 (29. 6. 2017 8:41)
- MartinVolenec
- Člen | 36
Tak děkuji Zuben45, tento kód funguje:
<?php
public function handleClick($songId)
{
$this->musicPlayer->handleShowSong($songId);
$this['musicPlayer']->redrawControl(); // redraw component
}
?>
Avšak mohl bych se zeptat proč ? V té komponentě MusicPlayer volám
v hangleShowSong($id) metodu $this->redrawControl().
Jde mi o to, že už jsem nějaký komponenty, které pracují s AJAXem
napsal, právě způsobem, který jsem uvedl jako první a najednou ten postup
nefunguje.
Edit:
Ještě mě napadlo, dole v pravo Debugger/Laděnka ? ukazuje počet dotazů do
databáze, tak při AJAXovým požadavku jsou tam i ty dotazy, který by tam
být neměli. To znamená při načtení stránky si v renderDefault() beru
z databáze 2 alba. A při AJAXovém by měl být dotaz pouze na konkrétní
písničku. Avšak mi to ukazuje i dotazy na ty 2 alba (při AJAXovém).
Je to tak dobře? Takhle mi přijde, že se načítá celá stránka zbytečně, i když AJAXově.
Editoval MartinVolenec (29. 6. 2017 9:56)
- Zuben45
- Člen | 268
MartinVolenec napsal(a):
Tak děkuji Zuben45, tento kód funguje:
<?php public function handleClick($songId) { $this->musicPlayer->handleShowSong($songId); $this['musicPlayer']->redrawControl(); // redraw component } ?>
Avšak mohl bych se zeptat proč ? V té komponentě MusicPlayer volám v hangleShowSong($id) metodu $this->redrawControl().
Jde mi o to, že už jsem nějaký komponenty, které pracují s AJAXem napsal, právě způsobem, který jsem uvedl jako první a najednou ten postup nefunguje.Každopádně děkuji velice za pomoc.
Handle metodu bych ručně nevolal. Jelikož se vytvoří nová / clone instance ;) (aspon myslím, nezkoumal jsem to až tak podrobně nikdy) snad to někdo zde lépe vysvětlí.