Snippet / Multiplier / zachování modal okna

emololftw
Člen | 81
+
0
-

Dobrý den / Ahoj všem,

v latte šabloně mám snippet:

{snippet deviceList}
	{foreach $result->objects as $technologyId => $technologyRow}
		{control "inlineChart-" . bin2hex($technologyId)}
	{else}
		{control nothingHere}
	{/foreach}
{/snippet}

List je dynamicky vázaný na tabulku, takže je možné položku přidávat nebo odebírat. Vše funguje bezvadně, ale problém nastává, když mám v komponentě nějáký MODAL nebo DROPDOWN. Při každém překreslení listu se prvek zavře. Zkoušel jsem různé {if $presenter->isAjax()} apod. zkoušel jsem kód v komponenntě obalit snippetama, kromě zmiňovaného modalu/dropdownu a bez výsledku. Jak řešíte Vy prvek co nechcete překreslovat v multiplieru?

Děkuji

Edit:

Při každém překreslení v šabloně se v komponentě volá render() metoda. Bude pravděpodobně nutné vytvořit modal okno mimo komponentu?

Editoval emololftw (22. 10. 2021 15:20)

Polki
Člen | 553
+
0
-

No takto multiplier je ok i modal v komponentě je ok.

Vzhledem k tomu ale, jak fungují moderní modální okna spolu s JS, tak je dobrá praktika nepřekreslovat celý modal, ale jen jeho vnitřek. Pokud máš tedy modal uvnitř komponenty nothingHere, pak by si neměl překreslovat celou komponentu nothingHere, ale jen obsah jejího modalu. Pak ti modal zůstane otevřený a jen se změní jeho obsah.

emololftw
Člen | 81
+
0
-

Polki napsal(a):

No takto multiplier je ok i modal v komponentě je ok.

Vzhledem k tomu ale, jak fungují moderní modální okna spolu s JS, tak je dobrá praktika nepřekreslovat celý modal, ale jen jeho vnitřek. Pokud máš tedy modal uvnitř komponenty nothingHere, pak by si neměl překreslovat celou komponentu nothingHere, ale jen obsah jejího modalu. Pak ti modal zůstane otevřený a jen se změní jeho obsah.

Děkuji za odpověď. nothingHere komponenta jen zobrazí ilustraci, že zde nic není. V komponentě vykresluji pouze body modalu, ale pakliže ho má uživatel otevřené, další ajaxový požadavek na pozadí okno zavře. Chtěl bych ponechat okno otevřené, ať už přichází do komponenty jakýkoliv signál.

Polki
Člen | 553
+
0
-

Důležité je nepřekreslovat snippetem samotný modal. Jen jeho obsah :)

emololftw
Člen | 81
+
0
-

Polki napsal(a):

Důležité je nepřekreslovat snippetem samotný modal. Jen jeho obsah :)

Ano máte pravdu. V komponentě mám mnoho továrniček s repositories a modelu. V presenteru pouze volám komponentu se setterem. Každý řádek obsahuje právě zmíněný MODAL. Avšak při ve snippetu mám multiplier, takže se mi vždy přepíše celá render metoda komponenty a taktéž již zmiňovaný modal. Napadá mne vytvořit MODAL na úrovni presenteru, mimo snippet multiplieru a v komponentě volat: $this->getPresenter()['mainModal'] = $this->factory->create($this->rowId); ale nevím jak moc velký je to overkill. Protože když budu mít ajaxový formulář, půjde signál vždy do presenteru a né komponenty, kde mám veškerou spjatou logiku. Nebo je zde možnost v komponentě definovat blok např:` {block mainModalContent}` a tím přepisovat snippet MODAL mimo snippet multiplieru?

Děkuji.

EDIT: obsah snippetu je pouze modal content.

<div class="modal" id="showDowntimeModal-{$control->getName()}" data-bs-keyboard="false" tabindex="-1" aria-hidden="true">
	<div class="modal-dialog modal-md">
		<div class="modal-content">
			<div class="modal-header">
				<h5 class="modal-title">{_message.form.downtimesCard.title}</h5>
				<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
			</div>
			<div class="modal-body p-4 loading-ajax-part downtimes-timeline-comment" n:snippet="downtimeModal">
				<div n:snippet="flashMessages">
					<div n:foreach="$flashes as $flash" n:class="alert, 'alert-'.$flash->type, fade, show">
						{$flash->message}
						<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
					</div>
				</div>
				{control downtimeModal}
			</div>
		</div>
	</div>
</div>

Editoval emololftw (23. 10. 2021 11:43)

Polki
Člen | 553
+
0
-

Já nevidím komplet celou logiku za tím, takže nemůžu jednoznačně napsat, co máš kde volat.

Důležité je však vědět, že je úplně jedno, jestli máš multiplier, nebo ne. Komponenty se chovají pořád stejně.

Například pokud chceš překreslit snippet uvnitř komponenty komentáře, což je multiplier, a ty potřebuješ překreslit obsah toho jednoho konkrétního komentáře, tak se to dělá cca takto:

$this->getComponent('comments-11')->redrawControl('content');

Kde říkáš, že comments je multiplier a číslo 11 je v něm jedenáctá komponenta, nad kterou chceš překreslit jen ten její jeden snippet s názvem content.

Samozřejmě lépe se to dělá pomocí signálů směřujících přímo do té komponenty (metody formuláře), nebo pokud to potřebuješ z vnějšku, tak pomocí nějaké eventy, kterou si nadefinuješ v nějakém svém Event Managerovi.

emololftw
Člen | 81
+
0
-

Zkusím ještě otevřít toto téma. Řekl bych, že největší bottleneck jsou mé vyjadřovací schopnosti.

Mám v default.latte snippet:

{snippet rowsArea}
	{foreach $result->objects as $technologyId => $technologyRow}
		{control "inlineChart-" . bin2hex($technologyRow->getOperation())}
	{/foreach}
{/snippet}

tento proces volá Multiplier, kde se tvoří komponenty. Je to dynamický seznam, uživatel může kdykoliv odebrat položku nebo jí přidat. Na pozadí běží setInterval a každou minutu se ajaxově přepíše celý default.latte. Ale každá komponenta obsahuje MODAL okno. Jsou k tomu různé důvody, protože seznam je použitý i v jiných modulech webu. A tím, že se zavolá redraw na seznam, se automaticky přepíše i celý MODAL (zavolá se render metoda komponenty) a pokud má uživatel modal otevřený, automaticky se každou minutu zavře. Komponenta vypadá nějak takto:

<div class="modal">
	<div n:snippet=modalContent>
	</div>
</div>

<div class="row">
	<div n:snippet=header>
	</div>

	<div n:snippet=result>
	</div>

	<div class="dropdown">
	</div>
</div>

A já se právě snažil i přes snippetArea redrawnout pouze result a header. Vše mi fungovalo bez problému, dokud jsem nechtěl překreslovat celý seznam prvků kvůli jeho možnému dynamickému chování. Ideálně bych volal jak jste zmínil:

$this->getComponent('comments-11')->redrawControl('content');

ale seznam je dynamický a přepisovat foreachem možné komponenty tak redrawnu aktivní, ale odstraněné ze seznamu nezmizí.

Děkuji.

EDIT: ještě jsem zkoušel volat v komponentě signál na přepis snippetů v dynamické komponentě, ale kvůli volání komponenty ve foreach se vždy volá render metoda a je to zbytečné, pač se kompletně modal přepíše.

EDIT2:

pokud volám:

{snippetArea rowsArea}
	změn se prosím{time()}
	{foreach $result->objects as $technologyId => $technologyRow}
		{control "inlineChart-" . bin2hex($technologyRow->getOperation())}
	{/foreach}
{/snippetArea}

tak se právě $result->objects neaktualizuje, ale vše ostatní tak presně jak má.

Editoval emololftw (27. 10. 2021 15:01)