Předávání parametrů mezi komponentami a zpracování přes AJAX

Danny
Člen | 146
+
0
-

Zdravím,
měl bych jednu otázku jak řešíte např situaci kdy máte 2 komponenty a potřebujete mezi nimi po zpracování formu ajaxem předávat informace a překreslovat jejich snippety.

Řeším situaci kdy mám například komponentu která řeší vytvoření nějakého záznamu a obsahuje selectbox s výběrem uživatele a další inputy, pak mám druhou komponentu která řeší vytváření uživatele, oboje komponenty jsou injectnute v jednom presenteru a použity v jedné šabloně. Oboje komponenty jsou vidět na stránce a potřebuji docílit toho že pokud vytvořím uživatele na té stránce tak rovnou obnovit snippet komponenty pro vytvoření záznamu a nasetovat do selectboxu toho nového uživatele a zároveň neovlivnit to co uživatel při tvorbě vyplnil(další inputy).

Je vhodné řešení to řešit přes session nebo nějak jinak?

Děkuji za informace :-)

Danny
Člen | 146
+
0
-

Zkusím to lépe specifikovat. Mám Presenter kde si injectuju 2 komponenty přidání záznamu a přidání klienta.

class SheetPresenter extends BasePresenter
{
	/** @var IAddCustomerComponent @inject */
	public $IAddCustomerComponent;
	/** @var IAddSheetComponent @inject */
	public $IAddSheetComponent;

	protected function createComponentCustomerComponent() {
		$component = $this->IAddCustomerComponent->create();
		$component->onSuccess[] = function($customer) {
			$this->customer = $customer;
		};

		return $component;
	}

	protected function createComponentSheetComponent() {
		$component = $this->IAddSheetComponent->create();
		if($this->customer instanceof Customer) {
			$component->setCustomer($this->customer);
		}
		return $component;
	}
}

Dostal jsem se do stavu kdy si pomocí eventů předám ze zpracování(vytvoření klienta) konkrétní entitu klienta a nasetuju si jí do SheetComponenty.

class AddSheetComponent extends BaseComponent {

	/** @var CustomerDao */
	private $customerDao;

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

	public function createComponentForm() {
		$form = $this->create();
		$form->addSelect('customer_id', 'klient', [vyber klientu]));

		$form->addText('name', 'Name');
		return $form;
	}

	public function setCustomer(Customer $customer) {
		$this['form']['customer_id']->setDefaultValue($customer->getId());
	}
}

interface IAddSheetComponent {
	/** @return AddSheetComponent */
	public function create();
}

Problém mi nastává v momentě kdy uživatel bude mít vyplněné něco v text inputu(name) a až poté začne vytvářet klienta, proces se provede ajaxem na pozadí a obnoví snippet, klient ID se načte do formu, ale všechny ostatní data zmizí protože se nijak nepřenaší a ta komponenta se vytváří znova. Je nějaká možnost jak to udělat aby se obnovil například pouze snippet uvnitř toho formuláře, tedy pouze customer_id ? Nějak nejsem schopný se dostat přes ten cyklus.

Děkuji

Editoval Danny (17. 12. 2019 12:16)

CZechBoY
Člen | 3608
+
0
-

V presenteru nevidím že bys volal redrawControl.
V AddSheetComponent nevidím event onSuccess.

ps. doporučuju továrny pojmenovávat se suffixem Factory (např. IAddCustomerComponentFactory)

Danny
Člen | 146
+
0
-

Dám to sem celé. AddSheetComponent vytváří nějaký záznam, ten onSuccess je u vytváření klienta abych tu vytvořenou entitu mohl přenést do SheetComponenty. Tedy

class AddCustomerComponent extends BaseComponent {

	public $onSuccess = [];

	public function createComponentForm() {
		$form = $this->create();
		// inputy ...
		$form->onSuccess[] = function (Form $form, \stdClass $values) {

				$customer = new Customer()
				$customer->setId(1);
				....
				// vytvoreni customera
				$this->onSuccess($customer); // volání callbacku

				// tady se snažím dělat redraw ale překresluji to pouze v presentru, protože nevím jak bych sáhnul do
druhé komponenty odtud
				if($this->getPresenter()->isAjax()) {
					$this->getPresenter()->redrawControl('sheet');
				}

				return $form;
		};
		return $form;
	}

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

interface IAddCustomerComponent {
	/** @return AddCustomerComponent */
	public function create();
}

šablona Sheet presentru

{block content}
		{snippet sheet}
        <div class="panel-body">
            {control sheetComponent}
        </div>
		{/snippet}

        <div class="panel-body">
            {control customerComponent}
        </div>
{/block}
Danny
Člen | 146
+
0
-

S tím pojmenováním máš pravdu to bych měl, upravím si to. V jakém momentě bych měl v presentru volat ten redrawControl?

CZechBoY
Člen | 3608
+
0
-

RedrawControl volej v momente kdy chces prekreslit snippet :-)) tzn. asi po odeslani formulare.

Danny
Člen | 146
+
0
-

Nevim jestli si úplně rozumíme, potřebuju po vytvoření klienta nasetovat ty informace do jiné komponenty (což mám) a zároveň potřebuju v té druhé komponentě obnovit snippet a zároveň zachovat data které tam jsou, respektive tedy refreshnout jenom jeden input.

Bude to vůbec fungovat? Protože ty informace o klientovi setuji při vytváření té komponenty, tudíž tam naopak nebudu zase moci dostat data ne?

Editoval Danny (17. 12. 2019 17:09)

Danny
Člen | 146
+
+1
-

Po pár dnech mi došlo že se snažím vymýšlet složitě něco co je poměrně jednoduché. Nakonec vyřešeno takhle

SheetPresenter.php

	protected function createComponentCustomerComponent() {
		$component = $this->IAddCustomerComponent->create();
		$component->onSuccess[] = function($customer) {
			if($customer instanceof Customer) {
				if($this->isAjax()) {
					/** @var AddSheetComponent $component */
					$component = $this['addSheetComponent'];
					$component->setCustomer($customer);
					$component->redrawControl();
				}
			}
		};
		return $component;
	}

	protected function createComponentAddSheetComponent() {
		$component = $this->IAddSheetComponent->create();
		return $component;
	}
CZechBoY
Člen | 3608
+
+1
-

Do toho onSuccess callbacku bych si dal typehint a potom už necheckoval jestli je teda ten parametr typehint.
Továrnu bych pojmenoval se suffixem Factory – tzn. IAddSheetComponentFactory a IAddCustomerComponentFactory.
A když na to dojde tak proč event pojmenovávat onSuccess když můžeš mít třeba onCustomerAdded.

Danny
Člen | 146
+
0
-

Díky moc za připomínky :-)