Formulář s dependent selectem se nezpracuje

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
ch4rli3
Člen | 6
+
0
-

Nette 2.0.10
PHP 5

Ahoj,
podle kuchařky jsem napsal formulář a obsluhu multiple dependent select – tohle funguje přesně jak chci. Nicméně narazil jsem na trochu jiný problém. Když fomrulář odešlu tak mi hlásí, že u těch závislých selectů nemám vyplněné hodnoty.

Takto vypadá moje komponenta na vytváření formuláře:

protected function createComponentClientForm()
    {
        $cityPairs = $this->locationRepository->getCities()->fetchPairs('id','mesto');
        $form = new Form();

        $form->addText('jmeno', 'Klient:',40,100)
             ->addRule(Form::FILLED, 'Je nutné vyplnit jméno zákazníka');

        $form->addText('ip', 'IP Adresa:',40,100)
             ->addRule(Form::FILLED, 'Je nutné vyplnit IP zákazníka')
                ->addRule(Form::REGEXP, "Zadejte správný tvar IP", '/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/');

        $form->addSelect('cityId', 'Město:', $cityPairs)
             ->setPrompt('- Vyberte město -')
             ->addRule(Form::FILLED, 'Je nutné vybrat město');

        $form->addSelect('streetId', 'Ulice:')
             ->setPrompt('- Nejdříve vyberte město -')
             ->addRule(Form::FILLED, 'Je nutné vybrat ulici');

        $form->addSelect('locationId', 'Číslo popisné:')
             ->setPrompt('- Nejdříve vyberte město -')
             ->addRule(Form::FILLED, 'Je nutné vybrat číslo popisné');

        $form->addSubmit('create','Pokračovat');

        $form->onSuccess[] = $this->clientFormAccepted;
        return $form;
    }

a takto vypadá můj latte soubor:

{define content}
<fieldset>
    <legend>Přidat Klienta</legend>

    {form clientForm}
    {control $form errors}
    <table class="nostyle">
        <tr>
            <td>{label jmeno /}</td>
            <td>{input jmeno }</td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td>{label ip /}</td>
            <td>{input ip }</td>
            <td></td>
            <td></td>
        </tr>
        <tr n:snippet="secondSnippet">
            <td>{label cityId /}</td>
            <td>{input cityId }</td>
            <td>{label streetId /}</td>
            <td>{input streetId}</td>
            <td>{label locationId /}</td>
            <td n:snippet="thirdSnippet">{input locationId}</td>
            {include #js}
        </tr>
        <tr>
            <td></td>
            <td>{input create }</td>
            <td></td>
            <td></td>
        </tr>
    </table>

    {/form}
</fieldset>
{define #js}
<script>
{include #jsCallback, input => cityId, link => getStreets}
{include #jsCallback, input => streetId, link => getCP}
</script>
{/define}


{define #jsCallback}

$('#{$control["clientForm"][$input]->htmlId}').on('change', function() {

    $.nette.ajax({
        type: 'GET',
        url: '{link {$link}!}',
        data: {
            'value': $(this).val(),
        }
    });
});

{/define}
{/define}

Samotné závislosti selectů fungují, ale formulář se správně neodešle. hlásí to pořád že nemám vyplněnou hodntou u ulice a čísla popisného :( co dělám špatně? Díky

ch4rli3
Člen | 6
+
0
-

OK vyřešil jsem to nakonec sám. Pravidla pro nutnost vyplnění selectů streetId a locationId jsem přesunul aby se přidali až v jednotlivých handlech. Kód tedy vypadá takto:

Komponenta formuláře:

protected function createComponentClientForm()
    {
        $cityPairs = $this->locationRepository->getCities()->fetchPairs('id','mesto');
        $form = new Form();

        $form->addText('jmeno', 'Klient:',40,100)
             ->addRule(Form::FILLED, 'Je nutné vyplnit jméno zákazníka');

        $form->addText('ip', 'IP Adresa:',40,100)
             ->addRule(Form::FILLED, 'Je nutné vyplnit IP zákazníka')
                ->addRule(Form::REGEXP, "Zadejte správný tvar IP", '/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/');

        $form->addSelect('cityId', 'Město:', $cityPairs)
             ->setPrompt('- Vyberte město -')
             ->addRule(Form::FILLED, 'Je nutné vybrat město');

        $form->addSelect('streetId', 'Ulice:')
             ->setPrompt('- Nejdříve vyberte město -');


        $form->addSelect('locationId', 'Číslo popisné:')
             ->setPrompt('- Nejdříve vyberte město -');

        $form->addSubmit('create','Pokračovat');

        $form->onSuccess[] = $this->clientFormAccepted;
        return $form;
    }

latte soubor:

{define content}
<fieldset>
    <legend>Přidat Klienta</legend>

    {form clientForm}
    {control $form errors}
    <table class="nostyle">
        <tr>
            <td>{label jmeno /}</td>
            <td>{input jmeno }</td>
            <td></td>
            <td></td>
        </tr>
        <tr>
            <td>{label ip /}</td>
            <td>{input ip }</td>
            <td></td>
            <td></td>
        </tr>
        <tr n:snippet="secondSnippet">
            <td>{label cityId /}</td>
            <td>{input cityId }</td>
            <td>{label streetId /}</td>
            <td>{input streetId}</td>
            <td>{label locationId /}</td>
            <td n:snippet="thirdSnippet">{input locationId}</td>
            {include #js}
        </tr>
        <tr>
            <td></td>
            <td>{input create }</td>
            <td></td>
            <td></td>
        </tr>
    </table>

    {/form}
</fieldset>
{define #js}
<script>
{include #jsCallback, input => cityId, link => getStreets}
{include #jsCallback, input => streetId, link => getCP}
</script>
{/define}


{define #jsCallback}

$('#{$control["clientForm"][$input]->htmlId}').on('change', function() {

    $.nette.ajax({
        type: 'GET',
        url: '{link {$link}!}',
        data: {
            'value': $(this).val(),
        }
    });
});

{/define}
{/define}

handly:

public function handleGetStreets ($value)
    {

        $streetPairs = $this->locationRepository->getStreets($value)->fetchPairs('id','ulice');
        $this['clientForm']['cityId']->setDefaultValue($value);
        $this['clientForm']['streetId']->setPrompt('- Vyberte ulici -')
                ->setItems($streetPairs)
                ->addRule(Form::FILLED, 'Je nutné vybrat ulici');
        $this['clientForm']['locationId']->setPrompt('- Nejdříve vyberte ulici -');
        $this->invalidateControl('secondSnippet');

    }

    public function handleGetCP ($value)
    {
        $cpPairs = $this->locationRepository->getCP($value)->fetchPairs('id','cp');
        $this['clientForm']['locationId']->setPrompt('- Vyberte číslo popisné -')
                ->setItems($cpPairs)
             ->addRule(Form::FILLED, 'Je nutné vybrat číslo popisné');
        $this->template->form = $this->template->_form = $this['clientForm'];
        $this->invalidateControl('thirdSnippet');
    }

Zpracování formuláře:

public function clientFormAccepted(Form $form)
    {
        $values = $form->getHttpData();
        $response = $this->clientRepository->addClient($values);
        $this->flashMessage($response->message, $response->type);
        $this->redirect('this');
    }

Dávám to tu záměrně vše protože by to mohlo snad někomu mohlo pomoct jak řešit problematiku závislých selectů.

Editoval ch4rli3 (19. 6. 2013 8:37)

TeeBee87
Člen | 14
+
0
-

Já jsem si to upravil tak, že si ty hodnoty dotáhnu při vytváření formuláře. Akorát ten formulář musí být připojený, aby šlo použít getHttpData.

<?php


public function __construct(IContainer $parent, $name, EntityManager $em)
{
	parent::__construct($parent, $name);
	$this->em = $em;

	$this->addEntitySelect('eventType', 'Event type', $this->em->getDao(EventType::getClassName())->findAll())
		->setPrompt('Select')
		->addRule(self::FILLED);

	$this->addEntitySelect("competition", "Competition")
		->setPrompt('Select event')
		->addRule(AddBetForm::FILLED);

	$this->addEntitySelect("event", "Event")
		->setPrompt('Select competition')
		->addRule(AddBetForm::FILLED);

	if ($this->getHttpData('eventType')) {
		$this->eventTypeChange($this->getHttpData('eventType'));
	}

	if ($this->getHttpData('competition')) {
		$this->competitionChange($this->getHttpData('competition'));
	}

	$this->addSubmit('submit', 'front.forms.save');
}



public function eventTypeChange($value)
{
	if ($value) {

		$this['competition']
			->setPrompt('Select')
			->setItems($this->em->getDao(Competition::getClassName())->findBy(['eventType' => $value]));

	} else {
		$this['competition']
			->setPrompt('Select from event type')
			->setItems(array());
	}

	$this['event']
		->setPrompt('Select from competition')
		->setItems(array());
}



public function competitionChange($value)
{
	if ($value) {
		$this['event']
			->setPrompt('Select')
			->setItems($this->em->getDao(Event::getClassName())->findBy(['competition' => $value]));

	} else {
		$this['event']
			->setPrompt('Select from competition')
			->setItems(array());
	}
}


// A v presenteru:

protected function createComponentAddBetForm($name)
{
	$form = new AddBetForm($this, $name, $this->em);
	$form->onSuccess[] = $this->addBet;
	return $form;
}



public function addBet(AddBetForm $form)
{
	....
	$this->redirect('this');
}



public function handleEventTypeChange($value)
{
	$this['addBetForm']->eventTypeChange($value);
	$this->redrawControl('competition');
}



public function handleCompetitionChange($value)
{
	$this['addBetForm']->competitionChange($value);
	$this->redrawControl('event');
}

?>