Jednoduchý counter v Nette s využitím AJAXu, ajax.nette.js

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

Ahoj,
vedel by mi niekto poradiť čo robím zle? Napríklad v príklade nižšie chcem vytvoriť obyčajný counter, ktorý po kliknutí inkrementuje hodnotu. Na začiatku ho nastavím na 0. Problémom ale je, že metóda createComponentMySimpleComponent() sa vykoná pri každom kliknutí a teda counter sa vždy vynuluje. Potom sa counter inkrementuje na 1 a tak má counter hodnotu 1 po každom kliknutí, čo je samozrejme zle. Prikladám kód:

súbor HomepagePresenter.php:

class HomepagePresenter extends BasePresenter {

    /** @var Components\IMySimpleComponentFactory @inject */
    public $mySimpleComponentFactory;

	public function renderDefault() {
        // empty
	}

	protected function createComponentMySimpleComponent() {
        return $this->mySimpleComponentFactory->create();
    }

}

súbor MySimpleComponent.php:

class MySimpleComponent extends UI\Control {

    private $counter;

    public function __construct() {
        parent::__construct();
        Debugger::fireLog('MySimpleComponent constructor');
        $this->counter = 0;
    }

    public function render() {

        $this->template->counter = $this->counter;
        $this->template->render(__DIR__ . '/mySimpleComponent.latte');
    }

    public function handleClick() {
        $this->counter++;
        $this->redrawControl('counter');
    }

}

interface IMySimpleComponentFactory {
    /**
     * @return MySimpleComponent
     */
    function create();

}

súbor mySimpleComponent.latte:

<p>
    <a class="myLink" n:href="click!">Refresh!:</a>
    <strong>Counter:</strong> {snippet}{$counter}{/snippet}
</p>
David Matějka
Moderator | 6445
+
+2
-
  1. Mezi jednotlivymi pozadavky se v php/nette aplikaci neprenaseji ty promenne (v tomhle pripade $counter). To se v nette necha vyresit pomoci persistentnich parametru, takze z counter udelej public property a pridej anotaci @persistent. Hodnota toho counteru se pak bude drzet v URL.
  2. tim snippetem musis mit obaleny i ten odkaz, jelikoz nyni by stale odkazoval na ten inicialni stav (kde je counter 0)

mrkni se na tenhle example, kde se resi neco podobneho

schnappi
Člen | 13
+
0
-

Ďakujem, už to funguje!

Čo ale, ak by som chcel mať zajaxovaný iný element ako <a>, napr. div alebo select? V tom prípade si musím pridať udalosť onClick daného elementu a poslať AJAX request, napr.:

<p>
    {snippet counter}
    <a class="ajax myLink" n:href="click!">Click!</a>
    <div class="myDiv" style="width: 2em; height: 2em; background-color: red; cursor: pointer"></div>
    <strong>Counter:</strong> {$counter}
    {/snippet}
</p>

<script type="text/javascript">

        $(".myDiv").off('click').on('click', function () {

            $.nette.ajax({
                type: 'GET',
                url: {link Click!},
                data: {
                    'mySimpleComponent-value' : 'someValue',
                }
            });
        });

</script>

Ak to takto upravím tak mi to znova nefunguje. Po prvom kliknutí sa counter inkrementuje, ale potom to už nereaguje na kliknutie. Čo mi zase uniká? Súvisí to nejak s tými metódami loadState a saveState? Pretože im veľmi nerozumiem.

Editoval schnappi (14. 2. 2017 19:58)

schnappi
Člen | 13
+
0
-

Tak nakoniec som to vyriešil tak, že v handleri komponenty prekresľujem aj javascript. To mi ale nepríde veľmi korektné. Neexistuje iné riešenie?

CZechBoY
Člen | 3608
+
+1
-

Zkus dát ten .myDiv ven ze snippetu.

<p>
    <div class="myDiv" style="width: 2em; height: 2em; background-color: red; cursor: pointer"></div>
    {snippet counter}
    <a class="ajax myLink" n:href="click!">Click!</a>
    <strong>Counter:</strong> {$counter}
    {/snippet}
</p>

<script type="text/javascript">

        $(".myDiv").off('click').on('click', function () {

            $.nette.ajax({
                type: 'GET',
                url: {link Click!},
                data: {
                    'mySimpleComponent-value' : 'someValue',
                }
            });
        });

</script>

Případně selector nastavit na document a potom hledat .myDiv.

<p>
    {snippet counter}
    <a class="ajax myLink" n:href="click!">Click!</a>
    <div class="myDiv" style="width: 2em; height: 2em; background-color: red; cursor: pointer"></div>
    <strong>Counter:</strong> {$counter}
    {/snippet}
</p>

<script type="text/javascript">

        $(document).on('click', '.myDiv', function () {

            $.nette.ajax({
                type: 'GET',
                url: {link Click!},
                data: {
                    'mySimpleComponent-value' : 'someValue',
                }
            });
        });

</script>

Problém je totiž že nabinduješ událost při onload/onready a potom ten element zmizí a objeví se znova, ale už samozřejmě bez nabindování události (to bys musel znova bindovat po překreslení snippetu).