Proč signál vedoucí do konkretní komponenty spustí všechny createComponent metody daného presenteru?

crassus
Backer | 75
+
0
-

Ahoj,

mám FrontPresenter.php ve kterém jsou createComponent metody, např.

  1. createComponentProductListingControl()
  2. createComponentSearchPopupControl()
  3. atd..

Proč signál, který spouští handle v searchPopupControl, musí zároveň volat metodu createComponentProductListingControl() ?

Dá se tomu nějak zabránit?

Editoval crassus (24. 12. 2018 23:52)

CZechBoY
Člen | 3608
+
0
-

Protoze tvoje komponenta je zanorena… Jak bys ji chtel vytvorit bez vytvoreni predku?

crassus
Backer | 75
+
0
-

Předek je pouze ten FrontPresenter. Takže mě při ajaxovém requestu opravdu stačí, ať se vyrobí jenom 1 komponenta, do které vede ten ajaxový request. Je zbytečné, aby se vytvářely všechny ostatní komponenty (tahali se data z db), když se pak stejně nepoužijou.

CZechBoY napsal(a):

Protoze tvoje komponenta je zanorena… Jak bys ji chtel vytvorit bez vytvoreni predku?

Badaboom
Člen | 33
+
0
-

Odpověď je ve tvém kódu, Nette ty komponenty samovolně nevytváří. Bez tvého kódu budeme všichni jen hádat.

crassus
Backer | 75
+
0
-

Okay tak tady je ten FrontPresenter.php. Proč se spouští createComponentProductListingControl() při ajaxovém requestu do handle metody v SearchPopupControl? Já při tom requestu vůbec ProductListingControl nepotřebuji.

FrontPresenter.php

<?php
namespace App\Presenters;

use App\Components\ProductListing\ProductListingControl;
use App\Components\ProductListing\IProductListingControlFactory;
use App\Components\SearchPopup\SearchPopupControl;
use App\Components\SearchPopup\ISearchPopupControlFactory;

final class FrontPresenter extends BasePresenter
{
    /** @var IProductListingControlFactory */
    private $productListingControlFactory;

    /** @var ISearchPopupControlFactory */
    private $searchPopupControlFactory;

    /**
     * @param IProductListingControlFactory $productListingControlFactory
     * @param ISearchPopupControlFactory $searchPopupControlFactory
     */
    public function __construct(IProductListingControlFactory $productListingControlFactory, ISearchPopupControlFactory $searchPopupControlFactory)
    {
        $this->productListingControlFactory = $productListingControlFactory;
        $this->searchPopupControlFactory = $searchPopupControlFactory;
    }

    /**
     * @return ProductListingControl
     */
    public function createComponentProductListingControl()
    {
        return $this
            ->productListingControlFactory
            ->create();
    }

    /**
     * @return SearchPopupControl
     */
    public function createComponentSearchPopupControl()
    {
        return $this
            ->searchPopupControlFactory
            ->create();
    }
}

Badaboom napsal(a):

Odpověď je ve tvém kódu, Nette ty komponenty samovolně nevytváří. Bez tvého kódu budeme všichni jen hádat.

Editoval crassus (25. 12. 2018 14:04)

Badaboom
Člen | 33
+
0
-

Nikde v tom kódu nevidím použití těch komponent, ale tak zkusím to :) Podle názvů budu předpokládat, že jsou to vykreslované komponenty. Takže někde v šabloně budeš mít

{control searchPopupControl}
{control productListingControl}

Když pošleš signál do SearchPopupControl, tak program nepřestane pracovat po vyhodnocení handle metody. Životní cyklus pokračuje dál, takže se vykreslí i ta šablona a proto se ti vytvoří i ProductListingControl, viz životní cyklus presenteru.

crassus
Backer | 75
+
0
-

Chápu, ale já v té handle metodě volám: $this->redrawControl(‚nejakySnippetVKomponenteSearchPopupControl‘). Proč se teda renderují šablony dalších komponent? Když překresluji jenom nějaký fragment html kódu searchPopup komponenty?

Badaboom napsal(a):

Nikde v tom kódu nevidím použití těch komponent, ale tak zkusím to :) Podle názvů budu předpokládat, že jsou to vykreslované komponenty. Takže někde v šabloně budeš mít

{control searchPopupControl}
{control productListingControl}

Když pošleš signál do SearchPopupControl, tak program nepřestane pracovat po vyhodnocení handle metody. Životní cyklus pokračuje dál, takže se vykreslí i ta šablona a proto se ti vytvoří i ProductListingControl, viz životní cyklus presenteru.

Badaboom
Člen | 33
+
0
-

Protože tím překreslením se životní cyklus presenteru neukončí. Nette neví, pokud mu to neřekneš, co se má v rámci toho requestu ještě stát. Ta handle metoda může třeba změnit nějaký state a na základě toho se má překreslit další komponenta. A další komponenty se vykreslí, protože prostě v rámci toho životního cyklu jsou vykreslovány.

Zkus na to nahlížet tak, jako by to nebyl ajax request, protože to na tom průchodu až tolik nemění. Pokud se ti komponenta vykreslí při běžném requestu, tak se ti vykreslí i při ajaxovém requestu (pokud to nemáš nějak ošetřené).


Kdybys opravdu chtěl, tak ten cyklus můžeš po vyhodnocení SearchPopupControl::handleFoo() stopnout, např.:

// SearchPopupControl:
use SmartObject;

public $onAjaxHandle = [];

public function handleFoo()
{
	if ($this->presenter->isAjax()) {
		$this->onAjaxHandle();
	}
}

// FrontPresenter:
public function createComponentSearchPopupControl()
{
	$control = $this->searchPopupControlFactory->create();
	$control->onAjaxHandle[] = function () {
		$this->terminate();
	};
	return $control;
}

Nebo můžeš chování upravit pomocí metody Presenter::isSignalReceiver() – pokud není komponenta příjemcem signálu, tak ji nevykreslovat.

Ale pokud k tomu nemáš opravdu zásadní důvod, tak bych to nedoporučoval – ochudíš se o to dobré a zanese to trochu wtf do případného debugování.

Editoval Badaboom (25. 12. 2018 14:44)

Badaboom
Člen | 33
+
0
-

Nemáš ty komponenty obalené nějakým dalším snippetem, který také překresluješ? Nesaháš na tu druhou komponentu v presenteru (nevím, jestli ta ukázka je kompletní presenter) ? Protože po tom redrawControl v komponentě opravdu nevidím moc jiných důvodů, aby se vytvářela ta druhá komponenta.

Editoval Badaboom (25. 12. 2018 16:05)

crassus
Backer | 75
+
0
-

Máš pravdu, mě se tam v některých situacích nevolala redrawControl(), proto se spouštěly další komponenty. Pro dané situace volám v handle metodě: $this->getPresenter()->terminate() a funguje to suprovně.

Díky moc :)

Badaboom napsal(a):

Nemáš ty komponenty obalené nějakým dalším snippetem, který také překresluješ? Nesaháš na tu druhou komponentu v presenteru (nevím, jestli ta ukázka je kompletní presenter) ? Protože po tom redrawControl v komponentě opravdu nevidím moc jiných důvodů, aby se vytvářela ta druhá komponenta.