Po redraw submit tlačítko nereaguje a toggle přestane fungovat

anakonda100000
Člen | 6
+
0
-

Zdravím Vás!
Jsem nováček Nette a netušil jsem, zda tento problém patří do Začátečníci, Formuláře nebo do AJAX, tak se předem omlouvám, pokud jsem problém kategorizoval špatně. Nyní tedy k problému…

Přihlášený uživatel – správce rodinného účtu (tzn. že by měl umět nastavit emailové notifikace pro všechny členy rodiny)
Mám portlet se třemi taby, v každém z nich je jeden form.
Tab1 – Změna hesla
Tab2 – Změna loginu
Tab3 – Nastavení emailových notifikací <--- místo problému

{if $contactPerson}
	<div class="m-form__group form-group row">
		<center class=" col-12">
			<label for="selectPerson">Vyberte, komu chcete posílat notifikace</label>

		</center>
		<div class="col-md-6 offset-md-3">
			<center>
				<select class="form-control m-input" id="selectPerson">
					{foreach $people as $person}
						{if $person->email}
							{if ($contactRow->email == $person->email)}
								<option selected="selected" value="{$person->id}">{$person->email}S(Váš účet)</option>
							{else}
								<option value="{$person->id}">{$person->email}</option>
							{/if}
						{/if}
					{/foreach}
				</select>
			</center>

		</div>
	</div>
{/if}
{snippet redrawNotificationForm}

	{form notificationForm}
		{$emairu}
		{foreach $types as $key => $type}
			{if $key != 4}
				<div class="m-form__group form-group row">
					<label class="col-6 col-form-label" n:name="{$key}">{$type}</label>
					<div class="col-6">
						<span class="m-switch m-switch--lg m-switch--icon">
							<label>
								<input type="checkbox" n:name="{$key}" {if $selectedUserRow->notifikace & $key}checked="checked"{/if} class="ajax">
								<span></span>
							</label>
						</span>
					</div>
				</div>
			{else}

				{switch $notificationStatus}

				{case 'Aktivní'}
				<div class="m-form__group form-group row">
					<label class="col-6 col-form-label" n:name="{$key}">{$type}</label>
					<div class="col-6">
						<span class="m-switch m-switch--lg m-switch--icon">
							<label>
								<input type="checkbox" n:name="{$key}" {if $selectedUserRow->notifikace & $key}checked="checked"{/if} class="ajax">
								<span></span>
							</label>
						</span>
					</div>
					<div class="col-4">
						<center>
							<div  id="days">
								<h4>Kdy mě upozornit</h4>
								{input day class => "form-control m-input"}

							</div>
						</center>
						<center>
							<div id="times" style="padding-top: 5px;">
								{input time class => "form-control m-input"}
							</div>
						</center>
					</div>
					<div class="col-8">
						<div id="trashtypes">
							<div class="m-form__group form-group">
								<h4>Na co mě upozornit</h4>

								<div class="m-checkbox-list">
									<div class="row">
										{foreach $form[trashtype]->items as $key => $value}
											<div class="col-4">
												<label n:name="trashtype:$key" class="m-checkbox">{$value}
													<input type="checkbox" n:name="trashtype:$key" class="ajax"><span></span>
												</label><br>
											</div>
										{/foreach}
									</div>
								</div>
							</div>
						</div>
					</div>
				</div>

				{case 'Bude ukončeno'}
				<div class="m-form__group form-group row">
					<label class="col-6 col-form-label" n:name="{$key}" style="color: #ffb822;"><span  data-toggle="m-tooltip" data-original-title="Váš obecní/městský úřad ještě nezadal datum dalšího svozu. Pokud se tak nestane do třetího dne před koncem měsíce, budeme nuceni službu vypnout."><i class="fa fa-question" ></i> {$type}</span></label>
					<div class="col-6">
						<span class="m-switch m-switch--lg m-switch--icon">
							<label>
								<input  type="checkbox" n:name="{$key}" {if $selectedUserRow->notifikace & $key}checked="checked"{/if} class="ajax">
								<span></span>
							</label>
						</span>
					</div>
				</div>

				{case 'Ukončeno'}
				<div class="m-form__group form-group row">
					<label class="col-6 col-form-label" n:name="{$key}" style="color: #f4516c;"><span  data-toggle="m-tooltip" data-original-title="Váš obecní/městský úřad nezadal datum dalšího svozu. Jsme nuceni službu vypnout. V případě, že budete chtít službu obnovit, ozvěte se prosím na Váš obecní/městský úřad."><i class="fa fa-exclamation-triangle" ></i> {$type}</span></label>
					<div class="col-6">
						<span class="m-switch m-switch--lg m-switch--icon">
							<label>
								<input   type="checkbox" n:name="{$key}" {if $selectedUserRow->notifikace & $key}checked="checked"{/if} class="ajax">
								<span></span>
							</label>
						</span>
					</div>
				</div>
				{/switch}
			{/if}
		{/foreach}

		<center>
			{input submit class => 'ajax btn btn-brand'}
		</center>
	{/form}

{/snippet}

Ve třetím tabu přihlášený uživatel vidí selectbox, ze kterého vybere email/účet, kterému bude nastavovat notifikace.
Defaultně se načte email přihlášeného uživatele, tedy správce.
Když nastavuji form přihlášeného uživatele, tak je všechno v pořádku.
Jakmile selectboxem zvolím jiný email (chci nastavit notifikace jinému členu rodiny), načtu do formu uložené nastavení toho člena, které mohu měnit (checkboxy).

Problém je v tom, že poté mi již nefunguje submit button a vlastně ani toggle nefunguje.
Toggle i submit fungují před ajaxem perfektně.

Nevím, zda je to relevantní, ale když zmáčknu submit button v Tab3, tak se v Tab1 ve formuláři objeví setRequired věty (vyplňte prosím to či ono…), avšak když vyplním formulář v Tab1 a zmáčknu submit button v Tab3, tak se nic nestane (krom zmizení setRequired vět).

Už hledám řešení dva dny a určitě tam dělám nějakou základní chybu, kterou jsem přehlídl, ale netuším jak to vyřešit.
Myslím, že když zavolám ten ajax, tak tím překreslím IDčka, tudíž se nespustní JS, ale nevím, jak to vyřešit a zároveň ověřit, zda je to opravdu ten problém. Díky moc předem!

public function createComponentNotificationForm(): Form
	{
		$form = new Form();
		foreach ($this->types as $key => $type) {
			$checked = $this->emailNotificationHelper->checkTypes($this->selectedUserRow->notifikace, $key) ? true : false;

			if ($key == 4) {
				switch ($this->notificationStatus) {
					case 'Aktivní':
						$form->addCheckbox($key, $type)
							->setDefaultValue($checked)
							->addCondition($form::EQUAL, true)
							->toggle('days')
							->toggle('trashtypes');

						$form->addSelect('day', '', $this->notificationArrayModel->daysArray())
							->addCondition($form::MIN, 1)
							->addConditionOn($form[4], Form::EQUAL, true)
							->toggle('times');

						$form->addSelect('time', '', ['ráno', 'večer']);

						$form->addCheckboxList('trashtype', 'Typ svozu', $this->trashTypes);
						break;
					case 'Bude ukončeno':
						$form->addCheckbox($key, $type)
							->setDefaultValue(FALSE)
							->setDisabled(true);
						break;
					case 'Ukončeno':
						$form->addCheckbox($key, $type)
							->setDefaultValue(FALSE)
							->setDisabled(true);
						break;
				}
			} else {
				$form->addCheckbox($key, $type)
					->setDefaultValue($checked);
			}
		}

		$form->addSubmit('submit', 'Uložit notifikace');
		$form->onSuccess[] = [$this, 'manageNotificationSucceeded'];
		return $form;
	}

public function handleSelectedPersonId(): void
	{
		$response = $this->getHttpRequest()->getPost();
		bdump('handler', $response['selectedPersonId']);
		$this->template->emairu = $response['selectedPersonId'];
		$this->template->selectedUserRow = $this->setUser($response['selectedPersonId']);

		//bdump('before', $this['notificationForm']);
		//$this->createComponentNotificationForm();
		bdump('after', $this['notificationForm']);

		$this->redrawControl('wrapper');
		$this->redrawControl('redrawNotificationForm');
	}

Editoval anakonda100000 (27. 5. 2019 9:55)

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

klasický javascritový problém, po zavolání ajaxu ti dojde k překreslení obsahu a to znamená, že ty navěšené eventy zmizely, je potřeba je znovu inicializovat.

co tam máš za javascript? nějak to musíš inicializovat sám

Polki
Člen | 553
+
+1
-

Nevím, jestli to bude ten problém, protože jsem to nezkoumal dopodrobna, co tu máš rozepsáno, ale po ajaxovém požadavku se načte pouze část stránky a na tu danou část se neaplikuje JS, který máš nalinkovaný na změněný kód.

Proto by jsi měl tento JS po vykonání AJAXu vykonat znovu. Nejlépe jako uživatelsky vytvořenou extension v souboru nette.ajax.js viz dokumentace k nette.ajax.js

Polki
Člen | 553
+
0
-

Ondřej Kubíček napsal(a):

klasický javascritový problém, po zavolání ajaxu ti dojde k překreslení obsahu a to znamená, že ty navěšené eventy zmizely, je potřeba je znovu inicializovat.

co tam máš za javascript? nějak to musíš inicializovat sám

o chvíli jsi mě předběhl :D

anakonda100000
Člen | 6
+
0
-

V JS souboru mám jen naslouchač na změnu v select boxu viz. níže. Jak můžu tedy znovu inicializovat všechen JS? V hlavní template mám naimportované nette.ajax.js. Zkoušel jsem $.nette.load(); a $.nette.init();, ale asi to chápu špatně. Díky za rychlou odezvu. Mile překvapilo!

<script>
$("#selectPerson").on("change", function () {
	console.log($(this).children("option:selected").val());
	$(this).prop("disabled", true);
	$.nette.ajax(
			{
				type: 'post',
				url: selectedPersonId,
				data: {'selectedPersonId': $(this).children("option:selected").val()},

				complete: function () {
					console.log('Done!');
					$("select#selectPerson").prop("disabled", false);
//$.nette.load();
					$.nette.init();
				}
			});
});
</script>

Editoval anakonda100000 (27. 5. 2019 11:05)

manwe
Člen | 44
+
+1
-

@anakonda100000 mas dve moznosti.
Bud zmenis listener z

$("#selectPerson").on("change", function () {

na

$('document').on('change', '#selectPerson', function() {

nebo si tuhle inicializaci das do nejake funkce (treba „bindFunctions“) a tu bindFunctions pak pak budes po complete ajaxu volat. Pouzivame to takto

<script>
(function ($, undefined) {
	$.nette.ext('bindMyStuff', {
        complete: function(){
            bindFunctions();
        }
    });
})(jQuery);

$(document).ready(function(){
    bindFunctions();
})
jiri.pudil
Nette Blogger | 1032
+
+2
-

Jenom pro doplnění: problém je v tom, že se po ajaxovém požadavku všechny snippety nahradí na úrovni DOMu, takže element, na který jsi navěsil listener ($("#selectPerson")), už neexistuje nebo dožívá jenom někde v paměti a v DOMu je místo něj jiná instance, byť třeba ve všech ohledech stejná.

anakonda100000
Člen | 6
+
0
-

Zkoušel jsem nyní asi hodinku zmíněné varianty od @manwe a asi určitě dělám něco špatně viz. js kód.

<script>
(function ($, undefined) {
	$.nette.ext('bindMyStuff', {
		complete: function () {
			bindFunction();
		}
	});
})(jQuery);

jQuery(document).ready(function () {
 bindFunction();
 });

function bindFunction() {
	$("#selectPerson").on("change", function () {
		console.log($(this).children("option:selected").val());
		$($(this)).prop("disabled", true);
		$.nette.ajax(
				{
					type: 'post',
					url: selectedPersonId,
					data: {'selectedPersonId': $(this).children("option:selected").val()},

					complete: function () {
						console.log('Done!');
						$("select#selectPerson").prop("disabled", false);
						//$.nette.load();
						//$.nette.init();
					}
				});
	});
}
</script>

Po vybrání jiné option v selectboxu i nadále nefunguje toggle a ani submit button.
Navíc po prvním vybrání mi již nefunguje $($(this)).prop(„disabled“, true);.
Vkládání defaultních hodnot z presenteru však funguje, avšak to fungovalo i předtím.

Kamil Valenta
Člen | 820
+
+2
-

Dej si dovnitř snippetu v šabloně formuláře tohle:

<script>
	window.Nette.initForm($('#frm-Form').get(0));
</script>

Samozřejmě si změň ID formu na reálnou hodnotu. Jakmile se snippet invaliduje, překreslí se i tento JS, který znovu vše nahodí.

anakonda100000
Člen | 6
+
0
-

Pecka! Díky všem za pomoc a informace!