Problém s dynamickým skrývaním prvkov vo formulári

MajklNajt
Člen | 498
+
0
-

Ahoj,

narazil som na takýto problém s toggle pri formulári:

  1. mám vytvorený select s rôznymi hodnotami, podľa jednotlivých hodnôt sa skrývajú/odkrývajú niektoré časti formulára – všetko funguje perfektne
  2. mám druhý select, ktorý pri zmene ajaxom prekreslí jednu z týchto častí formulára – funguje bezproblémovo, snippet sa posiela, prekresľuje
  3. po prekreslení snippetu sa však skryjú všetky skrývateľné časti formulára – nechápem prečo, v konzole žiadna chyba, dokonca pri následnom change toho prvého selectu sa opäť jednotlivé časti skrývajú/odrývajú správne

Stretli ste sa s niečim podobným?

Polki
Člen | 553
+
0
-

Sice jsem se s tím nesetkal, ale jak píšeš, tak překresluješ část formuláře. Zkoušel jsi překreslit celý formulář? Můj typ, když překreslíš část, tak ta nová část se aplikuje podle nových pravidel, které jsou nastavené na skrytí, jelikož jsi ze serveru poslal jen část a né vše, takže pravidla neexistují, takže se vezme výchozí hodnota.

Takže bych zkusil řešit 2 způsoby:

  1. překreslovat ve snippetu a na klienta posílat celý formulář
  2. po dokončení ajax requestu vyvolat ‚change‘ událost na nastavovacím selectu (toto ale může způsobit probliknutí)
MajklNajt
Člen | 498
+
0
-

nemyslím si, že by sa to skrylo kvôli snippetu, lebo ten je vo vnútri toho „skrývajúceho“ elementu (#protocolsOptions), samotné „skrývajúce“ elementy zostávajú stále v DOMe

protected function createComponentOptionsForm(): Form
{
	$form = new Form();
	$set = $form->addSelect("set", "Tlačová zostava", ["certificates" => "Certifikáty", "protocols" => "Protokoly", "documentation" => "Dokumentácia"]);

	$set->addCondition(Form::EQUAL, "certificates")->toggle("certificatesOptions");
	$set->addCondition(Form::EQUAL, "protocols")->toggle("protocolsOptions");
	$set->addCondition(Form::EQUAL, "documentation")->toggle("documentationOptions");

	$certificatesOptions = $form->addContainer("certificatesOptions");
	$certificatesOptions->addText(...);
	$certificatesOptions->addText(...);

	$protocolsOptions = $form->addContainer("protocolsOptions");
	$protocolsOptions->addSelect("course", "Kurz"); // <-- na tento element sa potom binduje onchange
	$protocolsOptions->addText(...);

	$documentationOptions = $form->addContainer("documentationOptions");
	$documentationOptions->addText(...);
	$documentationOptions->addText(...);

	... submit, succes callback a všetko ostatné potrebné ...

	return $form;
}
{form optionsForm}
    <div n:ifcontent class="flashes">
        <div n:foreach="$form->errors as $error" class="flash error">{$error}</div>
    </div>
    <p>{label set /}{input set}</p>
    <div id="certificatesOptions">
        {snippet certificatesOptions}
            {formContainer certificatesOptions}
                {foreach $formContainer->getComponents() as $i}{label $i /}{input $i}{/foreach}
            {/formContainer}
        {/snippet}
    </div>
    <div id="protocolsOptions">
        {snippet protocolsOptions}
            {formContainer protocolsOptions}
                {foreach $formContainer->getComponents() as $i}{label $i /}{input $i}{/foreach}
            {/formContainer}
    		<script>
        	$("#" + {$control["optionsForm-protocolsOptions-course"]->htmlId}).on("change", function () {
	            $.nette.ajax({
	                type: "GET",
	                url: {link courseChange!},
	                data: {
	                    {$control->getParameterId("course_id")}: $(this).val()
	                }
	            });
	        });
		    </script>
        {/snippet}
    </div>
    <div id="documentationOptions">
        {snippet documentationOptions}
            {formContainer documentationOptions}
                {foreach $formContainer->getComponents() as $i}{label $i /}{input $i}{/foreach}
            {/formContainer}
        {/snippet}
    </div>
    <p>{input export}</p>
{/form}

podľa mňa je problém v reinicializácií prvkov, ktoré sa nejako nesprávne vyhodnotí…

Editoval MajklNajt (8. 2. 2020 14:43)

Polki
Člen | 553
+
0
-

@MajklNajt tak takto:

  1. musíš si minimálně obalit formulář snippetAreou, ale to asi víš, jinak by dotaz vypadal jinak.
  2. zkopíroval jsem si tvůj příklad a funguje bezproblémově. Otázka je tedy, jaké snippety všechny překresluješ a co do šablony posíláš (na čem všem záleží zobrazení apod). + Jestli používáš NetteForms, nebo nepoužíváš zároveň nette.ajax.js a Nittro apod…
  3. jinak inicializace prvků problém není. V případě, že neodesíláš formulář pomocí submit, ale posíláš na překreslení formuláře signál, jak to máš teď ty, tak se formulář vykreslí v ‚základním‘ nenaplněném stavu, takže vše, co vykreslíš a pošleš snippety zpátky ke klientovi se jeví, jako by jsi to nikdy nevyplnil. Je možné, že se to děje na základě tohoto chování. Zkusil bych si vytvořit tlačítko, které bude mít na sobě nabindovanou událost onclick a v ní bych řešil to, co řeší handle. Možná se ti totiž díky tomuto zresetuje nějaká hodnota, která má za cíl nastavování viditelnosti?

PS (OFFTOPIC): když chceš šetřit přeposílání dat mezi serverem a klientem a kvůli tomu nechceš obalovat celý formulář do jednoho snippetu, ale děláš to takto rozkouskovaně, tak bych použil:

  1. na ty formulářové prvky dynamické snippety, aby se posílaly opravdu jen ty, které chceš a ne vždy celé pole
  2. ten JS kód nabindoval na třídu, kterou bych přidal tomu danému selectu a JS kod vyhodil ven z formuláře a dal jej tam, kam patří (do souboru mimo HTML) a aby se aplikoval i na to, co změní ajax, tak bych jen změnil volání na:
$(document).on("change", ".tridaCoJsemDalSelectu", function () {
    ...
});

no a URL/název proměnné se pak dá předat do toho JS pomocí data atributu.

MajklNajt
Člen | 498
+
0
-

ospravedlňujem sa, funguje všetko tak, ako má fungovať… problém bol štandardne medzi PC a stoličkou – formulár som načítaval v modal okne a pobili sa tam ID-čka elementov