Komponenta pro vkládání a zobrazení komentářů

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

Ahoj,
chtěl bych vytvořit komponentu, která mi zobrazí jednoduchou diskusi (resp. komentáře) pod každým článkem. Chci ji ale používat i jinde než jen u článků, např. u fotky v galerii.
Potřeboval bych aby zobrazila výpis komentářů a jednoduchý formulář pro vložení komentáře pokud je uživatel přihlášen.

Momentálně mám tento presenter pro zobrazení detailu článku

<?php
class ArticlePresenter extends BasePresenter
{
    /** @var \Components\Comments @inject */
    public $commentsFactory;

    private $article;

    function __construct(Model\ArticleModel $article){
        $this->article = $article;
    }

    public function renderDetail($key = ''){
        $article = $this->article->getByKlic($key);
        if (!$article) {
                $this->error();
        }
        $this->template->article = $article;
    }

    function createComponentComments(){
        $comments = $this->commentsFactory;
        return $comments;
    }

}
?>

Toto mám v šabloně pro detail článku

<?php
	{control comments $article->id, TRUE}
?>

A takhle mám nadefinovánu komponentu

<?php
namespace Components;

class Comments extends Control
{
    private $db;

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

    function createForm(){
        $form = new UI\Form;
        $form->addTextArea('content', 'Text:')
            ->setRequired();
        $form->onSuccess[] = $this->addFormSucceeded;
        $form->addSubmit('send', 'Odeslat');
        return $form;
    }

    function addFormSucceeded($form){
        $vals = $form->getValues();
        //.....................
    }

    function getItems($id){
        return $this->db->table('diskusePolozka')->where('mainId', $idRodic);
    }

    public function render($id, $showForm){
        $this->template->polozky = $this->getItems($id);
        $this->template->form = $this->createForm();
        $this->template->setFile(__DIR__ . '/comments.latte');
        $this->template->render();
    }
}
?>

Nevím ale jak zpracovat odeslaný formulář v komponentě. V šabloně článku, kam komponentu vkládám chci jen odkázat na komponentu a předat Id článku, ke kterému komentáře náleží a chtěl bych v komponentě data z formuláře uložit do DB. Nejlépe ajaxově, ale může být i normálně.
Používám nette 2.2-dev.
Za každou radu díky. Jsem Nettista začátečník, tak prosím o schovívavost :)
Lukáš

Editoval konva (22. 1. 2014 19:14)

David Matějka
Moderator | 6445
+
0
-

nejdriv par poznamek:

  1. vyhni se posilani parametru do komponenty v sablone (to {control comments $article->id, true}), to true pro (ne)zobrazeni formu je jeste ok, ale posilat id timhle zpusobem muze byt pozde
  2. komponentu si (nikdy) neregistruj jako sluzbu, jen si na ni vytvor tovarnicku
  3. pro form si vytvor sub komponentu v te komponente s komentarema

a kod:

namespace Components;

class Comments extends Control
{
    private $db;

    private $id;

    public function __construct($id, \Nette\Database\Context $db){
//        parent::__construct(); v komponentach neni nutno volat rodice
        $this->db = $db;
        $this->id = $id;
    }

    function createComponentForm(){ //createComponent, aby to byla klasicka komponenta
        $form = new UI\Form;
        $form->addTextArea('content', 'Text:')
            ->setRequired();
        $form->onSuccess[] = $this->addFormSucceeded;
        $form->addSubmit('send', 'Odeslat');
        return $form;
    }

    function addFormSucceeded($form){
        $vals = $form->getValues();
        //.....................
    }

    protected function getItems($id){
        return $this->db->table('diskusePolozka')->where('mainId', $idRodic);
    }

    public function render($showForm = TRUE){
        $this->template->showForm = $showForm;
        $this->template->polozky = $this->getItems($this->id);
        $this->template->setFile(__DIR__ . '/comments.latte');
        $this->template->render();
    }
}

smazal jsem to posilani formu do sablony, tam pouzij jen

{control form}

pripadne makro {form}

pak si vytvor tovarnicku

namespace Components;

interface CommentsFactory
{
	/**
	* @return Comments
	*/
	public function create($id);
}

tu registrujes v neonu (do sekce services)

services:
	-
		implement: Components\CommentsFactory
		class: Components\Comments
		arguments: [%id%]
		parameters: [id]

a v presenteru

class ArticlePresenter extends BasePresenter
{
    /** @var \Components\CommentsFactory @inject */
    public $commentsFactory;

    private $article;

    function __construct(Model\ArticleModel $article){
        $this->article = $article;
    }

    public function renderDetail($key = ''){
        $article = $this->article->getByKlic($key);
        if (!$article) {
                $this->error();
        }
        $this->template->article = $article;
    }

    function createComponentComments(){
        $comments = $this->commentsFactory->create($this->getParameter('key');

        return $comments;
    }

}

a v sablone uz bez id

{control comments}

Editoval matej21 (22. 1. 2014 19:23)

konva
Člen | 88
+
0
-

Díky za supr rychlou odpověď. Ještě mám dvě otázečky.
V tom

<?php
$this->getParameter('key');
?>

si predavam „slug“ (textovy klic ke clanku)

Pro zobrazeni komentaru ale potrebuji ID clanku. Rikal jsem si, ze si teda v prezenteru vytvorim lokalni promenou a v metode renderDetail ji naplnim (viz. nize), ale pri odeslani formulare se asi renderDetail nezpousti protoze mi to vrati komentare ke vsem clankum … Jak to nejlepe vyresit?

<?php
public function renderDetail($klic = ''){
        $clanek = $this->clanek->getByKlic($klic);
	......
        $this->idClanek = $clanek->ckId;
}

function createComponentComments(){
        $comments = $this->commentsFactory->create($this->idClanek);
        return $comments;
    }
?>

Mohl bych si to ID zjistit z toho klice pri dotazu do databaze na ty prispevky, ale prijde mi to zbytecne kdyz to ID muzu ziskat z detailu clanku.

A ještě jedna asi blbá otázka …
Jaký je rozdíl v neonu mezi „arguments“ a „parameters“?

Díky za odpověď
Lukáš

konva
Člen | 88
+
0
-

Tak pokud se nepletu, tak k te promenne se nedostanu, protoze se pri odeslani formulare zpracovava signal, ktery je v zivotnim cyklu pred „render“. Spravne bych si tedy to ID mel ziskat ve „startup()“? Je to tak?

David Matějka
Moderator | 6445
+
0
-

aha, ze je tam slug jsem si nevsiml.. ve startupu ne, startup je spolecny pro vsechny akce, pokud by jich bylo vice. spravne bys to mel nacitat v actionDetail metode, cely kod muze pak vypadat treba takhle:

class ArticlePresenter extends BasePresenter
{
    /** @var \Components\CommentsFactory @inject */
    public $commentsFactory;

    private $articleModel; //prejmenoval jsem to, at se to rozpozna od article samotneho

    private $article;

    function __construct(Model\ArticleModel $article){
        $this->articleModel = $article;
    }

    public function actionDetail($key = '')
    {
        $this->article = $this->articleModel->getByKlic($key);
        if (!$this->article) {
                $this->error();
        }
    }

    public function renderDetail(){
        $this->template->article = $this->article;
    }

    function createComponentComments(){
        $comments = $this->commentsFactory->create($this->article->id);

        return $comments;
    }

}

nebo vlatne nemusis do create metody posilat jen id, ale klidne cely article, to uz je na tobe :)

Jaký je rozdíl v neonu mezi „arguments“ a „parameters“?

parametry jsou to, co posilas do create metody v presenteru, argumenty jsou to, co se potom posle do konstruktoru komponenty. v pripade tehle tovarnicek to vetsinou mapujes 1:1, v argumentech ale muze treba navic byt i nejaka zavislost (ktera neni autowired) apod.

Editoval matej21 (23. 1. 2014 13:22)

konva
Člen | 88
+
0
-

diky za odpověď. Stále si pročítám i dokumentaci a použít „action“ by mě nenapadlo i když to tam teď vidím. Tohle řešení je supr.
Díky
Lukáš

Pavel Macháň
Člen | 282
+
0
-

konva napsal(a):

diky za odpověď. Stále si pročítám i dokumentaci a použít „action“ by mě nenapadlo i když to tam teď vidím. Tohle řešení je supr.
Díky
Lukáš

Tedle schémátko životního cyklu presenteru si doporučuju někde vystavit :)

Editoval EIFEL (23. 1. 2014 14:25)

konva
Člen | 88
+
0
-

jojo, už jsem na něj dnes ráno narazil a mám ho tu pořát otevřené :) … už se tiskne