Jak renderovat snippety na cizích webech?

před 6 dny

Chuchy
Člen | 63
+
0
-

Ahoj,
už jsem bezradný, tak se obrací na forum.

mám přes nette vygenerované formuláře, který vkládám na cizí weby zhruba takto

<script src="http://forms.local:8888/api/form-js/?hash=1bdc342cf4bea96018a0274d7c2b1f80"></script>

Formulář se mi vždycky na webu vykreslí, fungují i js a validace, dokonce se mi formulář podaří i odeslat a uložit, nicméně problém nastává při překreslení snippetů, ke kterému vůbec nedojde a ajax response mi vrátí již vyrenderovanou stránku.

Takhle vypadá můj presenter, na který se formuláře odkazují

public function startup()
{
    parent::startup();
    Debugger::$showBar = false;
    Debugger::$productionMode = false;
    $httpResponse = $this->getHttpResponse();
    $httpResponse->addHeader("Access-Control-Allow-Origin", "*");
}

Vytvoření formuláře

/**
 * @return FormControl
 * @throws InvalidLinkException
 */
public function createComponentFormControl(): FormControl
{
    $formControl = $this->formControl;
    $formControl->setFormLink($this->createLinkToForm($this->formForm->getHash()));
    $formControl->setFormForm($this->formForm);
    $formControl->setDefaultValues((array)$this->sessionSection->default);
    $formControl->onSuccessForm[] = function (Form $form) {
        $this->showForm = true;
        $values = $form->getHttpData(1);
        $this->formService->saveFormForm($values, $this->formForm);
        $this->sessionSection->limit--;
        $this->sessionSection->default = $this->formService->deleteFileValues($values, $this->formForm);
        $this->flashMessage("Formulář byl odeslán!");
        $this->redrawControl("formFormSnippet");
        $this->redrawControl("flash");
    };
    $formControl->onErrorForm[] = function (Form $form) {
        $this->submittedFormErrors($form);
        $this->redrawControl("formFormSnippet");
        $this->redrawControl("flash");
    };

    return $formControl;
}

a latte

{snippet flash}
<div class="m-section m-section--c-gray">
    <div class="container">
        <div n:foreach="$flashes as $flash" class="alert alert-{$flash->type}">
            {$flash->message}
        </div>
    </div>
</div>
{/snippet}
{snippet formFormSnippet}
    {control formControl}
{/snippet}

Pro odesílání používám klasický nette.ajax.js

Editoval Chuchy (9. 9. 9:08)

před 6 dny

chemix
Gold Partner | 1030
+
0
-

Ahoj @Chuchy

  1. jak renderujes formular? Jelikoz vidim jen odkaz na JS soubor? Takze renderujes form pomoci JS? Snippety jsou vazane na html id.
  2. co vidis za chyby nebo odpovedi v dev konzoli
  3. je to cele nekde videt?

před 6 dny

Chuchy
Člen | 63
+
0
-

1, formulář renderuji přes takovou prasárnu, která mi byla doporučená

public function renderJsData(string $hash)
{
    $htmlFile = file_get_contents($this->createLinkToForm($hash));
    foreach (explode("\n", $htmlFile) as $row) {
        echo "document.write('" . str_replace("'", "\'", $row) . "');";
        echo "\r\n";
    }

    $this->terminate();
}

2, v konzoli nejsou žádné chyby
console
console2

3, není, mám to zatím na localu

Editoval Chuchy (9. 9. 9:29)

před 6 dny

chemix
Gold Partner | 1030
+
0
-

@Chuchy nette aplikace nic nevraci po odeslani formulare? Nejak v te konzoli nemuzu nic najit?

před 6 dny

Chuchy
Člen | 63
+
0
-

chemix napsal(a):

@Chuchy nette aplikace nic nevraci po odeslani formulare? Nejak v te konzoli nemuzu nic najit?

vrací již pouze html
response

před 6 dny

chemix
Gold Partner | 1030
+
0
-

Tak tam je chyba, mel by vracet json response se snippetem k prekresleni

před 6 dny

Chuchy
Člen | 63
+
0
-

Tak to už trošku vím, spíš nevím, jak tomu „podstrčit“, že se jedná o ajax. Myslím si, že bych měl ještě něco přidat do hlavičky requestu, aby nette vědělo, že se jedná o ajax, aby mohlo poslat json response

předpokládám, že bude potřeba nastavit/vypnout JSON-P v odesílání ajaxu, ale u nette.ajax.js to jde?

Editoval Chuchy (9. 9. 10:32)

před 6 dny

CZechBoY
Člen | 3385
+
0
-

Stačí se podívat jak Nette zjišťuje, že se jedná o ajax http požadavek:
https://github.com/…/Request.php#L253

před 6 dny

Chuchy
Člen | 63
+
0
-

CZechBoY napsal(a):

Stačí se podívat jak Nette zjišťuje, že se jedná o ajax http požadavek:
https://github.com/…/Request.php#L253

Nejedná, jelikož to vrací false, nicméně to, ale stále posílám přes „ajax“ a to by mělo i na straně serveru poznat, že to přes něj posílám? takže musím asi upravit nějak hlavičky nette.ajax?

před 6 dny

chemix
Gold Partner | 1030
+
0
-

@Chuchy a opravdu se to posila pres XHR? Nette to pozna a lze pak pouzit jen dotaz na isAjax() a pak dat redrawControl. Tenhle kus kodu si sem neposlal jak zpracovavas form. Nahod

před 6 dny

Chuchy
Člen | 63
+
0
-

Tohle to vrací při použítí třídy ajax na formuláři

console

xhr

to vytváření už jsem posílal

/**
 * @return FormControl
 * @throws InvalidLinkException
 */
public function createComponentFormControl(): FormControl
{
    $formControl = $this->formControl;
    $formControl->setFormLink($this->createLinkToForm($this->formForm->getHash()));
    $formControl->setFormForm($this->formForm);
    $formControl->setDefaultValues((array)$this->sessionSection->default);
    $formControl->onSuccessForm[] = function (Form $form) {
        $values = $form->getHttpData(1);
        $this->formService->saveFormForm($values, $this->formForm);
        $this->showForm = true;
        $this->sessionSection->limit--;
        $this->sessionSection->default = $this->formService->deleteFileValues($values, $this->formForm);
        $this->flashMessage("Formulář byl odeslán!");
        if ($this->isAjax()) {
            $this->redrawControl("formFormSnippet");
            $this->redrawControl("flash");
        } else {
            $this->redirect("this");
        }
    };
    $formControl->onErrorForm[] = function (Form $form) {
        $this->submittedFormErrors($form);
        $this->redrawControl("formFormSnippet");
        $this->redrawControl("flash");
    };

    return $formControl;
}

Editoval Chuchy (9. 9. 13:39)

před 6 dny

Chuchy
Člen | 63
+
0
-

Ještě jsem přišel na to, že při použití klasického ajaxu

<script defer>
    document.addEventListener("DOMContentLoaded", function(event) {
        $('.form-sender').on('submit', function (e) {
            let form = $(this);
            let xhttp = new XMLHttpRequest();
            xhttp.onreadystatechange = function() {
                if (xhttp.readyState == 4 && xhttp.status == 200) {
                    alert("as");
                }
                else {
                }
            };

            xhttp.open("POST", form.attr('action'), true);
            xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
            xhttp.setRequestHeader('X-Requested-With', 'XMLHttpRequest');

            xhttp.send(form.serialize());

            return false;
        });
    });
</script>

takže je potřeba nějak dostat do nette.ajax volání XMLHttpRequest

vyvolá ajax a vrací response json
console
json

nicméně se mi stále nepřekreslí snippet, věděl by někdo, kde může být ještě chyba?

před 6 dny

chemix
Gold Partner | 1030
+
0
-

@Chuchy ahoj, chapu to spravne, ze tedy s tim nette.ajax.js to neposila formualre pomoci XHR ?

A co se ti vraci v preview, kdyz to posilas pres XHR naprimo ? JSON s invalidovanejma snippetama? ?

PS: nette.ajax.js je uz obsolote, pro tenhle drobny use case doporucuju Naja.js neni zavisla na jQuery

PSS: na obrazky je super https://cloudup.com

před 6 dny

Chuchy
Člen | 63
+
0
-

@chemix ahoj, ne i s nette.ajax se to pošle pomocí XHR, jen v hlavíčce requestu chybí X-Requested-With XMLHttpRequest, což zapříčiní, že to nette nevezme jako ajaxou operaci.

Preview, když to posílám na přímo vrací spracovaný dotaz a kompletní stránku (HTML) nikoliv JSON

před 5 dny

chemix
Gold Partner | 1030
+
0
-

@Chuchy to je divne ze to posle xhr ale neda tam tu hlavicku a nette to pak nepochopi… :-/ s tim neporadim …

jinak custom implementace snippetu by nemela byt obtizna, defakto si projdes ten json co se ti vraci, a vsechny snippety podle html id najdes a nahradis jim html obsah. A mas danou vec a nepotrebujes nette.ajax.js

před 5 dny

jiri.pudil
Člen | 875
+
0
-

Trochu hádám, protože CORS je ohromně komplexní, ale není potřeba hlavičky nad rámec nějakého minima (tnz. i X-Requested-With) explicitně whitelistovat pomocí Access-Control-Allow-Headers v odpovědi?

před 5 dny

Chuchy
Člen | 63
+
0
-

Tak jsem se po těžkém boji rozhodl, že místo nette.ajax rozjedu, nittro, mělo by umět všechno co potřebuji, jen nevím, kde mám změnit allowOrigins?

Pro info mi to přes nittro neposílá přes xhr, ale other. ale to bude určitě nějakým nastavením.

Editoval Chuchy (10. 9. 13:54)

před 5 dny

chemix
Gold Partner | 1030
+
0
-

@Chuchy imho nittro je na tohle kanon na vrabce…

před 5 dny

Chuchy
Člen | 63
+
0
-

@chemix to asi je, ale využiju ho i na dalších částech aplikace a když už se zbavím nette.ajax, tak at mám nějaký lepší nástroj..

dokáže mi někdo říct, kam tohle nasadit?

před 5 dny

chemix
Gold Partner | 1030
+
0
-

@Chuchy bud si to muzes nakonfigurovat online na https://www.nittro.org/download nebo se nechat inspirovat na https://github.com/nittro/forum a zbuidlit si custom verzi pomoci gulpu

před 4 dny

Chuchy
Člen | 63
+
0
-

@chemix ahoj, tak už mi to „funguje“, jen nechápu, proč se mi odesílají dva requesty naráz? to asi není očekávaná vlastnost..

dva dotazy

před 4 dny

chemix
Gold Partner | 1030
+
0
-

@Chuchy tak to je super, jen zjistit proc… zkus si krokovat JS kdo posila ten druhej, nezapomel jsi tam nejakej starej kod?

před 4 dny

Chuchy
Člen | 63
+
0
-

@chemix starej kod tam už není, ještě to budu muset projít hold no, důležité je, že to není správné, že to posílá 2 requesty, s čím už si nějak poradím :D

btw. když už tady píšu ohledně toho nittra.., jakým způsobem se dá odeslat formulář při změně? přes jquery jsem používal

$(document).on('change', '.formOverviewSearchForm', function () {
    $(this).submit();
});

pro nittro mám napsáno něco takového, jenže to mě nikam nepustí

_context.invoke(function(di) {
    var frm = di.getService('formLocator').getForm('frm-agreementSearchForm');
    frm.on("change", function () {
        console.log(frm);
    });
});

před 4 dny

chemix
Gold Partner | 1030
+
+1
-

Nittro ma sve forum na https://forum.nittro.org

Ani nevim ze se onchange vola na formu, jen na inputu ne?

před 4 dny

Chuchy
Člen | 63
+
0
-

@chemix někde jsem to tak vygooglil :)

před 4 dny

chemix
Gold Partner | 1030
+
0
-

@Chuchy link? Me to prijde prave divne

před 4 dny

jiri.pudil
Člen | 875
+
+2
-

Tip od boku: zobraz si v dev tools i metodu požadavku. Pokud je to cross-origin, je naopak velmi správné, že to posílá dva requesty po sobě. Klient totiž posílá nejprve tzv. preflight request metodou OPTIONS, pomocí které zjistí, jestli vůbec může požadavek poslat (na základě Access-Control hlaviček v odpovědi), a až když usoudí, že může, reálně posílá původní požadavek původní metodou.

Takže je třeba dát pozor na to, aby OPTIONS request nevykonal samotnou požadovanou akci. Úplně postačí, když pošle patřičné Access-Control hlavičky a vrátí prázdnou odpověď se stavem 204 No Content.