Autor Zpráva
KarelEben
Profil
Zdravím,

v současné době dělám na jednom projektu a teď se vstekám s formulářem.
Má to dělat to že po kliknutí na add v formuláří addMealBlockForm se AJAXem odešlou data do db a znova se překreslí do snippetu listDietGroups a jako položky v mealBlock v addMealForm. Dále se má po odeslání formuláře addMealForm překreslit listDietGroups. Na serveru používáme Doctrine.
Šablona:
<div class="meal-bar edit">
                        {snippet addMealBlock}
                            {form addMealBlockForm, class => "meal-form ajax"}
                                <div class="row">
                                    {input mealBlock, class => "meal-headline required"}
                                    {input add, class => "no-button add-item add-block to-left"}
                                </div>
                            {/form}
                        {/snippet}
                        {snippet addMeal}
                            {form addMealForm, class => "last meal-form ajax"}
                                <div class="row">
                                    {input mealName, class => "name required"}
                                    {input moreInfo, class => "more-info"}
                                    {input mealBlock}
                                    {input add, class => "no-button add-item add-meal"}
                                    {input price, class => "price required"}
                                    <div class="error" n:if="$form['price']->getError()">{_$form['price']->getError()}</div>
                                </div>
                            {/form}
                        {/snippet}
                            <div class="required-info">{_admin.settings.meal-list.required-info}</div>
                        {snippet listDietGroups}
                            <div class="generated">
                                {foreach $company->dietGroups as $dietGroup}
                                    <div class="meal-block" id="MB_{$dietGroup->id}">
                                        <div class="meal-headline">{$dietGroup->name}<a class="ajax" n:href="deleteMealBlock!, id => $dietGroup->id"><span class="delete delete-block"></span></a></div>
                                        {foreach $dietGroup->dietItems as $dietItem}
                                            <div class="meal">
                                                <span class="name">{$dietItem->name}</span>
                                                <span class="more-info">{$dietItem->description}</span>
                                                <a class="ajax" n:href="deleteMeal!, id => $dietItem->id"><span class="delete"></span></a>
                                                <span class="price">{$dietItem->price},-</span>
                                            </div>
                                        {/foreach}
                                    </div>
                                {/foreach}
                            </div>
                        {/snippet}
                    </div>

Presenter:
/**
     * @var DietGroupFacade
     * @inject
     */
    public $dietGroupFacade;

    /**
     * @var CompanyFacade
     * @inject
     */
    public $companyFacade;
    .
    .

    public function renderDefault()
    {
        $this->template->company = $this->company;
    .
    .

    }

    .
    .
    .

    public function createComponentAddMealBlockForm()
    {
        $form = new Form;
        $form->setTranslator($this->translator);

        $form->addText('mealBlock')
        ->setAttribute('placeholder', 'admin.settings.meal-list.category-name')
        ->setRequired('common.form.fill');

        $form->addSubmit('add', '');

        $form->onSuccess[] = $this->addMealBlockFormSucceeded;

        return $form;
    }

    public function addMealBlockFormSucceeded(Form $form)
    {
        $values = $form->getValues();
        $this->dietGroupFacade->addDietGroup($values->mealBlock, $this->company);

        $this->flashMessage('common.database.operation-success', FlashMessage::GOOD);
        if($this->isAjax()) {
            $this->redrawControl('flash-message');
            $this->redrawControl('addMeal');
            $this->redrawControl('listDietGroups');
            $form->setValues(array(), TRUE);
        } else {
            $this->redirect('this');
        }
    }


    public function handleDeleteMealBlock($id)
    {
        $this->dietGroupFacade->deleteDietGroup($id, $this->company);

        $this->flashMessage('common.database.operation-success', FlashMessage::GOOD);
        //$this->redirect('this#meal-list');
            $this->redrawControl('flash-message');
            $this->redrawControl('add-meal-block-form-edit');
    }


    public function createComponentAddMealForm()
    {
        $form = new Form;
        $form->setTranslator($this->translator);

        $form->addText('mealName')
        ->setAttribute('placeholder', 'admin.settings.meal-list.meal')
        ->setRequired('common.form.fill');
        $form->addText('moreInfo')
        ->setAttribute('placeholder', 'admin.settings.meal-list.simple-discription');
        $form->addText('price')
            ->addRule(Form::FLOAT, 'admin.settings.meal-list.price-num')
        ->setAttribute('placeholder', 'admin.settings.meal-list.price')
        ->setRequired('common.form.fill');

        $mealBlocks = array();
        foreach ($this->company->dietGroups as $dietGroup) {
            $mealBlocks[$dietGroup->id] = $dietGroup->name;
        }

        $form->addSelect('mealBlock', '', $mealBlocks)
        ->setPrompt('admin.settings.meal-list.choose-group')
        ->setRequired('common.form.fill');
        $form->addSubmit('add', '');

        $form->onSuccess[] = $this->addMealFormSucceeded;

        return $form;
    }


    public function addMealFormSucceeded(Form $form)
    {
        $values = $form->getValues();
        $dietGroup = $this->dietGroupFacade->getDietGroupById($values->mealBlock);
        $this->dietItemFacade->addDietItem( $values->mealName, $dietGroup, $values->price, $values->moreInfo);

        $this->flashMessage('common.database.operation-success', FlashMessage::GOOD);
        //$this->redirect('this#meal-list');
        if($this->isAjax()) {
            $this->redrawControl('flash-message');
            $this->redrawControl('addMeal');
            $this->redrawControl('listDietGroups');
            $form->setValues(array(), TRUE);
        } else {
            $this->redirect('this');
        }
    }


    public function handleDeleteMeal($id)
    {
        $this->dietItemFacade->deleteDietItem($id, $this->company);

        $this->flashMessage('common.database.operation-success', FlashMessage::GOOD);
        //$this->redirect('this#meal-list');
        $this->redrawControl('flash-message');
        $this->redrawControl('add-meal-block-form-edit');
    }


Javascript:
<script type="text/javascript">
    .
    .
    .
$(function () {
    $.nette.init();
});
    .
    .
    .
</script>
Máme nasazený nette.ajax.js
Bohužel se nezobrazí žádná chyba, žádná exception ani v konzoli, nikde...
Jan Tvrdík
Profil
A co to tedy dělá? Co vrací server jako odpověď na to odeslání formuláře? Posíláš ten formulář určitě AJAXem? Jak vypadá ten požadavek?
KarelEben
Profil
Tak menší změna kodu.
Presenter:
public function actionDefault()
    {    
        $this->redrawControl('addMeal');
        $this->redrawControl('listDietGroups');
        $this->redrawControl('addMealBlock');
    }


    public function renderDefault()
    {
        $this->template->company = $this->company;
        $this->template->attributes = $this->attributeFacade->getAttributes();
        $this->template->activeAttributes = $this->company->getAttributesPairs();
        
    }
public function addMealBlockFormSucceeded(Form $form)
    {
        $values = $form->getValues();
        $this->dietGroupFacade->addDietGroup($values->mealBlock, $this->company);

        $this->flashMessage('common.database.operation-success', FlashMessage::GOOD);
        if($this->isAjax()) {
            $form->setValues(array(), TRUE);
        } else {
            $this->redirect('this');
        }
    }


    public function handleDeleteMealBlock($id)
    {
        $this->dietGroupFacade->deleteDietGroup($id, $this->company);

        $this->flashMessage('common.database.operation-success', FlashMessage::GOOD);
        //$this->redirect('this#meal-list');
            $this->redrawControl('flash-message');
            $this->redrawControl('add-meal-block-form-edit');
    }


    public function createComponentAddMealForm()
    {
        $form = new Form;
        $form->setTranslator($this->translator);

        $form->addText('mealName')
        ->setAttribute('placeholder', 'admin.settings.meal-list.meal')
        ->setRequired('common.form.fill');
        $form->addText('moreInfo')
        ->setAttribute('placeholder', 'admin.settings.meal-list.simple-discription');
        $form->addText('price')
            ->addRule(Form::FLOAT, 'admin.settings.meal-list.price-num')
        ->setAttribute('placeholder', 'admin.settings.meal-list.price')
        ->setRequired('common.form.fill');

        $mealBlocks = array();
        foreach ($this->company->dietGroups as $dietGroup) {
            $mealBlocks[$dietGroup->id] = $dietGroup->name;
        }

        $form->addSelect('mealBlock', '', $mealBlocks)
        ->setPrompt('admin.settings.meal-list.choose-group')
        ->setRequired('common.form.fill');
        $form->addSubmit('add', '');

        $form->onSuccess[] = $this->addMealFormSucceeded;

        return $form;
    }


    public function addMealFormSucceeded(Form $form)
    {
        $values = $form->getValues();
        $dietGroup = $this->dietGroupFacade->getDietGroupById($values->mealBlock);
        $this->dietItemFacade->addDietItem( $values->mealName, $dietGroup, $values->price, $values->moreInfo);

        $this->flashMessage('common.database.operation-success', FlashMessage::GOOD);
        //$this->redirect('this#meal-list');
        if($this->isAjax()) {
            $this->redrawControl('flash-message');
            $this->redrawControl('addMeal');
            $this->redrawControl('listDietGroups');
            $form->setValues(array(), TRUE);
        } else {
            $this->redirect('this');
        }
    }


    public function handleDeleteMeal($id)
    {
        $this->dietItemFacade->deleteDietItem($id, $this->company);

        $this->flashMessage('common.database.operation-success', FlashMessage::GOOD);
        //$this->redirect('this#meal-list');
        $this->redrawControl('flash-message');
        $this->redrawControl('add-meal-block-form-edit');
    }

a view:
{snippet addMealBlock}
                            {form addMealBlockForm, class => "meal-form ajax"}
                                <div class="row">
                                    {input mealBlock, class => "meal-headline required"}
                                    {input add, class => "no-button add-item add-block to-left"}
                                </div>
                            {/form}
                        {/snippet}
                        {snippet addMeal}
                            {form addMealForm, class => "last meal-form ajax"}
                                <div class="row">
                                    {input mealName, class => "name required"}
                                    {input moreInfo, class => "more-info"}
                                    {input mealBlock}
                                    {input add, class => "no-button add-item add-meal"}
                                    {input price, class => "price required"}
                                    <div class="error" n:if="$form['price']->getError()">{_$form['price']->getError()}</div>
                                </div>
                            {/form}
                        {/snippet}
                            <div class="required-info">{_admin.settings.meal-list.required-info}</div>
                        {snippet listDietGroups}
                            <div class="generated">
                                {foreach $company->dietGroups as $dietGroup}
                                    <div class="meal-block" id="MB_{$dietGroup->id}">
                                        <div class="meal-headline">{$dietGroup->name}<a class="ajax" n:href="deleteMealBlock!, id => $dietGroup->id"><span class="delete delete-block"></span></a></div>
                                        {foreach $dietGroup->dietItems as $dietItem}
                                            <div class="meal">
                                                <span class="name">{$dietItem->name}</span>
                                                <span class="more-info">{$dietItem->description}</span>
                                                <a class="ajax" n:href="deleteMeal!, id => $dietItem->id"><span class="delete"></span></a>
                                                <span class="price">{$dietItem->price},-</span>
                                            </div>
                                        {/foreach}
                                    </div>
                                {/foreach}
                            </div>
                        {/snippet}

Po této změně se to po načtení první odeslání formuláře nepošle a podruhe a dál jo


Jan Tvrdík:
Jinak první request:
mealBlock=&do=addMealBlockForm-submit&add=&
Druhý reguest:
mealBlock=Ty&do=addMealBlockForm-submit&add=&

Nechápu proč se do toho reguestu nedá obsah toho formu poprvé -.-
Dělal jsem DIFF formuláře po vykreslení i potom jak to funguje a žádná změna
Jan Tvrdík
Profil
Nechápu proč se do toho reguestu nedá obsah toho formu poprvé
Tak si debugni ten JS, ne?
KarelEben
Profil
Jan Tvrdík:
Ano posílám


Jan Tvrdík:
Jak přesně, ted Vás nechápu jak.
Jan Tvrdík
Profil
KarelEben:
developer.chrome.com/devtools/docs/javascript-debugging
KarelEben
Profil
Tak ted vás nechápu již vůbec :( Jako skoušel jsem to debugovat pomocí konzole ale prostě se to odešle. Ale žádná data v tom inputu prej nejsou teda aspon se neposílají
Jan Tvrdík
Profil
KarelEben:
Obecná strategie řešení problému s Ajaxem, snipetty a Nette je, že se nejprve koukneš na průběh HTTP komunikace a zjistíš, která strana udělala chybu jako první (buď klient nebo server). Následně se podíváš na zdrojový kód klienta resp. serveru a buď tě napadne, proč k té chybě dochází, nebo použiješ debugger. Pokud je problém se ve zdrojových kódech vyznat, tak chybu postupně izoluješ odmazáváním kódu, který nemá na chování vliv. Žádné složitosti v tom nejsou.
Toto téma je uzamčeno. Odpověď nelze zaslat.