Jak v nette zprovoznit odeslání formuláře pomocí ajaxu
- andros
- Člen | 145
Ahoj, mohl by mi prosím, někdo poradit funkční příklad odeslání
formuláře ajaxem ? Rád bych si to vyzkoušel na první aplikaci. Našel jsem
tento návod: https://pla.nette.org/…ivajici-ajax
Tento návod využívá js soubor jquery.ajaxform.js (https://componette.org/search/?…)
, odkaz ale na tento soubor již neukazuje.
- petr.jirous
- Člen | 128
použij https://componette.org/…tte.ajax.js/ a pak už jenom stačí formuláři dát třídu ajax
- andros
- Člen | 145
Nějak se mi nedaří přemluvit formulář, aby fungoval ajaxově. Co potřebuju: v detailu produktu mám formulář pro vložení zboží do košíku. Bez ajaxu vše funguje.
v šabloně mám nalinkovaný soubor nette.ajax.js
<script type="text/javascript" src="{$basePath}/js/nette.ajax.js"></script>
v js souboru mám inicializaci:
$(function () {
$.nette.init();
});
V šabloně presenteru potřebuju pro začátek znovu vykreslit jet flash zprávu, takže jsem ji obalil do snipetu:
{snippet flash}
<div class="row">
<div class="col-lg-12">
{foreach $flashes as $flash}
<div class="alert alert-dismissible alert-{$flash->type}">
<button type="button" class="close" data-dismiss="alert">×</button>
{$flash->message}
</div>
{/foreach}
</div>
</div>
{/snippet}
a v presenteru mám metody pro formulář:
protected function createComponentAddToBasketForm()
{
$form = new Form;
$form->getElementPrototype()->class('ajax');
$form->addText('quantity', 'Počet ks:');
$form->addHidden('prod_id');
$form->addHidden('guest_id');
$form->addHidden('name');
$form->addHidden('price');
$form->setDefaults([
'quantity' => 1,
'prod_id' => $this->product['id'],
'name' => $this->product['name'],
'price' => $this->product['d1']
]);
$form->addSubmit('send', 'Do košíku');
$form->onSuccess[] = [$this, 'AddToBasketFormSucceeded'];
return $form;
}
public function AddToBasketFormSucceeded($form, $values)
{
$this->productManager->insertProduct([
'quantity' => $values->quantity,
'prod_id' => $values->prod_id,
'guest_id' => $this->getHttpRequest()->getCookie('guest'),
'name' => $values->name,
'price' => $values->price
]);
$this->flashMessage('Přidali jste zboží do košíku', 'success');
if (!$this->isAjax())
$this->redirect('Product:default', array("id" => $values->prod_id));
else {
$this->redrawControl('flash');
}
}
Po odeslání formuláře se mi vůbec neprovede zpracování formuláře (
vložení dat do databáze) a flash zpráva se nezobrazí.
Laděnka říká že tam něco ajaxového proběhlo
http://prntscr.com/e036ox
Ale provede se to samé, jako při načtení stránky.
Kde dělám chybu ?
Pokud odstraním z formuláře class ajax vše funguje jak má
- iNviNho
- Člen | 352
Skús pozrieť v chrome cez developer consolu network, či naozaj po stlačení submit tlačídla sa posiela niečo na server.
Mal by si tam vidieť tvoj link a za nim niečo ako URL&do=addToBasketForm…
Taktiež ešte skontroluj či po submitnutí ti nevyhodí v console nejaký error.
Editoval iNviNho (25. 1. 2017 12:56)
- andros
- Člen | 145
class ajax přidávám v továrničce formuláře:
$form->getElementPrototype()->class('ajax');
pokud ho přidám přímo do formuláře přímo na button, udělá se klasický redirect
Konsole žádnou chybu nevyhodí
v Network se po kliknutí pošle na server url adresa aktuální stránky, bez
dalších parametrů, takže jako kdyby se stránka načetla znova
- CZechBoY
- Člen | 3608
Včera/dneska jsem psal, že je potřeba to mít v action metodě :-) prácí s šablonou samozřejmě nechej v render metodě.
private $product;
public function actionDefault()
{
$this->product = $this->productManager->getProduct();
}
public function renderDefault()
{
$this->template->product = $this->product;
}
- andros
- Člen | 145
I když to přesunu do metody actionDefault, problém je pořád stejný
Celý presenter vypadá takto:
<?php
namespace FrontModule;
use Nette\Application\UI\Form;
use App\Model\CategoryManager;
use App\Model\ProductManager;
class ProductPresenter extends BasePresenter
{
private $productManager;
private $categoryManager;
private $product;
/**
* @var $categoryId
*
*/
private $categoryId;
private $categories;
public function __construct(ProductManager $productManager, CategoryManager $categoryManager )
{
parent::__construct();
$this->productManager = $productManager;
$this->categoryManager = $categoryManager;
}
public function renderDefault($id)
{
$this->template->product = $this->product;
/**
* ID defaultní kategorie produktu (pokud neexistuje defaultní kategorie , použije se první nalezená
*/
$this->template->categoriesBreadcrumb = $this->categories;
$this->template->stock = $this->product->ref('stock', 'stock_id')->name;
$this->template->stock_label = $this->product->ref('stock', 'stock_id')->label_type;
$this->template->producer = $this->product->ref('prod_producer', 'producer_id')->name;
$this->template->images = $this->product->related('prod_images');
$this->template->image_default = $this->product->related('prod_images')->where('default_img', '1')->fetch();
}
public function actionDefault($id)
{
$this->product = $this->productManager->getProduct()
->where('active',1)
->get($id);
if (!$this->product) {
$this->error('Produkt nebyl nalezen!');
}
$this->categoryId = $this->product->related('prod_cat')->where('default','1')->fetch();
if (!$this->categoryId) {
$this->categoryId = $this->product->related('prod_cat')->limit(1)->fetch();
}
$this->categories = $this->getCategoriesParentName($this->categoryId->category_id);
krsort($this->categories);
}
protected function createComponentAddToBasketForm()
{
$form = new Form;
$form->getElementPrototype()->class('ajax');
$form->addText('quantity', 'Počet ks:');
$form->addHidden('prod_id');
$form->addHidden('guest_id');
$form->addHidden('name');
$form->addHidden('price');
$form->setDefaults([
'quantity' => 1,
'prod_id' => $this->product['id'],
'name' => $this->product['name'],
'price' => $this->product['d1']
]);
$form->addSubmit('send', 'Do košíku');
$form->onSuccess[] = [$this, 'AddToBasketFormSucceeded'];
return $form;
}
public function AddToBasketFormSucceeded($form, $values)
{
$this->productManager->insertProduct([
'quantity' => $values->quantity,
'prod_id' => $values->prod_id,
'guest_id' => $this->getHttpRequest()->getCookie('guest'),
'name' => $values->name,
'price' => $values->price
]);
$this->flashMessage('Přidali jste zboží do košíku', 'success');
if (!$this->isAjax())
$this->redirect('Product:default', array("id" => $values->prod_id));
else {
$this->redrawControl('flash');
}
}
}
- CZechBoY
- Člen | 3608
- Nástroje pro vývojáře (třeba přes pravej klik někam do stránky, poslední položka Revize prvku)
- záložka Network/Síť
- vyfiltruj XHR
- klikni na tlačítko ve formuláři
- měl by se ti tam objevit jeden http požadavek, klikni na něj
- zkopíruj http hlavičky i parametry pro požadavek i odpověď
- přepni na záložku Response/Odpověď a pak sem napiš jestli to je json (pošli) nebo html
- andros
- Člen | 145
Takže:
Request URL:http://localhost/playhracky3/www/product/10230
Request Method:GET
Status Code:200 OK
Remote Address:127.0.0.1:80
Response Headers
view source
Cache-Control:no-store, no-cache, must-revalidate
Connection:Keep-Alive
Content-Encoding:gzip
Content-Length:6645
Content-Type:text/html; charset=utf-8
Date:Wed, 25 Jan 2017 13:29:31 GMT
Expires:Thu, 19 Nov 1981 08:52:00 GMT
Keep-Alive:timeout=5, max=100
Pragma:no-cache
Server:Apache/2.2.31 (Win32) DAV/2 mod_ssl/2.2.31 OpenSSL/1.0.2e mod_fcgid/2.3.9 mod_wsgi/3.4 Python/2.7.6 PHP/7.0.9 mod_perl/2.0.8 Perl/v5.16.3
Set-Cookie:PHPSESSID=9dtm5fd55auqrscdlt212edqm0; expires=Wed, 08-Feb-2017 13:29:31 GMT; Max-Age=1209600; path=/; HttpOnly
Vary:X-Requested-With,Accept-Encoding
X-Frame-Options:SAMEORIGIN
X-Powered-By:Nette Framework
X-Tracy-Ajax:1
Request Headers
view source
Accept:*/*
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:cs-CZ,cs;q=0.8
Connection:keep-alive
Cookie:Phpstorm-f1db6934=37031b54-37ac-4adb-97c5-b4368090fd7c; guest=58813b0babe94; PHPSESSID=9dtm5fd55auqrscdlt212edqm0
Host:localhost
Referer:http://localhost/playhracky3/www/product/10230
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
X-FireLogger:1.3
X-Requested-With:XMLHttpRequest
X-Tracy-Ajax:59591ff4e7
V záložce response je html celé stránky.
- andros
- Člen | 145
připadá mi, že je to podobný problém jako tady: https://forum.nette.org/…lar-s-ajaxem
- andros
- Člen | 145
zkusil jsem místo formuláře v šabloně vypsat formulář
{control addToBasket}
a konzole vyhodi chybu:
Uncaught ReferenceError: Nette is not defined
at Object.before (nette.ajax.js:318)
at Function.<anonymous> (nette.ajax.js:42)
at Function.each (jquery.js:371)
at Object.fire (nette.ajax.js:40)
at Object.settings.beforeSend (nette.ajax.js:215)
at Function.ajax (jquery.js:8614)
at nette.ajax (nette.ajax.js:225)
at HTMLInputElement.requestHandler (nette.ajax.js:48)
at HTMLFormElement.dispatch (jquery.js:4737)
at HTMLFormElement.elemData.handle (jquery.js:4549)
- andros
- Člen | 145
Tak po mnoha pokusech pokus – omyl jsem nakonec se mi to nakonec povedlo rozhýbat :)
Chyby jsem tam měl dvě
ve formuláři jsem měl
<button class="btn btn-primary">
</button>
Ono to chce ale
<button n:name=send class="btn btn-primary">
</button>
a nenačítal jsem scrip netteForms.min.js bez kterého se to neobejde. Protože ve formuláři nemám validaci, mysel jsem že je tento script zbytečný. Ovšem nette.ajax.js se bez něj prostě neobejde
- andros
- Člen | 145
Když už mi funguje odesílání formuláře ajaxem, snažím se přidat spinner, aby bylo vidět, že se něco děje, než se požadavek zpracuje.
v @layout.latte jsem přidal před inicializaci $.nette.init();
<script src="{$basePath}/js/extensions/spinner.ajax.js"></script>
do css jsem dal
#ajax-spinner {
position: fixed;
width: 32px;
height: 32px;
/* - use if you use bacground image, no ico */
background: url('../img/ajax-loader.gif') no-repeat;
z-index: 123456;
color: green;
}
Ale spinner se ne a ne objevit :)
Když to spinner.ajax.js přidám na zkoušku alert (např.)
start: function () {
this.counter++;
if (this.counter === 1) {
this.spinner.show(this.speed);
alert('test');
}
},
Tak po kliknutí na tlačítko formuláře se mi alert okno zobrazí, takže by to mělo fungovat. Ale nastylovaný spinner se nezobrazí.
Poradíte mi prosím někdo ?
- novasol
- Člen | 1
Jen doplňující informaci, snad to někomu pomůže. Po pěti hodinách jsem zjistil, že hned pod namespace v presenteru používám
use Nette\Forms\Form;
namísto správného
use Nette\Application\UI\Form;
Dejte si na to pozor! Jinak Vám AJAX pojede, ale nebude se volat callback v presenteru a pokaždé bude response komplet stránka, resp. funkce renderDefault() !
Editoval novasol (17. 5. 2018 21:24)