vnořené snippety – špatná invalidace snippetů

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

Ahoj,

mám nette verze 2.0.3.

Potřebuji použít vnořené snippety.
Pokud používám samotné snippety bez vnořených, tak všechno funguje správně.
Pokud však vnořím snippety, tak mi to začne invalidovat úplně jiné věci, než které invaliduji přes invalidate control.

Kód

{snippet discussionSnippet}
    {form discussionForm class => ajax}
        <div>{input text}</div>
        <div>{input publish}{label publish /}{input submit}</div>
    {/form}

    {if $myDiscussionPosts != FALSE}
        {? $i = 0}
        {foreach $myDiscussionPosts as $post}
            <div>
                <p>{$post['text']}</p>
                <span>
                    <a n:href="commentPost! $post['id']" class="ajax">
                        {_"DISCUSSION_ADD_YOUR_COMMENT"}
                    </a>
                </span>
                <span>
                    <a n:href="ratePost! $post['id'], -1" class="ajax">-1</a>
                    {$post['rating']}
                    <a n:href="ratePost! $post['id'], 1" class="ajax">+1</a>
                </span>
                <span>{$post['created_on']}</span>

                {snippet postComment$i}
                        {ifset $showComment[$i]}
                            <div>
                            {form commentForm class => ajax}
                                {input postId}
                                <div>{input comment}</div>
                                <div>{input submit}</div>
                            {/form}
                             </div>
                        {/ifset}
                {/snippet}
             </div>
             {? $i++}
        {/foreach}
    {/if}
{/snippet}
    $this->template->showComment = array();
    $this->template->showComment[$i] = TRUE;
    $this->invalidateControl('discussionSnippet'.$i);
}

public function handleRatePost($postId, $value) {
        ...
        $this->invalidateControl('discussionSnippet');
}

Pokud odstraním vložený snippet, tak se správně volá snippet discussionSnippet. Jakmile se vloží vnořené snippety, začne to místo hlavního snippetu invalidovat jen vnořené. A pokud chci invalidovat vložený, tak se neinvaliduje vůbec nic. Konzele hlásí jen {„state“:[]}.

Editoval tttpapi (22. 8. 2012 10:28)

Vojtěch Dobeš
Gold Partner | 1316
+
0
-

To je korektní chování (myslím) dynamických snippetů. Je třeba invalidovat jak konkrétní, tak ten obalující. Podrobnější čtení např.: https://doc.nette.org/…mic-snippets

tttpapi
Člen | 100
+
0
-

Díky moc. Teď to dává už smysl. Jen jsem to nikde nemohl najít.

tttpapi
Člen | 100
+
0
-

Tak jsem to předělal na komponenty.
A stále se mi hodnocení příspěvku neinvaliduje. Změna se provede, vše v databázi je. Když stránku refreshnu, tak se změny objeví.
Konzole však vrací stále prázný {„state“:[]}.

protected function createComponentShowPosts() {
    $translator = $this->translator;
    $uniModel = $this->uniModel;
    return new Nette\Application\UI\Multiplier(function ($id) use ($translator, $uniModel) {
        return new DiscussionPost($translator, $id, $uniModel);
    });
}

A komponenta pro hodnocení
latte

<div>{$post['text']}</div>
<div>
   {snippet}
      <a n:href="ratePost! $post['id'], -1" class="ajax">-1</a>
      {$post['rating']}
      <a n:href="ratePost! $post['id'], 1" class="ajax">+1</a>
    {/snippet}
    <span>{$post['created_on']}</span>
 </div>

php

public function handleRatePost($postId, $value) {
    $this->ratePost($postId, $value);
    $this->invalidateControl();
}
Vojtěch Dobeš
Gold Partner | 1316
+
0
-

Hm, this is weird. Nechceš někam nahrát nebo poslat celé soubory? Tohle by to dělat nemělo.

Voláš v konstruktoru parent?

Editoval vojtech.dobes (17. 8. 2012 0:15)

natrim
Člen | 73
+
0
-

pokud je ten handleRatePost v presenteru tak musis invalidovat snippety komponenty a ne snippety presenteru

<?php
$this['showPosts']->invalidateControl();
?>
tttpapi
Člen | 100
+
0
-

Tady je kód.
vytvoření diskuze

use Nette\Application\UI;

class Discussion extends UI\Control {
    private $translator;
    private $uniModel;
    private $presenter;
    private $profileId;
    private $commentedPostId;
    private $posts;

    public function __construct($translator, UniversalModel $universalModel,
            $presenter, $profileId) {
        parent::__construct();
        $this->translator = $translator;
        $this->presenter = $presenter;
        $this->uniModel = $universalModel;
        $this->profileId = $profileId;
        $this->posts = $this->getMyDiscussionPosts();
    }

    public function render() {
        $this->template->setFile(__DIR__ . '/Discussion.latte');
        $this->template->setTranslator($this->translator);
        $this->template->discussionPosts = $this->getMyDiscussionPosts();
        $this->template->commentedPostId = $this->commentedPostId;
        $this->template->render();
    }

    private function discussionForm() {
	...
    }

    public function discissionFormSubmitted($form) {
	...
        $form->setValues(array(), TRUE);
        $this->invalidateControl('discussionSnippet');
    }

    public function createComponentDiscussionForm() {
        return $this->discussionForm();
    }

    public function getMyDiscussionPosts() {
	...
        return $discusionPosts;  // vrací pole s příspevkama
    }

    protected function createComponentShowPosts() {
        $translator = $this->translator;
        $uniModel = $this->uniModel;
        return new Nette\Application\UI\Multiplier(function ($id) use ($translator, $uniModel) {
            return new DiscussionPost($translator, $id, $uniModel);
        });
    }
}

latte diskuze

{block content}
<h1>Diskuze</h1>
{snippet discussionSnippet}
    {form discussionForm class => ajax}
        <div>{input text}</div>
        <div>{input publish}{label publish /}{input submit}</div>
    {/form}

    {foreach $discussionPosts as $post}
        {control "showPosts-".$post['id']}
    {/foreach}
{/snippet}
{/block}

Hodnocení příspěvku

use Nette\Application\UI;

class DiscussionPost extends UI\Control {
    private $translator;
    private $postId;
    private $uniModel;
    private $post;

    public function __construct($translator, $postId, UniversalModel $universalModel) {
        parent::__construct();
        $this->translator = $translator;
        $this->postId = $postId;
        $this->uniModel = $universalModel;
        $this->post = $this->getPost($postId);
    }

    public function render() {
        $this->template->setFile(__DIR__ . '/DiscussionPost.latte');
        $this->template->setTranslator($this->translator);
        $this->template->post = $this->post;
        $this->template->render();
    }

    public function handleRatePost($postId, $value) {
        $this->ratePost($postId, $value);
        $this->invalidateControl();
    }

    private function ratePost($postId, $value) {
       ... uložení do db
    }

    public function getPost($id) {
        ... načtení příspěvku z db se změněným hodnocením
    }
}

latte

{snippet}
    <div>{$post['text']}</div>
    <div>
        <a n:href="ratePost! $post['id'], -1" class="ajax">-1</a>
        {$post['rating']}
        <a n:href="ratePost! $post['id'], 1" class="ajax">+1</a>

        <span>{$post['created_on']}</span>
    </div>
{/snippet}
Vojtěch Dobeš
Gold Partner | 1316
+
0
-

Zatím odpověď neznám, pokusím se to vyzkoušet, jen dotaz: proč si tam předáváš presenter v konstruktoru? Každý UI\Control má presenter vždy dostupn.

tttpapi
Člen | 100
+
0
-

vojtech.dobes napsal(a):

Zatím odpověď neznám, pokusím se to vyzkoušet, jen dotaz: proč si tam předáváš presenter v konstruktoru? Každý UI\Control má presenter vždy dostupn.

S nette začínám a nevěděl jsem to. Jiný důvod v tom není.

tttpapi
Člen | 100
+
0
-

Chtěl jsem se zeptat, jestli už se přišlo na důvod, proč se snippety neinvalidují?