formát URL handle komponenty

d@rkWolf
Člen | 163
+
0
-

Prosím, poradil by někdo? Vytvořil jsem si komponentu k zobrazování mapy(potřebuju ju trochu upravenou zobrazit na 2 místech) a mám problém s url, co vytváří handle v té komponentně. Linky, co se vytvoří v šabloně komponenty vypadají takto:

domena/contact?mapsComponent-slug=australia&do=mapsComponent-Country

  1. Jak tu generovanou adresu upravit na něco normálního(nejlíp tak jenom ?country=australia)? Nedaří se mi na nic přijít, zkoušel sem to nějak vložit do routru, ale buď to neudělalo nic, nebo to crashlo… Mám to nastavené při kliku na provádění ajaxem(Naja) a takto se mi to při kliku na odkaz propíše do url.
  2. Jak to url potom přenést do té komponenty v případě, že to někdo zadá do adresního řádku? Chtěl bych, aby to bylo přístupné, když se třeba pošle odkaz emailem. Můžu je vzít v Presenteru přes getParameters, ale kam co pak dát?

Dík za radu.

IMapsComponentFactory

<?php
interface IMapsComponentFactory
{
    /**
     * @return MapsComponent
     */
    public function create(): MapsComponent;
}
?>

MapsComponent

<?php
class MapsComponent extends UI\Control
{
    /** @var string $templateFile */
    private $templateFile = __DIR__ . '/MapsComponent.latte';

    public $country;
    public $locations = [];

	...constructor předává translator, naplní to $locations sezname z DB...


    public function handleCountry(string $slug)
    {
        foreach ($this->locations as $country) {
            if ($country->slug === $slug) {
                $this->country = $country->id;
            }
        }
        $this->template->countryId = $this->country;

        if ($this->presenter->isAjax()) {
            $this->redrawControl('mapLeft');
        } else {
            $this->redirect('this');
        }
    }


    public function render()
    {
        $this->template->countries = $this->locations;
        $this->template->setFile($this->templateFile);
        $this->template->render();
    }
...
}
?>

MapsComponent.latte

<?php
...
                <ul class="list-unstyled">
                    <li n:foreach="$countries as $country">
                        <a class="ajax" n:href="Country, $country->slug" rel="nofollow">{$country->name}</a>
                    </li>
                </ul>
...
?>

presenter

<?php
final class ContactPresenter extends BasePresenter
{
...
    protected function createComponentMapsComponent(): MapsComponent
    {
        return $this->MapsComponentFactory->create();
    }
...
}
?>

a v default.latte už jen {control mapsComponent}

Milo
Nette Core | 1283
+
+2
-

Parametry mapsComponent-slug=australia a do=mapsComponent-Country představují stav komponenty, který se přenáší v URL. A jejich jméno vzniká automaticky podle toho, jak je komponenta připojena do stromu komponent. Ty se tak vůbec o URL starat nemusíš a píšeš jen handle metody. Tuhle celou automatiku nemusíš použít a stav komponenty budeš udržovat ručně.

Komponenta

final class MapsControl ...
{
	private $slug;

	public function setSlug(?string $slug)
	{
		# validace
		$this->slug = $slug;
	}
}

Presenter:

public function actionXyz(string $slug = null): void
{
	$this['mapsComponent']->setSlug($slug);
}

A parametr slug už si v URL naroutuješ, jak je potřeba.

V komponentě potřebuješ potom vytvářet URL na změnu země. To se dá udělat buď přes presenter $this->presenter->link(...) nebo {plink ...} ale komponenta přestane být znovupoužitelná. Řešením je předat si do komponenty callback, který URL generuje.

Komponenta:

public function __construct(..., callable $urlGenerator)
{
	...
}

Továrna:

interface IMapsComponentFactory
{
	public function create(callable $urlGenerator);
}

Presenter:

protected function createComponentMapsComponent(): MapsComponent
{
	return $this->mapsComponentFactory->create(function (string $country) {
		return $this->link('xyz', ['slug' => $country]);
	});
}
d@rkWolf
Člen | 163
+
0
-

@Milo Já úplně netuším, jak to pak ale naroutovat? Ty stránky, co v nich ta komponenta bude se mi routují přes výchozí routu:

<?php
	$router->withModule('Front')
               ->addRoute('[<locale=en en|cs>/]<presenter>[/<action>[/<id>]]', [
                   'presenter' => 'Homepage',
                   'action'    => 'default',
                   'id'        => null,
               ]);
?>

Netuším, jak to tam přidat, aby to vypadalo nějak takto třeba domena/kontakt?country=australia?

Jako já bych se asi i bez té url obešel, ale z nějakého důvodu se mi adresa toho handle teď s Najou propisuje do adresy, tahleta věc byla dřív použitá s nette.ajax na staré verzi a tam se to do adresy nepropisovalo.

Editoval d@rkWolf (20. 5. 2020 11:06)

Milo
Nette Core | 1283
+
0
-

Aha. Tak to byl ode mě trochu overengineering :-)

Zkus tomu linku přidat atribut data-naja-history="off"

https://naja.js.org/#…

d@rkWolf
Člen | 163
+
0
-

No jako ona se mi ta možnosti s funkčním linkem a history líbí, ale mám problém s rozchozením routování, systému routování v Nette furt nějak nemůžu přijít na kloub(teď sem zrovna zjistil, že mi web crashne, když někdo zadá domena/abc.abc, nechápu proč, dle mě je to normální neexistující adresa a mělo by vypadnout 404, ne 500)… Pravděpodobně to vyzkouším, ale napřed to zprovozním bez toho, zkusím tam dát to history=off a toto zařadím do pole upgradů.

Editoval d@rkWolf (21. 5. 2020 20:10)