Předání závislostí (ne jenom ID) komponentě ze šablony

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

Potřeboval bych vyřěšit následující ilustrativní příklad:

  • Presenter ArticlePresenter zobrazuje výpis všech článků.
  • Máme vytvořenou komponentu Comments pro zobrazení formuláře pro vložení komentáře k článku.
  • U každého článku se zobrazí formulář.
  • Jak do komponenty dostat veškerá data článku? ID článku je jasný (následující kód), ale potřeboval bych komplet data $article.

Kód pouze ilustrační:

ArticlePresenter.php

public function renderDefault(){
	$articles = $this->articleModel->getArticles();
	$this->template->articles= $articles;
}

protected function createComponentComments(){
	return new Multiplier(function($id_article){
		$control = new Control\Comments($id_article);
		return $control;
	});
}

default.latte

{foreach $articles as $article}
	<h2>{$article->name}</h2>
	<p>{$article->perex}</p>
	{control comments-$article->id} // lze nějak předat i celý $article a ne jenom ID ???
	<hr>
{/foreach}

CommentsControl.php

/** @var int */
private $id_article;

public function __construct($id_article){
	parent::__construct();
	$this->id_article = $id_article;
}

Takže ID článku ($id_article) mám v komponentě, paráda. Lze ale do této komponenty dostat i celý obsah $article ze šablony? Abych v komponentě Comments měl k dispozici např. název článku $article->name a nemusel to v komponentě tahat přes articleModel (který bych tam musel samozřejmě vytvořit, nebo předat při vytváření komponenty v multiplieru).

Předem díky moc za nasměrování, opravdu jsem hledal a hledal a nazadařilo se mi.

Jiří Nápravník
Člen | 710
+
+2
-

Nějak takhle. Render zmen na action a uloz si to do privatni proměnné, musíš tam mít to pole tak, že klíč je id toho článku, pripadne si v tom multiplieru nejak jinak poresit jak vytahnes konkretni article pro to

ArticlePresenter.php

private $articles;
public function actionDefault(){
    $this->articles = $this->articleModel->getArticles();
    $this->template->articles= $this->articles;
}

protected function createComponentComments(){
    return new Multiplier(function($id_article){
        $control = new Control\Comments($this->articles[$id_article]);
        return $control;
    });
}

default.latte

{foreach $articles as $article}
    <h2>{$article->name}</h2>
    <p>{$article->perex}</p>
    {control comments-$article->id}
    <hr>
{/foreach}

CommentsControl.php

/** @var int */
private $article;

public function __construct($article){
    parent::__construct();
    $this->article = $article;
}

Editoval Jiří Nápravník (17. 2. 2016 17:38)

CZechBoY
Člen | 3608
+
0
-

Pouzivam presne to jako pise post nademnou.
S tim, ze v tovarnicce vyzaduju IRow a ten tam dostanu prave z pole hodnot $this->articles.

flamengo
Člen | 135
+
0
-

Super díky moc. Ještě jeden dotaz spíše k databázi a to jak dostat data v modelu do požadovaného pole.
Jě nějaký efektivnější způsob, jak dostat data z databáze do pole, kde klíč bude ID?

public function getArticles(){
	rows2 = FALSE;
	$rows = $this->database->query("SELECT ...")->fetchAll();
	if($rows){
		foreach($rows as $row){
			$rows2[$row->id] = $row;
		}
	}
	return $rows2;
}

Opět předem díky.

Pavel Macháň
Člen | 282
+
0
-

Jiří Nápravník napsal(a):

Nějak takhle. Render zmen na action a uloz si to do privatni proměnné, musíš tam mít to pole tak, že klíč je id toho článku, pripadne si v tom multiplieru nejak jinak poresit jak vytahnes konkretni article pro to

ArticlePresenter.php

private $articles;
public function actionDefault(){
    $this->articles = $this->articleModel->getArticles();
    $this->template->articles= $this->articles;
}

protected function createComponentComments(){
    return new Multiplier(function($id_article){
        $control = new Control\Comments($this->articles[$id_article]);
        return $control;
    });
}

default.latte

{foreach $articles as $article}
    <h2>{$article->name}</h2>
    <p>{$article->perex}</p>
    {control comments-$article->id}
    <hr>
{/foreach}

CommentsControl.php

/** @var int */
private $article;

public function __construct($article){
    parent::__construct();
    $this->article = $article;
}

ještě bych to rozdělil na action a render (je to detail ale když už tak už :) )

private $articles;

public function actionDefault(){
    $this->articles = $this->articleModel->getArticles();
}

public function renderDefault(){
    $this->template->articles= $this->articles;
}
David Matějka
Moderator | 6445
+
+3
-

myslim, ze

->query("..")->fetchPairs("id")
flamengo
Člen | 135
+
0
-

Díky všem, přesně takto to potřebuji :)

flamengo
Člen | 135
+
0
-

Tak nakonec mám ještě jeden dotaz :) V případě, že se jedná o komponentu, která pouze něco zobrazí, tak to takto stačí. Ale kdyby to byla komponenta, která zobrazí formulář pro přidání komentáře a formulář odešlu ajaxem, tak přijdu o data v $article. Jak z toho ven respektive jak i po odeslání formuláře ajaxem získám původní data článku?

CommentsControl.php

private $article;

public function __construct($article){
    parent::__construct();
    $this->article = $article;
}
CZechBoY
Člen | 3608
+
0
-

Pokud se o to má starat ta komponenta, kterou už máš, tak do ní přidej komponentu formuláře.

class CommentsControl
{
	private $article;
	private $commentsFormFactory;

	public function ($article, CommentsFormFactory $commentsFormFactory)
	{
		$this->article = $article;
		$this->commentsFormFactory = $commentsFormFactory;
	}

	protected function createComponentCommentsForm ()
	{
		$form = $this->commentsFormFactory->create();

		$form->onSuccess[] = function ($form, $values) {
			// zpracování formuláře
		};

		return $form;
	}
}
flamengo
Člen | 135
+
0
-

Celé jsem to trochu popletl, takže mů poslední dotaz ignorujte :)