Jak odeslat URL parameter ve formulari

MrAndy
Člen | 10
+
0
-

Dobry den,
mam formular na multilanguage webu

protected function createComponentManageQuestion(): Form
    {
        $form = new Form();
        $form->addHidden('locale',$this->translator->getLocale());
        $form->addHidden('object',0);
        $form->addTextArea('question');
        $form->addTextArea('explanation');
        $form->addSubmit('sendForm')->setHtmlAttribute('id','sendForm');
        $form->addSubmit('sendFormApprove')->setHtmlAttribute('id','sendFormApprove');;
        $form->onSuccess[] = [$this, 'saveQuestionAndAnswers'];
        return $form;

    }

parameter locale standartne predavam pres url $this->link(‚Question:manage‘, [$question->id, ‚locale‘ ⇒ $this->locale]).
Vychozi jazyk je CS, kdyz odeslu formular s EN verze tak se vzdy odesle na default.

Jde mu nejak predat ten parameter locale, jinak nez resenim v hidden inputu?

Dekuji

MajklNajt
Člen | 471
+
0
-

otázkou je, na čo potrebuješ locale posielať? nie je jednoduchšie si ho vytiahnuť až v saveQuestionAndAnswers?

MrAndy
Člen | 10
+
0
-

MajklNajt napsal(a):

otázkou je, na čo potrebuješ locale posielať? nie je jednoduchšie si ho vytiahnuť až v saveQuestionAndAnswers?

zpracovani v ‚saveQuestionAndAnswers‘ je spise nouze.
Jde o to ze locale pro web beru z routeru, takze kdyz jsem na url /en/manage a odeslu formular tak se mi odesle na /namage a tim padem se mi prepne web do default locale a ja to pak musim zbytecne osetrovat podruhe.

nightfish
Člen | 472
+
0
-

MrAndy napsal(a):
kdyz jsem na url /en/manage a odeslu formular tak se mi odesle na /manage

Tohle mi přijde jako hlavní problém – potřebuješ se dostat do stavu, kdy se ti formulář odešle na /en/manage. Obvykle se to děje automaticky. Pokud ne, tak buď někde natvrdo nastavuješ /manage a nebo ti nefunguje správně router (v takovém případě ideálně dodej ukázku svých routovacích pravidel).

MrAndy
Člen | 10
+
0
-

nightfish napsal(a):

MrAndy napsal(a):
kdyz jsem na url /en/manage a odeslu formular tak se mi odesle na /manage

a nebo ti nefunguje správně router (v takovém případě ideálně dodej ukázku svých routovacích pravidel).

priznam se ze to je zcela mozne, s routerem jeste nejsem kamarad

	public static function createRouter(): RouteList
	{
		$router = new RouteList;

        $router->addRoute('[<locale=cs cs|en>/]panel/<presenter>/<action>[/<id>]', 'Panel:Home:default');
        $router->addRoute('[<locale=cs cs|en>/]<presenter>/<action>[/<id>]', 'Home:default');
		return $router;
	}
m.brecher
Generous Backer | 736
+
0
-

@MrAndy

Vychozi jazyk je CS, kdyz odeslu formular s EN verze tak se vzdy odesle na default. Jde mu nejak predat ten parameter locale, jinak nez resenim v hidden inputu?

Ano, na podobný problém narazí časem každý – není jednoduché pochopit jak donutit formulář aby v URL konkrétně v atributu action poslal nějaké parametry. Lidi pak ze zoufalství cpou parametry do input hidden. Lepší je akceptovat koncepci signálů Nette a nejít proti srsti.

Nette je poměrně striktní co se týče signálů komponent a formulářů. Signál lze odesílat POUZE A JEDINĚ na aktuálním requestu. Co je to aktuální request? Ten je odvozen z url které dorazilo na server. Patří tam modul, presenter, action a některé parametry, ale ne všechny. Jenom tzv. parametry akce – tedy parametry které si do některé z metod akce v presenteru napíšeme:

public function actionUpdate(int $id)  // toto $id je parametr započítaný do aktuálního requestu
{
    .......
}

Takže stručně řečeno je aktuální request:

aktuální presenter
aktuální akce
parametry uvedené v některé z metod akce

Navíc do aktuálního requestu, která signály respektují patří PERSISTENTNÍ parametry které se definují v presenteru

    use Nette\Application\Attributes\Persistent;  // bacha!! tohle tam musí být

    class MyPresenter extends Presenter
    {
	    #Persistent
        public string $lang = 'cs';  // bacha !! musí být public, jinak to nefunguje !!
    }

Takže ideální v Tvém případě je definovat si $lang jako persistentní parametr. Ale bacha, definuj ho v plném rozsahu platnosti v aplikaci, tedy ideálně v BasePresenteru, což je abstraktní předek všech presenterů a ostatní final presentery z něj dědí. Nebo budeš muset ručně deklarovat persistentní parametr ve VŠECH presenterech, což je spousty práce a to přece nechceš :).

Editoval m.brecher (24. 3. 2023 15:08)

m.brecher
Generous Backer | 736
+
0
-

@nightfish

Tohle mi přijde jako hlavní problém – potřebuješ se dostat do stavu, kdy se ti formulář odešle na /en/manage. Obvykle se to děje automaticky. Pokud ne, tak buď někde natvrdo nastavuješ /manage a nebo ti nefunguje správně router (v takovém případě ideálně dodej ukázku svých routovacích pravidel).

Tohle určitě není problém routeru, ale striktní implementace signálů v Nette. Jediný rozumný způsob je nastavit parametr $lang jako persistentní napříč všemi presentery. Pak je to úplně jednoduché.

MrAndy
Člen | 10
+
0
-

m.brecher napsal(a):

@MrAndy

Takže ideální v Tvém případě je definovat si $lang jako persistentní parametr. Ale bacha, definuj ho v plném rozsahu platnosti v aplikaci, tedy ideálně v BasePresenteru, což je abstraktní předek všech presenterů a ostatní final presentery z něj dědí. Nebo budeš muset ručně deklarovat persistentní parametr ve VŠECH presenterech, což je spousty práce a to přece nechceš :).

locale mam definovane „globalne“
ale kdyz se kouknu do form action tak vidim ze odkazuje na adresu bez locale,

muj BasePresenter

<?php declare(strict_types = 1);

namespace App;

use Nette;
use Contributte;

abstract class BasePresenter extends Nette\Application\UI\Presenter
{
    public $locale;

    /** @var Nette\Localization\ITranslator @inject */
    public $translator;

    /** @var Contributte\Translation\LocalesResolvers\Session @inject */
    public $translatorSessionResolver;

    public function __construct(
        Nette\Localization\ITranslator $translator,
    )
    {
        $this->translator = $translator;
    }
    public function beforeRender(){
        parent::beforeRender();
        $this->locale = $this->translator->getLocale();
        $this->template->locale = $this->locale;

    }
}
Kcko
Člen | 465
+
0
-

MrAndy napsal(a):

m.brecher napsal(a):

@MrAndy

Takže ideální v Tvém případě je definovat si $lang jako persistentní parametr. Ale bacha, definuj ho v plném rozsahu platnosti v aplikaci, tedy ideálně v BasePresenteru, což je abstraktní předek všech presenterů a ostatní final presentery z něj dědí. Nebo budeš muset ručně deklarovat persistentní parametr ve VŠECH presenterech, což je spousty práce a to přece nechceš :).

locale mam definovane „globalne“
ale kdyz se kouknu do form action tak vidim ze odkazuje na adresu bez locale,

muj BasePresenter

<?php declare(strict_types = 1);

namespace App;

use Nette;
use Contributte;

abstract class BasePresenter extends Nette\Application\UI\Presenter
{
    public $locale;

    /** @var Nette\Localization\ITranslator @inject */
    public $translator;

    /** @var Contributte\Translation\LocalesResolvers\Session @inject */
    public $translatorSessionResolver;

    public function __construct(
        Nette\Localization\ITranslator $translator,
    )
    {
        $this->translator = $translator;
    }
    public function beforeRender(){
        parent::beforeRender();
        $this->locale = $this->translator->getLocale();
        $this->template->locale = $this->locale;

    }
}

Doplň si persistentní notaci, jak Ti řekl m.brecher, pak se Ti to bude přenášet, ideálně s výchozí hodnotou.

MrAndy
Člen | 10
+
0
-

doplnil jsem to tam
router jsem zmenil na

        $router->withModule('Panel')->addRoute('[<locale=cs cs|en>/]panel/<presenter>/<action>[/<id>]', 'Home:default');
        $router->withModule('Api')->addRoute('[<locale=cs cs|en>/]api/<presenter>/<action>[/<id>]', 'Home:default');
        $router->addRoute('[<locale=cs cs|en>/]<presenter>/<action>[/<id>]', 'Home:default');

a funguje to perfektne, nechapu vubec jak, ale dela to presne to co od toho ocekavam :-)

@mbrecher Diky
@Kcko Diky

Kcko
Člen | 465
+
0
-