AJAX – překreslení komponenty

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
MartinVolenec
Člen | 36
+
0
-

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
+
0
-

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)

CZechBoY
Člen | 3608
+
0
-

Muzes poslat jeste sablonu presenteru?

MartinVolenec
Člen | 36
+
0
-

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
+
0
-

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í.