Prekreslenie komponenty ajaxom

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

Zdravím, robím nejaké pokusy s quickstartom. Snažím sa z komentárov a formuláru na pridanie komentáru spraviť komponentu. V podstate som to zvládol, či tým naj spôsobom to nvm, ale funguje. Problém je len v tom že sa mi komponenta nedarí prekresliť ajaxom, fórum som prešiel ale nenašiel som takýto problém. Vie mi niekto poradiť čo robím zle?

používam jQuery JavaScript Library v2.1.0 a AJAX Nette Framework plugin for jQuery

firefox konzola – sieť mi hodí HTTP/1.1 500 Internal Server Error

komponenta – CommentsControl.php

namespace App;
use Nette;

class CommentsControl extends Nette\Application\UI\Control
{
	private $database;

	public function __construct(Nette\Database\Context $database)
	{
		parent::__construct();
		$this->database = $database;
	}

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

	protected function createComponentCommentForm()
	{
		$form = new Nette\Application\UI\Form;
		$form->addText('name', 'Meno:');
		....
		$form->onSuccess[] = $this->commentFormSucceeded;
		$form->addSubmit('send', 'Pridať komentár');
		$form->getElementPrototype()->class('form-horizontal ajax');
		return $form;
	}

	public function commentFormSucceeded(Nette\Application\UI\Form $form)
	{
		$values = $form->getValues();
		$postId = $this->presenter->getParameter('postId');
		$this->database->table('comments')->insert(array(
			'post_id' => $postId,
			'name' => $values->name,
			'email' => $values->email,
			'content' => $values->content,
		));
		// po odoslani formu prebehne zápis do db no k prekresleniu ajaxom už nedojde
		$this->flashMessage('Ďakujeme za komentár', 'alert-success');
		if (!$this->presenter->isAjax())
			$this->presenter->redirect('this');
		else {
			$form->setValues(array(), TRUE);
			// skúšal som už aj $this->presenter->redrawControl(); a nič ..neviem čo iné skúsiť
			$this->redrawControl();
		}
	}
}
šablóna - CommentsControl.latte
{snippet comments}


<div class="comments">
	<h2>Komentáre k článku:</h2>
	<div n:if="count($comments) == '0'">Článok zatiaľ nik nekomentoval</div>
	{foreach $comments as $comment}
		<div class="comment">
			<div class="comment-header">
				<a n:href="commentDelete! $comment->id" n:if="$user->loggedIn" class="pull-right ajax"><span class="glyphicon glyphicon-remove"></span></a>
				<b><a href="mailto:{$comment->email}" n:tag-if="$comment->email">{$comment->name}</a></b>
				<small> {$comment->created_at|date:'d. m. Y H:i:s'}</small>
			</div>
			<div class="comment-content">{$comment->content}</div>
		</div>
	{sep}<div class="separator"></div>{/sep}
	{/foreach}
</div>

<div class="addcomment">
	<h2>Pridajte komentár</h2>
	{control commentForm}
</div>

{/snippet}
presenter - PostPresenter.php
	/**
	 * @return CommentsControl
	 */
	protected function createComponentComments()
	{
		$comments = new CommentsControl($this->database);
		$comments->template->comments = $this->comments;
		$comments->template->user = $this->user;
		return $comments;
	}
mkoubik
Člen | 728
+
0
-

A samotný ajax na klientu ti funguje (odešle se ajax request)? Co ti ti nette vrátí za response (koukni do chrome dev tools nebo něčeho podobného)?

Matey
Člen | 142
+
0
-

ajax funguje, kým som to mal všetko cez prezenter tak to bolo ok, formulár sa odoslal ajaxom, došlo k prekresleniu komentárov a vykresleniu flashmessage

keď som to skúsil prerobiť na komponentu tak to nejak zlyháva

toto mi hodil chrome dev tools

POST http://nette21/post/show?… 500 (Internal Server Error) jquery.js:8556
send jquery.js:8556
jQuery.extend.ajax jquery.js:8084
ajax nette.ajax.js:222
inner.requestHandler nette.ajax.js:48
jQuery.event.dispatch jquery.js:4371
elemData.handle

Etch
Člen | 403
+
0
-

Zakomentuj si ten redirect v té submit metodě:

if (!$this->presenter->isAjax())
    //$this->presenter->redirect('this');
else {
    $form->setValues(array(), TRUE);
    // skúšal som už aj $this->presenter->redrawControl(); a nič ..neviem čo iné skúsiť
    $this->redrawControl();
}

a pak přistup k té metodě bez ajaxu.

Nejjednodušeji prostě klikni na odeslat a ve firebugu pak klikni na ten POST požadavek, který neprojde a dej otevřít v novém okně. Pak by se ti měla vyhodit normálně Tracy, kde by si již měl vidět co způsobuje tu 500.

Pokud ti to ten komentář normálně uloží do databáze a chyba se vyskytuje jen při použití ajaxu, tak logicky musí být chyba někde na těchto řádcích:

$form->setValues(array(), TRUE);
$this->redrawControl();

Pokud to neajaxově proběhne normálně, tak tyhle dva řádky dej mimo tu podmínku o ajaxu a znova k té metodě přistup klasicky neajaxově.

Editoval Etch (13. 2. 2014 13:51)

Matey
Člen | 142
+
0
-

tak som sa cez ten firebug dostal k Tracy

Nette\InvalidArgumentException

Invalid argument passed to foreach resp. Nette\Iterators\CachingIterator; array or Traversable expected, NULL given.

problém s template->render()

18:        public function render()
19:        {
20:            $template = $this->template;
21:            $template->setFile(__DIR__ . '/CommentsControl.latte');
22:            $template->render();  //tu sa to zasekne
23:        }

žeby bol problém PostPresenteru? lebo tam získavam $comments v renderShow() a v createComponentComments() predám $comments do šablóny komponenty

private $comments;

public function renderShow($postId)
{
	$post = $this->database->table('posts')->get($postId);
	if (!$post) {
		$this->error('Stránka nebola nájdená');
	}
	$this->template->post = $post;
	$this->comments = $post->related('comment')->order('created_at');
}

/**
 * @return CommentsControl
 */
protected function createComponentComments()
{
	$comments = new CommentsControl($this->database);
	$comments->template->comments = $this->comments;
	$comments->template->user = $this->user;
	return $comments;
}

idem to skúsiť prerobiť, aby si priamo komponenta načítavala komentáre, tak ako to mám teraz je to asi fakt zle :)

edit:

tak predsa.. pomôhlo mi keď som naplnil premennú $comments až v komponente

//CommentsControl.php
public function render()
{
	$template = $this->template;
	$template->setFile(__DIR__ . '/CommentsControl.latte');
	$template->comments = $this->database->table('comments')->where('post_id', $this->postId)->order('created_at');
	$template->render();
}

a tiež bolo potrebné zmeniť renderShow() na actionShow() v PostPresenter

ďakujem za pomoc

Editoval Matey (13. 2. 2014 17:23)