Nefunkční překreslení snippetu

zzmichalqq
Člen | 7
+
0
-

Ahoj.

Poslední dobou si hraji s manažerem uživatelů, a trošku jsem se zasekl na vyhledání uživatelů. Chci ho udělat přes ajax, ať je načítání uživatelů dynamické a není potřeba vždy načítat celou stránku. AJAX se dle Tracy úspěšně posílá do Handlu a včetně dotazu do databáze (userId = 6), ale mám právě problém s překreslením snippetu, ve kterém vykresluji uživatele.

Latte:

{snippet kktAna}
	{foreach $usersTable as $userTable}
		<tr>
		<td>
			<div class="form-check p-0">
				<input class="select-user" onclick="selectCheckboxPrevent(this)" class="form-check-input position-static" value="{$userTable->id}" type="checkbox">
			</div>
		</td>
			<td>{$userTable->username}</td>
			<td>{$userTable->name}</td>
			<td>
				{switch $userTable->role}
					{case admin}
						Administrátor
					{case user}
						Uživatel
					{case guest}
						Host
					{default}
						Neznámá role
				{/switch}
			</td>
			<td class="text-center">
				{if $userTable->username != $user->getIdentity()->username}
					{if $userTable->active == 1}
						<a n:href="Users:deactivate $userTable->id"><i class="far fa-eye"></i></a>
					{else}
						<a n:href="Users:activate $userTable->id"><i class="far fa-eye-slash"></i></a>
					{/if}
				{/if}
			</td>
			<td class="text-center">
				<a class="btn btn-primary mr-2 edit-button" onclick="editModal(this)" data-userid="{$userTable->id}" href="#"><i class="far fa-edit pr-2"></i>Upravit uživatele</a>
				<a class="btn btn-danger ml-2" n:href="Users:delete $userTable->id"><i class="far fa-trash-alt pr-2"></i>Smazat uživatele</a>
			</td>
		</tr>
	{/foreach}
</tbody>
{/snippet}

Presenter:

public function renderDefault($string): void
{
    if (!$this->isAjax())
    {
        $this->template->usersTable = $this->database->table("users")->order("id ASC");
    }
}

Ajax handle:

public function handleSearchUsers(): void
{
    if ($this->isAjax())
    {
        $this->template->usersTable = $this->database->table("users")->where("id", 6);
        $this->redrawControl("kktAna");
    }
}
Kamil Valenta
Člen | 610
+
0
-
  1. Záměrně chceš při invalidaci všechny uživatele překreslit jedním?
  2. Snippet generuje nevalidní DOM (tbody).
  3. Díval ses, co se z handlu vrátí za json?
zzmichalqq
Člen | 7
+
0
-

Předem děkuji za odpověď.

1.) Ano, jde pouze o testovací select.
2.) Děkuji, upraveno.
3.) Handle vrací, podle mě, json správně – snippet se mi aktualizuje, ale jeho vykreslení už očividně neprobíhá.

{"state":[],"snippets":{"snippet--kktAna":"\t\t\t\t\t<tr>\n\t\t\t\t\t<td>\n\t\t\t\t\t\t<div class=\"form-check p-0\">\n\t\t\t\t\t\t\t<input class=\"select-user\" onclick=\"selectCheckboxPrevent(this)\" class=\"form-check-input position-static\" value=\"6\" type=\"checkbox\">\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</td>\n\t\t\t\t\t\t<td>asd</td>\n\t\t\t\t\t\t<td>Michal Slovák</td>\n\t\t\t\t\t\t<td>\n\t\t\t\t\t\t\t\t\tAdministrátor\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td class=\"text-center\">\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td class=\"text-center\">\t\t\t\t\t\t\n\t\t\t\t\t\t\t<a class=\"btn btn-primary mr-2 edit-button\" onclick=\"editModal(this)\" data-userid=\"6\" href=\"#\"><i class=\"far fa-edit pr-2\"></i>Upravit uživatele</a>\n\t\t\t\t\t\t\t<a class=\"btn btn-danger ml-2\" href=\"/matprac2/www/users/delete?userId=6\"><i class=\"far fa-trash-alt pr-2\"></i>Smazat uživatele</a>\n\t\t\t\t\t\t</td>\n\t\t\t\t\t</tr>\n"}}

EDIT: Vypadá to, že se mi vzhledem k životnímu cyklu presenteru přepisoval usersTable v latte v metodě renderDefault, tudíž jsem kod upravil:

public function renderDefault($string): void
{
    if (!isset($this->template->usersTable))
    {
        $this->template->usersTable = $this->database->table("users")->order("id ASC");
    }
}

Editoval zzmichalqq (16. 1. 2020 10:03)

Kamil Valenta
Člen | 610
+
0
-

Vždyť v renderu to máš za podmínkou !$this->isAjax(), to je v pohodě. JSON také vrací správně jen ten jeden řádek.

Hledal bych chybu na straně JS.
Máš načtený nějaký nette.ajax.js nebo něco podobného, co se postará o překreslení snippetu? Voláš ten handle opravdu ajaxově, neudělá se redirect, který by regulerně zpracoval renderDefault()?

zzmichalqq
Člen | 7
+
0
-

Ano, taktéž jsem si myslel, že ajaxová podmínka by měla stačit, ale nevypadá to tak. V layoutu inicializuji ajax následovně:

<script>
	$(function () {
		$.nette.init();
	});
</script>

Redirect se neprovádí, nevidím refresh stránky a ani tracy neříká, že byl poslán query do tabulky.

Editoval zzmichalqq (16. 1. 2020 11:05)

Phalanx
Člen | 310
+
0
-

Ukaž jak voláš handleSearchUsers

zzmichalqq
Člen | 7
+
0
-

Phalanx napsal(a):

Ukaž jak voláš handleSearchUsers

<a n:href="searchUsers! marian" class="ajax">Hledat</a>

Pochopitelně „marian“ je pouze placeholder. Ovšem když zaměním podmínku v metodě renderDefault na if (!$this->isAjax()), tak mi program funguje tak jak má. :) Jsem z toho jelen. Ve snippetu jsem musel ještě obalit celou tabulku, jinak mi to vypisovalo data nevhodně a mimo tabulku.

Editoval zzmichalqq (16. 1. 2020 17:55)

Robin Martinez
Člen | 79
+
0
-

Ahoj, zkousim to tu, protoze ted v jednoduchem jednoakcnim presenteru resim stejnou vec.

Mam treba 4 ‚handle‘ akce:

	public function handleChangeMenu(int $menu = null)
	{
		$this->session->supplier = null;
		$this->session->activeMenu = $menu;
		$this->session->search = null;
		$this->session->page = 1;

		$this->redrawControl();
	}

	public function handleClearFilters()
	{
		$this->session->activeMenu = null;
		$this->session->supplier = null;
		$this->session->search = null;
		$this->session->page = 1;

		$this->redrawControl();
	}

	public function handleSetSupplier(int $sid = null)
	{
		$this->session->supplier = $sid;
		$this->session->activeMenu = null;
		$this->session->search = null;
		$this->session->page = 1;

		$this->redrawControl();
	}


	public function handleSetSearchTerm(string $term = null)
	{
		$this->session->search = $term;
		$this->session->supplier = null;
		$this->session->activeMenu = null;
		$this->session->page = 1;

		$this->redrawControl();
	}

v renderu dle filtru naplnuji sablonu:

	public function renderDefault()
	{
		$filter['categories'] = $categorie //ziskano jinou funkci z $this->session->activeMenu;
		$filter['supplier'] = $this->session->supplier;
		$filter['search'] = $this->session->search;
		$filter['perPage'] = $this->session->perPage;
		$filter['page'] = $this->session->page;
		$filter['sort'] = $this->session->sort;

		$this->template->items = $this->model->getList($filter);

		\Tracy\Debugger::barDump($filter);
		\Tracy\Debugger::barDump($this->template->items);
	}

Problem mam v tom, ze handle metody handleChangeMenu() a handleClearFilters() plne funguji, ale zbyle dve ne. A to takovym zpusobem, ze v renderDefault se vse posle do sablony spravne (tracy debugy zobrazuji spravna data) a ajaxove mi tam snippety prijdou taktez spravne, nicmene DOM jako takovy se vubec neprekresli.

Uz s tim bojuju dva dny. Poradi nekdo, co muze byt spatne?

Editoval Robin Martinez (8. 9. 8:06)

Pepino
Člen | 183
+
0
-

@RobinMartinez Co používáš na ajax?

Robin Martinez
Člen | 79
+
0
-

nette.ajax.js

Vsude v aplikaci to funguje, ale tady v tom presenteru to funguje napul, to mi prijde divny.

Pepino
Člen | 183
+
0
-

A v konzoli není žádná chyba?

Robin Martinez
Člen | 79
+
0
-

ne, ale prisel jsem na jednu vec, pokud metodu


public function handleSetSearchTerm(string $term = null)
	{
		$this->session->search = $term;
		$this->session->supplier = null;
		$this->session->activeMenu = null;
		$this->session->page = 1;

		$this->redrawControl();
	}

predelam do ‚formulare‘:

	public function createComponentSearchForm(): Form
	{
		$form = new Form();

		$form->addText('search')
				->setHtmlAttribute('onkeyup', 'debounce(this.form.requestSubmit(), 600)')
				->setDefaultValue($this->session->search);

		$form->onSuccess[] = function (Form $form, ArrayHash $values) {
			$this->session->activeMenu = null;
			$this->session->supplier = null;
			$this->session->search = $values->search;
			$this->session->page = 1;

			$this->redrawControl();
		};

		return $form;
	}

tak to funguje. Ppredtim to bylo ciste <input> pole, ktere nastavovalo handleMetodu ciste pres nette.ajax. Ale to by snad proboha fungovat melo taky, stejne tak funguje tlacitko pro handleClearFilters()

Ted mi tedy uz jen chybi nejak zprovoznit metodu pro suggest. Takze musim to samy policko predelat do formulare a nejak tam naroubovat suggest.

Editoval Robin Martinez (8. 9. 9:23)

Robin Martinez
Člen | 79
+
0
-

tak jsem ze dvou samostatnych inputu udelal dva formy a funguje to.

Nejak to nepobiram, ale treba je to spravne.

Robin Martinez
Člen | 79
+
0
-

Ok, tak pokracuji dal a bude tam nejaky jiny problem, protoze mi nefunguje ani toto:

	public function handleOpenModal(int $productID = null, int $webID = null)
	{
		$this->template->modalWeb = $web = $this->webs->getWebById($webID);
		$this->template->modalProduct = $product = $this->products->getProductEntity($productID);

		$this->template->modalForm = $this->remoteProductFormFactory->create($web, $product);

		$this->template->openModal = true;

		$this->redrawControl();
	}
{snippet test}
{= ($openModal ?? false) ? 'show' : 'hide'}
{/snippet}

je to posledni ‚testovaci‘ verze, tak tam treba jsou blbosti, ale zkusil jsem x veci a nic.
Vzdy to vypise ‚hide‘, v js console zadny error, AJAX payload prijde spravne, ale dom se neprekresli.

zkusil jsem i update knihoven (php i js)

Editoval Robin Martinez (8. 9. 10:28)

Robin Martinez
Člen | 79
+
0
-

ok, tak pro de*ily jako jsem ja.

Pouzivejte $.nette.ajax, ne $.ajax

omg