creating form factory for file upload
- jdan1131x
- Member | 41
The code below works fine in a presenter, but not in a FormFactory thats
not extending Nette\Application\UI\Presenter. I tried injecting
Nette\Http\Request
but get tracy error (two request objects…)
protected function createComponentUploadPdfForm(): Form {
$size = 1024 * 1024;
$form = new Form();
//post required for uploads
$form->setMethod('POST');
$form->addUpload('document')
->addRule($form::MAX_FILE_SIZE, "Maximum size is 1 MB", $size);
$form->addSubmit('send');
$form->addSubmit('clear');
$form->onSubmit[] = function () {
//per the Nette Website documentation at https://doc.nette.org/en/http/request#toc-getpost
$request = $this->getHttpRequest();
//returns tree of uploaded normalized files each instance is Nette\Http\FileUpload
//FileUpload object returned by request https://doc.nette.org/en/http/request#toc-getfile
$file = $request->getFile('document');
//test 1 https://doc.nette.org/en/http/request#toc-getfile
if($file->hasFile() != true) {
$form->addError(sprintf('File was not received'));
}
};
$form->onSuccess[] = function () {
// Some handling on success...
$this->redrawControl('docStatus');
$this->flashMessage("Success", 'success');
$this->redrawControl('nextStep');
};
return $form;
}
I want to extract the code above from presenter and put
in a formfactory service so its easily available elswhere on site.
I have two formfactories working fine, but the upload file form …
i cant seem to instantiate or inject the httpRequest object
so that i can get access to the FileUpload object and its methods..
I am afraid i dont know what URL to send when attempting $request = $new
HttpRequest($url).
i think that may be my issue. ??
thanks very much, sorry to bug…
James
- jdan1131x
- Member | 41
and when I move the working code to the Form Factory (shown above)
then tracy says :
Service of type JDApp\Forms\LessonThreeFormFactory used in type hint at App\Presenters\LessonWizardStep3Presenter::$formfactory3 not found. Did you add it to configuration file? search►
the answeris yes, i did add to the services.neon file that was added to Bootstrap.php
$configurator->addConfig($appDir . '/config/services.neon');
- jdan1131x
- Member | 41
i get the tracy error on the presenter although
this code works elsewhere
class LessonWizardStep3Presenter extends LessonWizardPresenter {
/** @var \JDApp\Forms\LessonThreeFormFactory @inject */
public \JDApp\Forms\LessonThreeFormFactory $formfactory3;
and
protected function createComponentUploadPdfForm(): Form {
//see details in /app/forms...
$form = $this->formfactory3->create();
return $form;
}
the only diff between the other working form factories and this one is the
use of the
file upload input type:
<div class="struct"><input class="form-group" type="file" n:name="document"> Use PDF</div>
- dsar
- Backer | 53
The business of onSubmit and onSuccess is best left to the Presenter or the Control.
Below an example of a Login form within a Control, it allows you to have some more specific events (such onAuthenticationSuccess) and it is more fine grained.
Factory:
final class LoginFormFactory
{
public function create(): Form
{
$form = new Form;
$form->addText('email', 'Email')
->setRequired('Enter your email');
$form->addPassword('password', 'Password')
->setRequired('Enter your password');
$form->addSubmit('submit', 'Login');
return $form;
}
}
Control:
use App\Forms\LoginFormFactory;
final class LoginControl extends Control
{
private LoginFormFactory $loginFormFactory;
private User $user;
public $onAuthenticationSuccess = [];
public function __construct(LoginFormFactory $loginFormFactory, User $user)
{
$this->loginFormFactory = $loginFormFactory;
$this->user = $user;
}
protected function createComponentLoginForm(): Form
{
$form = $this->loginFormFactory->create();
$form->onSuccess[] = [$this, 'doAuthentication'];
return $form;
}
public function doAuthentication(Form $form, \stdClass $values): void
{
try {
$this->user->login($values->email, $values->password);
} catch (AuthenticationException $e) {
$form->addError($e->getMessage());
return;
}
Arrays::invoke($this->onAuthenticationSuccess);
}
}
Presenter:
use App\Controls\LoginControl;
use App\Factories\LoginControlFactory;
final class UserPresenter extends Presenter
{
private LoginControlFactory $loginControlFactory;
public function __construct(LoginControlFactory $loginControlFactory)
{
parent::__construct();
$this->loginControlFactory = $loginControlFactory;
}
protected function createComponentLogin(): LoginControl
{
$control = $this->loginControlFactory->create();
$control->onAuthenticationSuccess[] = [$this, 'loginFormSucceeded'];
return $control;
}
public function loginFormSucceeded()
{
$this->redirect('Homepage:default');
}
}