Komponenta s přístupem do modelu
- dj.kure
- Člen | 70
Zdravím,
mám další menší problém s vytvářením formuláře.
Mám formulář, jehož 3/4 část (je poměrně rozsáhlý) bude použita v několika desítkách dalších formulářů, takže si chci vytvořit komponentu carForm, kterou pak budu volat v rámci továrničky.
Do „/app/forms/CarForm.php“ jsem si vytvořil základ formuláře takto:
namespace App;
use Nette\Application\UI,
Nette\ComponentModel\IContainer,
Nette\Forms\Container;
class CarForm extends UI\Form
{
/**
* @var \App\Cars
* @inject
*/
public $cars;
public function __construct(IContainer $parent = NULL, $name = NULL)
{
parent::__construct($parent, $name);
$this->addSelect('brand', 'Výrobce:', $this->cars->listOfCarBrands())
->setPrompt('Zvolte výrobce vozidla');
.............
a volám jej v rámci Presenteru takto:
protected function createComponentAddCarForm()
{
$form = new CarForm();
// dočasné testovací prvky formuláře
$form->addSubmit('send', 'Odeslat formulář');
// call method logInFormSucceeded() on success
$form->onSuccess[] = $this->addCarFormSucceeded;
return $form;
}
Tohle všechno by fungovalo, ale mám problém s doplněním seznamu hodnot
do Selectů tohoto formuláře, což dělám za pomocí modelu
$this->cars->listOfCarBrands() (viz první část
kódu).
Problém je ale v tom, že k tomu modelu zřejmě nemám přístup (což je
divné), každopádně laděnka mi hlásí toto:
Call to a member function listOfCarBrands() on a non-object search►
Proč? Co dělám špatně nebo přehlížím?
Případně měl bych řešit naplnění výchozích hodnot do selectu nějak
jinak? (třeba v rámci Presenteru, kde přístup do
listOfCarBrands() mám).
Díky!
- thunderbuff
- Člen | 164
<?php
// formulář
class CarForm extends UI\Form
{
/**
* @var \App\Cars
*/
private $cars;
public function __construct(Cars $cars)
{
parent::__construct();
$this->cars = $cars;
$this->addSelect('brand', 'Výrobce:', $this->cars->listOfCarBrands())
->setPrompt('Zvolte výrobce vozidla');
}
}
// presenter
// tady už by fungovala i anotace inject
private $carForm;
public function injectCars(CarForm $carForm) {
$this->carForm = $carForm;
}
protected function createComponentAddCarForm()
{
$form = $this->carForm;
// dočasné testovací prvky formuláře
$form->addSubmit('send', 'Odeslat formulář');
// call method logInFormSucceeded() on success
$form->onSuccess[] = $this->addCarFormSucceeded;
return $form;
}
?>
… a zaregistruj si carForm jako sužbu v configu, pak to bude fungovat.
Editoval thunderbuff (10. 1. 2014 15:09)
- David Matějka
- Moderator | 6445
@thunderbuff: komponenty jako sluzbu neni spravny reseni, muze se to rozbit
@dj.kure: udelej si tovarnicku
class CarForm extends UI\Form
{
/**
* @var \App\Cars
*/
private $cars;
public function __construct(Cars $cars)
{
$this->cars = $cars;
$this->addSelect('brand', 'Výrobce:', $this->cars->listOfCarBrands())
->setPrompt('Zvolte výrobce vozidla');
}
}
interface CarFormFactory
{
/**
* @return CarForm
*/
public function create();
}
config.neon:
services:
- CarFormFactory
presenter:
/**
* @var CarFormFactory
* @inject
*/
public $carFormFactory;
protected function createComponentAddCarForm()
{
$carForm = $this->carFormFactory->create();
.....
return $carForm;
}
- dj.kure
- Člen | 70
Děkuji za rady, udělal jsem to podle matej21, ale stále to nefunguje, stále tento error:
Call to a member function listOfCarBrands() on a non-object
chyba je u:
$this->addSelect(‚brand‘, ‚Výrobce:‘,
$this->cars->listOfCarBrands())
Pak jsem si všiml, že jsem nepředělal toto:
class CarForm extends UI\Form
{
/**
* @var \App\Cars
*/
private $cars;
public function __construct(Cars $cars)
{
$this->cars = $cars;
$this->addSelect('brand', 'Výrobce:', $this->cars->listOfCarBrands())
->setPrompt('Zvolte výrobce vozidla');
}
}
Takže jsem to předělal a stejně mi to hlásí následující Error:
Argument 1 passed to Nette\Application\UI\Form::__construct() must implement interface Nette\ComponentModel\IContainer, instance of App\Cars given, called in /usr/local/zend/apache2/htdocs/esk/app/forms/CarForm.php on line 21 and defined
- David Matějka
- Moderator | 6445
Call to a member function listOfCarBrands() on a non-object
to hlasit nemuze, pokud jsi postupoval, jak jsem psal. to by driv selhalo na
spatnem argumentu nebo tak…
- David Matějka
- Moderator | 6445
nevolas nahodou v konstruktoru parent::__construct($cars);?? kdyztak to smaz
- dj.kure
- Člen | 70
Ano, náhodou volám, už je to pryč:
class CarForm extends UI\Form
{
/**
* @var \App\Cars
* @inject
*/
private $cars;
public function __construct(Cars $cars)
{
$this->cars = $cars;
Container::extensionMethod('addDatePicker', function (Container $container, $name, $label = NUL
{
return $container[$name] = new \JanTvrdik\Components\DatePicker($label);
});
$this->addSelect('brand', 'Výrobce:', $this->cars->listOfCarBrands())
->setPrompt('Zvolte výrobce vozidla');
Chyba: Trying to get property of non-object
200: /**
201: * Returns form's method.
202: * @return string get | post
203: */
204: public function getMethod()
205: {
206: return $this->element->method;
207: }
208:
209:
A NetBeans na mě pořád křičí, že:
Parent Constructor is not Called, 0 mandatory, 2 optional parameters
needed, Your objects can be wrongly initalized:
- David Matějka
- Moderator | 6445
ajo vlastne, kecam :)
zavolej parent::__construct(); ale bez parametru
a
Container::extensionMethod('addDatePicker', function (Container $container, $name, $label = NUL
{
return $container[$name] = new \JanTvrdik\Components\DatePicker($label);
});
dej do bootstrapu, tady to nema co delat..
a posledni vec, i kdyz nemam rad dedeni formu, tak kdyz to delas, dej definici polozek radeji do attached (pryc z __construct). cely to bude vypadat asi takhle
class CarForm extends UI\Form
{
/**
* @var \App\Cars
*/
private $cars;
public function __construct(Cars $cars)
{
$this->cars = $cars;
parent::__construct();
}
public function attached($presenter)
{
parent::attached($presenter);
if($presenter instanceof \Nette\Application\UI\Presenter) {
$this->addSelect('brand', 'Výrobce:', $this->cars->listOfCarBrands())
->setPrompt('Zvolte výrobce vozidla');
}
}
- dj.kure
- Člen | 70
Už to funguje, addDatePicker jsem přehodil do Bootstrapu.
Ale teď mám takový menší jiný problém, ale to asi bude drobnost –
protected function createComponentAddCarForm()
{
$form = $this->carFormFactory->create();
$form->addSubmit('send', 'Odeslat formulář');
// call method logInFormSucceeded() on success
$form->onSuccess[] = $this->addCarFormSucceeded;
return $form;
}
Problém je v tom, že tlačítko „Odeslat formulář“ se mi vkládá do formuláře jako první, místo aby bylo úplně na konci :( Proč?
- David Matějka
- Moderator | 6445
aaaa pravda, jsem si neuvedomil, sorry :)
ok, prehod zas zpatky tu definici $this->addSelect do konstruktoru, snad se nic nerozbije :)
- dj.kure
- Člen | 70
Opraveno, děkuju moc :-) sám bych na to nepřišel ani kdybych se rozkrájel.
Já sázel na to, že ten jednoduchý Injector (jestli to nazývám správně) bude fungovat všude, ne jen v Presenterech.
Mám na mysli toto:
/**
* @var \App\Cars
* @inject
*/
private $cars;
Editoval dj.kure (10. 1. 2014 16:39)