Ajax – Zmena formulare po odesilani pozadavku

Piticu
Člen | 93
+
0
-

Ahoj,

uz nekolik hodin se snazim davat dohromady Ajax,Zmena formulare a Snippet(predpokladam ze tohle potrebuji pro zmenu formulare). Vubec se nedari aspon trochu prekreslovat okno.

answerSecurityQuestionForm.latte

<form n:name="answerSecuriyQuestionForm">
....
</form>

sendPasswordLinkForm.latte

<script>
    window.onload = function () {
        $('#submit').click(function (e) {
            $.ajax({
                type: "POST",
                url: {link checkEmail!},
                data: { email: $('#email').val()},
                 success: function (data) {
                 alert('OK');
                 },
                 error: function (textStatus, errorThrown) {
                 alert('BAD');
                 }
            });
        });
    }
</script>
<form n:name="sendPasswordLinkForm">
....
</form>

reset.latte – hlavni soubor pro obnoveni hesla

{block title}Obnovení hesla{/block}
{block content}
.....

        {if $presenter->getParameter('token') && $presenter->getParameter('email')}
            {include 'resetPasswordForm.latte'} //TOHLE NENI NIJAK PODSTATNE
        {else}
            {include 'sendPasswordLinkForm.latte'}
        {/if}
......
{/block}

AccountPresenter

class AccountPresenter extends BasePresenter
{
    public function handleCheckEmail(){
        if($this->isAjax()){
			//pokud zadana emailova adresa existuje
			//nejak kouzelne smaz aktualni formular a zobraz formular answerSecuritQuestionForm.latte
        }
    }
}

Rozdelil jsem formulare do vice latte souboru, ale nemam problem je dat dohromady, pokud bude fungovat prepinani formularu.
V podstate sendPasswordLinkForm.latte obsahuje formular, kde uzivatel zadava email sveho uctu.

Pokud takovy email existuje,tak chci aby aktualni formular zmizel a misto neho, aby byl answerSecuriyQuestionForm, ktery obsahuje bezpecnostni otazku a odpoved, ktere patri k uctu se zadanym emailem.

Jak teda na to?

Zkusil jsem neco ve smyslu:

$this->template->setFile(__DIR__ . '/../templates/Account/answerSecurityQuestionForm.latte');
$this->template->render();

nebo redrawControl ruznymi zpusoby, ale bez sance. Nevim jak na to.

Dekuji vam.

Editoval Piticu (30. 1. 2018 2:13)

Šaman
Člen | 2666
+
0
-

A ty snippety máš kde?

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

a navíc když si to takhle řešíš sám a nepoužíváš třeba nette.ajax.js, takže si musíš ten snippet sám překreslit v successu potom co ti ze serveru přijde payload s novou šablonou

Piticu
Člen | 93
+
0
-

Tak udelal jsem teda par zmen, ale porad delam neco spatne. Je to poprve kdyz pracuji s ajaxem a snippety a moc mi to nejde no :D

AccountPresenter

public function handleCheckEmail(){
        $this->redrawControl('resetPassword');

}

reset.latte

{snippetArea resetPassword}
           {if $presenter->isAjax()}}
				{include 'aswerSecurityQuestionForm.latte'}
           {else}
               {include 'sendPasswordLinkForm.latte'}
           {/if}
 {/snippetArea}

sendpasswordLinkForm.latte

//formular pro zadani emailove adresy
<a n:href="checkEmail!" class="ajax">Submit</a>

Ajax pozadavek se odesle, ale porad stejny formular. Jdu na to dobre? Nebo spis zase mam tam nesmysly?

Šaman
Člen | 2666
+
0
-

SnippetArea se nepřekresluje, ta slouží ke složitější práci se snippety. Pro začátek zkus:

  1. Obyčejnou šablonu, v ní mít snippet (bez snippetArea)
  2. přilinkovat a inicializovat nette.ajax.js (a pozor, pro určitou práci s formuláři je potřeba mít i nette.forms.js, jinak ten ajax nefunguje – je tam nezdokumentovaná závislost.)
  3. Překreslit snippet z handleru presenteru.

Až tohle bude fungovat, můžeš to zkoušet zesložiťovat.

Piticu
Člen | 93
+
0
-

Šaman napsal(a):

SnippetArea se nepřekresluje, ta slouží ke složitější práci se snippety. Pro začátek zkus:

  1. Obyčejnou šablonu, v ní mít snippet (bez snippetArea)
  2. přilinkovat a inicializovat nette.ajax.js (a pozor, pro určitou práci s formuláři je potřeba mít i nette.forms.js, jinak ten ajax nefunguje – je tam nezdokumentovaná závislost.)
  3. Překreslit snippet z handleru presenteru.

Až tohle bude fungovat, můžeš to zkoušet zesložiťovat.

Ted jsem zkusil jen nejakej text prekreslovat, ale porad nic. Neco, nekde delam spatne. Takze zatim zbytecne neco nacvicuji s formularem.

public function renderReset(){
    $this->template->resetForm = "aaaaaaaaaaaa";
}
public function actionReset($email, $token){}

public function handleCheckEmail(){
    if($this->isAjax()){
        $this->template->resetForm = "bbbbbbb";
        $this->redrawControl('resetPassword');

    }

}
{snippet resetPassword}
{$resetForm}
    <a n:href="checkEmail!" class="ajax">Submit</a>
{/snippet}

Ocekaval jsem ze po kliknuti na Submit se mi to prepise na bbbb. Zadna zmena. Zatim zkoumam co delam spatne.

Šaman
Člen | 2666
+
0
-

Jop, přesně tohle jsem myslel. Ještě si zjisti, jestli vůbec nastane to $this->isAjax() (třeba pomocí bdump). Když ne, zkontroluj si ty js knihovny. Jakou verzi Nette máš?

Dodatek: Zkus ještě tu renderReset změnit na actionReset. Teď z hlavy nevím, jestli se při překreslení znovu nenastaví původní hodnota v té render metodě. Já už používám hlavně komponenty, tam tenhle problém nenastává (a ty se nastavují z podobných důvodů už v action).

Editoval Šaman (30. 1. 2018 12:20)

Piticu
Člen | 93
+
0
-

Šaman napsal(a):

Jop, přesně tohle jsem myslel. Ještě si zjisti, jestli vůbec nastane to $this->isAjax() (třeba pomocí bdump). Když ne, zkontroluj si ty js knihovny. Jakou verzi Nette máš?

$this->isAjax() funguje. Ted jsem zkusil tenhle priklad:

https://doc.nette.org/…ication/ajax#…

a vsechno funguje v poradku :). Verze 2.4

Šaman
Člen | 2666
+
0
-

Ještě jsem tam dopsal tu poznámku o action a render. Verze 2.4 je fajn, při ajaxu se ti přidá i debug panel, takže se během ajaxových požadavků dá dumpovat. To dost ulehčuje ladění.

Piticu
Člen | 93
+
0
-

Šaman napsal(a):

Ještě jsem tam dopsal tu poznámku o action a render. Verze 2.4 je fajn, při ajaxu se ti přidá i debug panel, takže se během ajaxových požadavků dá dumpovat. To dost ulehčuje ladění.

Uz mi funguje prepinani textu. Prepsal jsem renderReset na actionReset. Sice nevim proc to funguje, ale uz jsem udelal krok dopredu.

Mam jeste k tomu dotaz:

Jak muzu pouzit tuhle sablonu v Presenteru?

<form n:name="sendPasswordLinkForm">
    <ul class="alert-message error" n:if="$form->hasErrors()">
        <li n:foreach="$form->errors as $error">{$error}</li>
    </ul>
    <div class="row myborder">
        <img src="{$basePath}/img/logo_websitebuilder.png" alt="FastWeb">
        <hr>
        {snippet flashMessage}
            <div n:foreach="$flashes as $flash" class="alert-message {$flash->type}">
                <a class="close" data-dismiss="alert">×</a>

                <p>{$flash->message}</p>
            </div>
        {/snippet}
        <div class="input-group margin-bottom-20">
            <span class="input-group-addon"><i class="glyphicon glyphicon-envelope mycolor"></i></span>
            <input id="email" size="60" maxlength="255" class="form-control"
                   placeholder="Emailová adresa vašeho účtu" n:name="email" type="text">
        </div>
        <br><br><br><br>

        <div class="row">
            <div class="col-md-12 text-center">
                <button class="btn-u" type="submit" n:name="reset">Obnovit heslo</button>
            </div>
        </div>
        <a n:href="checkEmail!" class="ajax">Submit</a>
        <div class="row">
            <div class="col-md-12">
                <p class="account-already">Pokud ještě nemáte účet, tady si ho <a n:href="signup">vytvoříte.</a></p>
            </div>
        </div>
        <div class="row">
            <div class="col-md-12">
                <p class="account-already">Pokud už účet máte, stačí se <a n:href="signin">přihlásit.</a></p>
            </div>
        </div>
</form>

ukaze mi error Unknown attribute n:name in.... Zkusil jsem

Nette\Bridges\ApplicationLatte\UIMacros::install($latte->getCompiler());

ale bez uspechu :/ Chci ted delat totez co s textem, jenze misto textu budou ty dve sablony.

UPDATE:

$latte = new Latte\Engine;
Nette\Bridges\ApplicationLatte\UIMacros::install($latte->getCompiler());
$this->template->resetForm = $latte->render(__DIR__ . '/../templates/Account/sendPasswordLinkForm.latte');

Takhle to mam prozatim.

Editoval Piticu (30. 1. 2018 12:44)

Šaman
Člen | 2666
+
0
-

Tak to bylo tím, že po příkazu k překreslení se opravdu znovu spustí render, včetně render metody. A ta to přepsala zase na aaaaa. Action nastává ještě před handlery.


Nechápu otázku. V šabloně presenteru přece n:makra fungují. To zkoušíš samostatné latte, nebo co? Jestli ti jde o includované šablony, udělej si z nich komponenty. Includované šablony si se snippety moc nerozumí (ta makra se musí předtím zkompilovat).
Jestli pracuješ s běžnou strukturou projektu, tak žádné ruční instalace latte nepotřebuješ.

Editoval Šaman (30. 1. 2018 12:47)

Piticu
Člen | 93
+
0
-

Šaman napsal(a):

Tak to bylo tím, že po příkazu k překreslení se opravdu znovu spustí render, včetně render metody. A ta to přepsala zase na aaaaa. Action nastává ještě před handlery.


Nechápu otázku. V šabloně presenteru přece n:makra fungují. To zkoušíš samostatné latte, nebo co? Jestli ti jde o includované šablony, udělej si z nich komponenty. Includované šablony si se snippety moc nerozumí (ta makra se musí předtím zkompilovat).

V podstate mam 2 formulare, a kazdy ma svuj latte soubor. A muj cil je zobrazit(includovat) jeden a po odeslani AJAX pozadavku, odstranit ten prvni a zobrazit(includovat) druhy.

Zkusim se teda mrknout na komponenty.

Projekt jsem udelal pres composer: composer create-project nette/web-project myproject

Editoval Piticu (30. 1. 2018 12:53)

Šaman
Člen | 2666
+
0
-

Jj, web-project je dobrý základ. Pak nepotřebuješ žádné latte bridges, to máš už všechno funkční.
Co potřebuješ je buď hodit ty formuláře do komponenty (vlastní, pokud potřebuješ to ruční vykreslení), nebo je zatím vykreslovat pomocí rendereru (pak se s nimi pracuje taky jako s komponentou a vykreslí se pomocí {control testForm}). Kdysi jsem includoval šablony, ale už pár let jsem to nedělal, tak ti neřeknu kde přesně bude problém. Ale v includovaných šablonách některé složitější možnosti latte nefungují. (Bude to souviset s tím, že běžná šablona je vlastně nejen html, ale i kód, který je potřeba zkompilovat. A u snippetů se při tom vygenerují i funkce pro překreslování jednotlivých bloků apod. Ale includovat můžeš i za běhu a pak ti tyhle předkompilované části chybí.)

Piticu
Člen | 93
+
0
-

Ja se chtel drzet latte souboru, kvuli te HTML struktry (divs). Tak moje predstava byla, ze to pujde bez problemu :D

Jinak je v Presenteru mam i jako Component

protected function createComponentSendPasswordLinkForm()
{
    $form = new Form;
    $form->addEmail('email')
        ->setRequired('Zadejte prosím Email Vašého účtu');
    $form->addSubmit('reset','Obnovit');
    $form->onSuccess[] = [$this,'sendPasswordLinkFormSucceded'];
    return $form;
Šaman
Člen | 2666
+
0
-

Tak to zkus nejprve renderovat defaultně {control sendPasswordLinkForm}. To si dej do ifů a zkus rozchodit. Jako poslední pak bude vyčlenit to do komponent a přidat manuální vykreslení.

Případně to prostě dej oboje manuálně do šablony presenteru. Bez includování.

Jinak koukal jsem, že includování ještě používám, ale jen na vložení menu. Tam nemám nic složitějšího, než pár ifů pro zvýraznění aktuální položky. A řekl bych, že na složité věci to ani není určené. K tomu slouží komponenty (zvlášť, když chceš mít pohromadě kód a šablonu, což je přesně to, co od formulářů chceš).

Piticu
Člen | 93
+
+1
-

Šaman napsal(a):

Tak to zkus nejprve renderovat defaultně {control sendPasswordLinkForm}. To si dej do ifů a zkus rozchodit. Jako poslední pak bude vyčlenit to do komponent a přidat manuální vykreslení.

Případně to prostě dej oboje manuálně do šablony presenteru. Bez includování.

Jinak koukal jsem, že includování ještě používám, ale jen na vložení menu. Tam nemám nic složitějšího, než pár ifů pro zvýraznění aktuální položky. A řekl bych, že na složité věci to ani není určené. K tomu slouží komponenty (zvlášť, když chceš mít pohromadě kód a šablonu, což je přesně to, co od formulářů chceš).

No,je to na me uz dost narocne a trochu se v tom ztracim, ale asi zrusim sablony a zkusim prve mit vsechno v jedne sablone hlavni sablone. Hlavni cil je at to jakkoliv funguje :D

Edit: Kouzelnym zpusobem funguje to pomoci if a isAjax.

{snippet resetPassword}
	{if $presenter->isAjax()}
    <form n:name="answerSecuriyQuestionForm">
		//form
    </form>
  {else}
    <form n:name="sendPasswordLinkForm">
		//form
    </form>
  {/if}

  <a n:href="checkEmail!" class="ajax">Submit</a>
{/snippet}

Dekuji za pomoc

Editoval Piticu (30. 1. 2018 13:58)