Form wizard – vicekrokovy formular
- Jan Tvrdík
- Nette guru | 2595
- zdenek.hrib
- Člen | 2
Při šel jsi na něco? Dost by mě to taky zajímalo. Chci udělat aplikaci, která bude v podstatě jeden velký „wizard“. Rozhoduju se mezi více frameworkama – konkrétně Yii, Kohana a Nette a tohle je v podstatě moje základní výběrové kritérium.
- zdenek.hrib
- Člen | 2
Dostal jsem odpověď mailem od _Martin_ na dotaz na tu hotovou komponentu, kterou zmiňuje v těch příspěvcích na které jsou tu odkazy:
*Ahoj,
rád bych pomohl, ale obávám se, že už to nepůjde. Komponentu jsem psal pro
jednoho dřívějšího odběratele, pro něhož již nepracuji. Zdrojové
kódy, které jsem měl u sebe v PC, skončily v křemíkovém nebi poté, co
mi z ničeho nic odešel starý disk.
Pokud se do této komponenty pustíš sám, doporučuji nastudovat nové možnosti Nette a také addon Request Button (https://componette.org/search/?…), který by ti v tom mohl pomoci.
Přeji hodně úspěchů s vývojem,
Martin*
- Filip111
- Člen | 244
Ahoj, sám jsem před pár dny řešil podobnou otázku pro eshop – šel
jsem trochu jinou cestou a vytvořil třídu StepManagera, který obstarává
jednotlivé kroky. Každý krok je implementován vlastní
komponentou/formulářem a konfiguruje se přes neon. Lze tedy jednoduše
přidávat jednotlivé kroky nebo měnit pro různé klienty.
Každý krok si sám musí zajistit vykreslení a uložení dat, takže je
vhodné jim předat v konstruktoru nějaké úložiště (to mám zatím
vyřešené trochu prasácky a předávám celou session).
Konfigurace:
factories:
orderStep1:
class: web123\Eshop\OrderStepCustomer
arguments: [@cart]
orderStep2:
class: web123\Eshop\OrderStepPayShipping
arguments: [@session, @cart]
orderStep4:
class: web123\Eshop\OrderStepRecap
arguments: [@cart, @orderManager]
services:
orderSteps:
class: web123\Eshop\StepManager
arguments: [@session::getSection('orderSteps'), [@orderStep1, @orderStep2, orderStep4]]
Interface – jeden krok:
interface IStep
{
function getTitle(); // nazev kroku
function setManager($manager);
function render(); // vykresleni formulare nebo komponenty
function reset(); // reset stavu kroku
}
Interface vlastniho step managera – asi nakonec neni potreba:
interface IStepManager
{
function getCurrentStep();
function setCurrentStep($step);
function reset();
function getSteps();
function setSteps($steps);
}
Implemetace:
class StepManager extends Nette\Object implements IStepManager {
private $current; // aktualni krok
private $repository;
private $steps;
private $activated; // pole jiz aktivnich kroku
private $presenter;
public function __construct($repository, $steps) {
$this->repository = $repository;
$this->steps = $steps;
$this->registerSteps();
if ($repository->activated)
$this->activated = $repository->activated;
else {
// inicialni naplneni pole
$this->activated = array();
$i = 0;
foreach ($this->steps as $step) {
$this->activated[$i] = false;
$i++;
}
}
if ($repository->current > '')
$this->current = $repository->current;
else
$this->setCurrentStep(0);
}
public function __destruct() {
$this->repository->current = $this->current;
$this->repository->activated = $this->activated;
}
public function reset() {
$this->activated = array();
$this->current = null;
// projdu jednotlive komponenty a zavolam reset
if (!empty($this->steps)) {
foreach ($this->steps as $step) {
$step->reset();
}
}
if ($this->presenter)
$this->presenter->redirect('default');
}
public function nextStep() {
$this->setCurrentStep($this->current + 1);
}
public function getCurrentStep() {
return $this->current;
}
public function getActivatedSteps() {
return $this->activated;
}
public function setCurrentStep($step) {
// oznacim krok jako jiz jednou aktivovany
$this->activated[$step] = true;
if (count($this->steps) >= $step)
// dalsi krok
$this->current = $step;
//else konec
// musim si sem predat referenci na presenter
if ($this->presenter)
$this->presenter->redirect('default');
}
public function registerPresenter($presenter) {
$this->presenter = $presenter;
}
public function getPresenter() {
return $this->presenter;
}
public function setSteps($steps) {
$this->steps = $steps;
}
public function getSteps() {
return $this->steps;
}
public function registerSteps() {
// kazdemu kroku nastavim referenci na tento manager aby az udela svoji praci, zavolal callback
if (!empty($this->steps)) {
foreach ($this->steps as $step) {
$step->setManager($this);
}
}
}
}
Nevěděl jsem jak vyřešit redirect, takže zatím řeším oberličkou a
v prezenteru si musím StepManager doregistrovat pomocí
registerPresenter()
.
Pro samotné použití pak volám v latte
{control orderStepForm}
a v presenteru mám k této komponentě
továrničku:
public function createComponentOrderStepForm() {
$steps = $this->stepsManager->getSteps();
$step = $steps[$this->stepsManager->getCurrentStep()];
return $step->render();
}
O vykreslení navigačního okna, které přepíná mezi jednotlivými kroky se samostatná komponenta, které předávám celou službu stepManagera.
Určitě by se to dalo zjednodušit nebo udělat jednodušší, ale chtěl jsem mít možnost konfigurovat kroky přes neon a nahradit některé kroky klientským řešením.
Jestli k tomu máte nějaké návrhy, budu rád (ale ne že mi napíšete stejný řešení na 10 řádků, to bych byl dost nasr… :)
- maarlin
- Člen | 207
Filip111 napsal(a):
Ahoj, sám jsem před pár dny řešil podobnou otázku pro eshop – šel jsem trochu jinou cestou a vytvořil třídu StepManagera, který obstarává jednotlivé kroky. Každý krok je implementován vlastní komponentou/formulářem a konfiguruje se přes neon. Lze tedy jednoduše přidávat jednotlivé kroky nebo měnit pro různé klienty.
…
Tvoje řešení vypadá celkem fajn, asi ho s určitými modifikacemi
použiju.
Moje hlavní requirements na „wizarda“ jsou tyto:
- možnost dokreslovat jednotlivé kroky pod sebe s nějakými fancy efekty (= možno získat další step nějak skrze AJAJ/AJAX)
- možnost odkázat na nějaký krok s parametry, které předvyplní předchozí kroky