Proč po redrawControl() nefunguje formulář?

DrCactus
Člen | 2
+
0
-

Zdravím, mám presenter, ve kterém mám metodu na vytvoření formuláře.

Formulář je pak vyrenderován v šabloně za pomocí {control} tagu, který je obalen ve {snippet}u.

Ve formuláři jsou 2 select boxy a 1 submit button.
Jeden select box je ajaxový, který po změně vyvolá signál do presenteru, ve kterém se aktualizují položky druhého select boxu a který redrawControl()ne snippet.

Má otázka zní jednoduše.
Proč mi po redrawControl()u nejde odeslat formulář nebo-li nespustí se callback ve $form->onSuccess?
Jak toto vyřešit a existuje nějaká lepší alternativa?

(tuším že po redrawu se vytratily bindnutý JS $.nette handlery, ale cpát do snippetu i kousek <script>u mi přijde „neohrabané“)

Kamil Valenta
Člen | 762
+
0
-

Není ten druhý select povinný a bez nabindované JS události nedostane hodnotu? Dump na $form->getErrors() by to prozradil.
Záleží, jakým JS obhospodařuješ snippety, buď si udělej event na afterUpdate, nebo si ten kousek JS do snippetu dej. Možná to trochu „neohrabané“ je, ale třeba s nette.ajax to asi bude nejrychlejší cesta…

DrCactus
Člen | 2
+
0
-

Kamil Valenta napsal(a):

Není ten druhý select povinný a bez nabindované JS události nedostane hodnotu? Dump na $form->getErrors() by to prozradil.
Záleží, jakým JS obhospodařuješ snippety, buď si udělej event na afterUpdate, nebo si ten kousek JS do snippetu dej. Možná to trochu „neohrabané“ je, ale třeba s nette.ajax to asi bude nejrychlejší cesta…

Tady je to komplet.

<script>
	$(document).ready(function(){
		$(document).on('change', '.super-input', function ()
		{
			$.nette.ajax({
				type: 'POST',
				url: $(this).data('super-url'),
				data: {
					'current': $(this).val(),
					'values': jQuery.param(
						$(this).closest('form').find(':input').serializeArray()
					)
				}
			});
		});
	});
</script>

{snippet superFormSnippet}
	{control superForm}
{/snippet}
<?php

declare(strict_types=1);

namespace App\Presenters;

use Nette;
use Nette\Application\UI\Form;
use Nette\Utils\ArrayHash;


final class HomePresenter extends Nette\Application\UI\Presenter
{
    public function ajaxParams( $values, $except = [] )
    {
        $postParams = [];
        $params = [];
        parse_str($values, $postParams);
        foreach($postParams as $key => $value){
            if(in_array($key, $except)) continue;
            $params[$key] = $value === '' ? NULL : $value;
        }
        return $params;
    }

    public function superFormSucceeded(Form $form, ArrayHash $values){
        bdump($values, 'succeeded');
        // při setValidationScope([]) vrací prázdný $values
    }

    public function superFormSubmitted(Form $form){
        bdump($form->getErrors(), 'submitted');
        // když není setValidationScope([])
        // vrací 'Please select a valid option.' pro 'select2'
    }

    public function handleSelect1Changed($current, $values){
        $form          = $this->getComponent('superForm');
        $otherItemName = 'select2';

        $params = $this->ajaxParams( $values, [$otherItemName] );
        $form->setDefaults( $params );

        $otherItems = [NULL => '-'];
        if ( $current ) {
            if($current === '1'){
                $otherItems['test1'] = 'Test1';
            } else if($current === '2'){
                $otherItems['test2'] = 'Test2';
            }
        }

        $form[$otherItemName]->setItems( $otherItems )->setPrompt( '-' );

        $this->redrawControl( 'superFormSnippet' );
    }

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

        $items = [
            '-' => 'Choose',
            '1' => 'First',
            '2' => 'Second'
        ];

        $form->addText('text', 'Text');

        $form->addSelect('select1', 'Select 1', $items)
            ->setHtmlAttribute( 'class', 'super-input' )
            ->setHtmlAttribute( 'data-super-url', $this->link( 'select1Changed!' ) );

        $form->addSelect('select2', 'Select 2', [NULL => '-']);

        $form->addSubmit('submit', 'Submit')->setValidationScope([]);

        $form->onSubmit[] = [$this, 'superFormSubmitted'];
        $form->onSuccess[] = [$this, 'superFormSucceeded'];

        return $form;
    }
}

Editoval DrCactus (10. 5. 2023 11:10)