Submit formuláře – refresh pouze snippet (ostatní formy na stránce zůstanou i s daty)

Tomas Trdla
Člen | 19
+
0
-

Zdravím,

  1. Pracuji na presenteru, který vytváří graf s filtrovanými daty.
  2. Filtry jsou vybrány v několika identických formulářích (každý z formulářů je pro jednu křivku v grafu → porovnání mezi nimy)
  3. Při aplikování filtrů jednoho z formulárů je překreslen pouze graf.

Jak to funguje: Problém nastává když je jeden z formulářů potvrzen. Celá stránka se refreshne a data v ostatních formulářích se ztratí.

Jak by to mělo fungovat: Všechny formuláře si ponechají svoje data a překreslen je pouze graf.

Kód pro několik formulářů na jedné stránce:

class MultiForm extends Form {

    var $parent; // used in process()

    public function __construct($parent = null, $name = null) {
        parent::__construct($parent, $name);
        $this->parent = $parent;
    }
}

Předvytvoření formulářu:

public function actionStatsTest() {
        $this->checkLogin();
        $formsID = array(1,2);

        foreach ($formsID as $id) {
            $this->_createSearchForm($id);
. . . // empty data for graph
        }

        $this->template->forms = $formsID;
		$this->template->graphData = $graphData;
    }

public function _createSearchForm($formID) {
        $form = new MultiForm($this, 'SearchForm_' . $formID);
        $this->DBpatientSearchFF->AddFilterFields($form);
        $form->addSubmit('send', 'Aplikovat filtry');
        $form->onSuccess[] = array($this, "postFormSucceeded");
    }

Form submit handler:

public function postFormSucceeded($form, $values) {
		//process into graph data
    // . . .
		$this->template->graphData = $graphData;
    $this->redrawControl('graph');
}

Latte:

{foreach $forms as $id}
	<div id="SearchFilters{$id}">
		<div class="panel-body">
			{var formName = 'SearchForm_' . $id}
			<form n:name="$formName" class="validation-form">
				{include '../MultipresenterForms/dbSearchForm.latte'}
				<fieldset class="form-group">
					<input n:name=send class="btn btn-primary">
				</fieldset>
			</form>
		</div>
	</div>
{/foreach}

{snippet graph}
        . . .
{/snippet}
Ondřej Kubíček
Člen | 494
+
0
-

nikde tam nevidím ajax, bez něj to neuděláš
a spíš bych ten form řešil přes multiplier

Tomas Trdla
Člen | 19
+
0
-

Mrknu na ten multiplier, díky

Tomas Trdla
Člen | 19
+
0
-

Tak multiplier můj problém nevyřešil, dělá přesně to samé → po submitu jednoho z formů multiplieru se stránka refreshne a co bylo napsané v ostatních formech zmizí a zůstane pouze ten submitnutý

je nějaká možnost jak z latte poslat instanci formu do handler metody… něco jako <a n:href="methodHandle! $form, $formID">Apply</a>, že bych si ty data vytahnul ručně?

a ten ajax se nedaří, pravděpodobně protože pořadně nevim jak na to

Editoval Tomas Trdla (20. 4. 2018 12:19)

Ondřej Kubíček
Člen | 494
+
0
-

ten multiplier je jen na to abys to nedělal tak prasácky jak jsi to měl :)
jinak jsem ti psal, že tam nemáš ajax, takže si nastuduj https://doc.nette.org/…ication/ajax

Editoval Ondřej Kubíček (20. 4. 2018 12:21)

Tomas Trdla
Člen | 19
+
0
-

takze…

public function createComponentSearchForm($formId) {
    return new Multiplier(function ($formId) {
        $form = new Form;
        $this->DBpatientSearchFF->AddFilterFields($form);
        $form->getElementPrototype()->class('ajax'); // pridavam ajax formu poprve
        $form->onSuccess[] = array($this, 'postFormSucceeded');
        return $form;
    });
}
<form n:snippet="fsnipet$id" n:name=searchForm-$id class="validation-form ajax"> pridavam ajax do formu podruhe
	{include '../MultipresenterForms/dbSearchForm.latte'}

	<fieldset class="form-group">
		<a n:href="FormRefresh! $id" class="btn btn-warning ajax"> Odebrat křivku</a> *V1* s ajaxem pres handle
		<a n:href="FormRefresh! $id" class="btn btn-warning"> Odebrat křivku</a> *V2* bez ajaxu pres handle
		<input n:name=send class="btn btn-primary ajax"> *V3* s ajaxem pres submit
		<input n:name=send class="btn btn-primary"> *V4* bez ajaxu pres submit
	</fieldset>
</form>

a vysledek:

public function postFormSucceeded($form, $values) {//tady form ziskam, ale nejde ajax
    if (!$this->isAjax()) {
        // tady skonci V3 a V4
    } else {
        // sem se nedostane nikdy
    }
}

public function handleFormRefresh($id) { // nevim jak ziskat form, ale ajax jde
    if (!$this->isAjax()) {
        // sem se dostane V2
    } else {
        // sem se dostane V1
			// ale nemam obekt formu abych z nej mohl nacist hodnoty nebo s nim vubec neco udelat
    }
}

a pro uplnost layout a js inicializace

{block scripts}
	...
	<!-- Ajax scripts -->
	<script src="{$basePath}/bs/js/nette.ajax.js"></script>
	...
{/block}
$(function () {
    $.nette.init();
});

jak tedy ziskam formular? uz jsem stravil nekolik hodin hledanim a nenasel nic co by mi fungovalo

jo a V3 mi vyhazuje chybu v konzoli:

Uncaught ReferenceError: Nette is not defined	(nette.ajax.js:319)
    at Object.before (nette.ajax.js:319)
    at Function.<anonymous> (nette.ajax.js:42)
    at Function.each (jquery.min.js:2)
    at Object.fire (nette.ajax.js:40)
    at Object.settings.beforeSend (nette.ajax.js:215)
    at Function.ajax (jquery.min.js:4)
    at nette.ajax (nette.ajax.js:225)
    at HTMLFormElement.requestHandler (nette.ajax.js:48)
    at HTMLFormElement.dispatch (jquery.min.js:3)
    at HTMLFormElement.q.handle (jquery.min.js:3)

je radek: if ((typeof Nette.version === 'undefined' || Nette.version == '2.3')) { // Nette 2.3 and older

a jediny co je starsi nez 2.3 jsou tyhle:

"name": "nette/tester",
"version": "v1.7.1"

"name": "dg/composer-cleaner",
"version": "v1.0",

Editoval Tomas Trdla (26. 4. 2018 14:14)

Tomas Trdla
Člen | 19
+
0
-

Asi uz jsem na to prisel. Mel jsem v layoutu zakomentovane

{block scripts}
	<!-- Nette forms -->
	<script src="https://nette.github.io/resources/js/netteForms.min.js"></script>
	...
{/block}

po odkomentovani to uz skocilo tam kam melo

… ted si jeste vzpomenou proc to bylo zakomentovane

Editoval Tomas Trdla (26. 4. 2018 14:21)

Tomas Trdla
Člen | 19
+
0
-

Nicmene stale to neresi muj problem… snippet se proste neprekresli

{snippetArea wrapper}
	<div class="cont">
		{foreach $forms as $id}
			{var snipname = "fs$id"}
			{snippet $snipname}
				<form n:name=searchForm-$id class="validation-form ajax">
					{include '../MultipresenterForms/dbSearchForm.latte'}

					<fieldset class="form-group">
						<a class="btn btn-primary" onClick="HandleThisForms(this,{$id}, 'filter')">Aplikovat filtry</a>
						<input n:name=send class="btn btn-primary">
					</fieldset>
				</form>
			{/snippet}
		{/foreach}
	</div>
{/snippetArea}
public function postFormSucceeded($form, $values) {
	if ($this->isAjax()) {
		$id = $values->formID;
		$form->setValues([], TRUE);
		$form->setValues(['formID' => $id], TRUE);
		$this->redrawControl("fs$id");
	}
}

jako odpoved v XHR se mi dostane pouze

{state: []}
	state:[]

jmena snippetu co chci prekreslit jsou stejna jako na strance