Nette formular – defaultne hodnoty

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
steelbull
Člen | 244
+
0
-

Defaultne hodnoty do formulara nastavujem v presenteri:

$form->setDefaults(pole_hodnot);

ALE:
Ako defaultne hodnoty ziskam vo formulari?
$formData = ???? existuje nieco ako getDefaults?

Formular mam vytvoreny ako komponent.

Velmi pekne dakujem.

duke
Člen | 650
+
+1
-

Neexistuje. Metoda setDefaults prostě jen podmíněně nastaví hodnoty, a sice pouze v případě, kdy neproběhlo zpracování odeslání formuláře (buď proto, že vůbec nebyl odeslán, nebo proto, že ještě nebyla komponenta formuláře připojena k presenteru).

steelbull
Člen | 244
+
0
-

duke napsal(a):

Neexistuje. Metoda setDefaults prostě jen podmíněně nastaví hodnoty, a sice pouze v případě, kdy neproběhlo zpracování odeslání formuláře (buď proto, že vůbec nebyl odeslán, nebo proto, že ještě nebyla komponenta formuláře připojena k presenteru).

Totiz, problem mam ten, ze formular pouziva hodnoty z viacerych tabuliek. Doteraz som to robil tak, ze som poslal hlavne formData do formulara a zvysne hodnoty si formular nacital sam:


    /**
     * Create laboratory request form
     */
    function create($data = NULL) {

        //Create new instance
        $form = new UI\Form;

        //Call needed models
        $lrModel = new Model\LabRequestsModel($this->context);
        $projectsModel = new Model\LrProjectsModel($this->context);
        $procModel = new Model\ProceduresModel($this->context);
        $modelsModel = new Model\WuModelsModel($this->context);
        $componentsModel = new Model\TcComponentsModel($this->context);
        $modelUsers = new Model\UsersModel($this->context);
        $lrTypesModel = new Model\LrTypesModel($this->context);

        //Load Data from models
        $projects = $projectsModel->getProjects()->fetchPairs('id', 'title');
        $types = $lrTypesModel->getLrTypes()->fetchPairs('id', 'title');
        $models = $modelsModel->getModels()->fetchPairs('id', 'title');
        $components = $componentsModel->getComponents()->fetchPairs('id', 'title');

        //Get all requesters
        $requesters = array();
        foreach ($modelUsers->getUsers(array(1, 2, 3)) as $requester) {
            $requesters[$requester->id] = $requester->lastname . ', ' . $requester->firstname;
        }

        //Load components from database as object and convert to array to use in form multiselect
        $tested_components_id = array();
        if (isset($defaults->id)) {
            $tested_components = $lrModel->getTestedComponents($defaults->id);
            foreach ($tested_components as $component) {
                array_push($tested_components_id, $component->component_id);
            }
        }

        // Load data from procedure variant model
        $proc_variantlist = $procModel->getProcedureVariants();
        $proc_variants = array();
        foreach ($proc_variantlist as $proc_variant) {
            $proc_variants[$proc_variant->id] = $proc_variant->ref('proc', 'proc_id')->title . '/' . $proc_variant->title;
        }

        //Render form
        $form->method = 'post';
        $form->getElementPrototype()->addAttributes(array('id' => 'lrForm'));

        $form->getElementPrototype()->addAttributes(array('class' => 'ajax'));

        $form->addText('number', $this->translator->translate('lr.form.request_number'))
                ->setAttribute('class', 'form-control')
                //->setDefaultValue(($data == NULL) ? NULL : $data->number)
                ->addRule(Form::PATTERN, $this->translator->translate('flash.bad_format'), "^[a-zA-Z0-9.]{0,30}$");

        $form->addSelect('project_id', $this->translator->translate('lr.form.project'), $projects)
                ->setAttribute('class', 'chosen-select')
                ->setPrompt('')
                ->setDefaultValue(($data == NULL) ? NULL : $data->project_id)
                ->setRequired($this->translator->translate('lr.form.please_select_the_project'));

        $form->addSelect('type_id', $this->translator->translate('lr.form.type'), $types)
                ->setPrompt('')
                ->setAttribute('class', 'chosen-select')
                ->setDefaultValue(($data == NULL) ? NULL : $data->type_id)
                ->setRequired($this->translator->translate('lr.form.please_select_laboratory_request_type'));

        $form->addSelect('proc_variant_id', $this->translator->translate('lr.form.procedure_variant'), $proc_variants)
                ->setPrompt('')
                ->setAttribute('class', 'chosen-select')
                ->setDefaultValue(($data == NULL) ? NULL : $data->proc_variant_id)
                ->setRequired($this->translator->translate('lr.form.please_select_the_procedure_variant'));

        $form->addSelect('wu_model_id', $this->translator->translate('lr.form.model'), $models)
                ->setPrompt('')
                ->setAttribute('class', 'chosen-select')
                ->setDefaultValue(($data == NULL) ? NULL : $data->wu_model_id)
                ->setRequired($this->translator->translate('lr.form.please_select_model'));

        $form->addMultiSelect('tested_components_id', $this->translator->translate('lr.form.tested_components'), $components)
                ->setAttribute('class', 'chosen-select')
                ->setDefaultValue(($data == NULL) ? NULL : $tested_components_id);

        $form->addMultiSelect('requester_id', $this->translator->translate('lr.form.requesters'), $requesters)
                ->setAttribute('class', 'chosen-select')
                //->setDefaultValue(($data == NULL) ? NULL : $lrModel->getRequesters($data->id)->fetchPairs('id', 'requester_id'))
                ->setRequired($this->translator->translate('lr.form.please_select_requester'));

        $form->addTextArea('description', $this->translator->translate('lr.form.description'))
                ->setAttribute('class', 'form-control')
                ->setDefaultValue(($data == NULL) ? NULL : $data->description);

        $form->addText('planned_start', $this->translator->translate('lr.form.planned_start'))
                ->setAttribute('class', 'form-control bootstrap-datepicker')
                ->setDefaultValue(($data == NULL) ? NULL : date_format($data->planned_start, 'Y-m-d'))
                ->addRule(Form::PATTERN, $this->translator->translate('flash.bad_format'), '^([0-9]{4}-[0-1][0-9]-[0-3][0-9])?$');

        $form->addText('planned_finish', $this->translator->translate('lr.form.planned_finish'))
                ->setAttribute('class', 'form-control bootstrap-datepicker')
                ->setDefaultValue(($data == NULL) ? NULL : date_format($data->planned_finish, 'Y-m-d'))
                ->addRule(Form::PATTERN, $this->translator->translate('flash.bad_format'), '^([0-9]{4}-[0-1][0-9]-[0-3][0-9])?$');

        $form->addTextArea('objective', $this->translator->translate('lr.form.objective'))
                ->setAttribute('class', 'form-control')
                ->setDefaultValue(($data == NULL) ? NULL : $data->objective);

        $form->addTextArea('information', $this->translator->translate('lr.form.informations'))
                ->setAttribute('class', 'form-control')
                ->setDefaultValue(($data == NULL) ? NULL : $data->information);

        $form->addTextArea('monitoring_instructions', $this->translator->translate('lr.form.monitoring_instructions'))
                ->setAttribute('class', 'form-control');

        $form->addHidden('id');

        $form->addProtection();

        // Validate form
        $form->onValidate[] = function($form) {
            $lrModel = new Model\LabRequestsModel($this->context);
            $data = $form->getValues();

            // Check date difference
            if (strtotime($data->planned_finish) < strtotime($data->planned_start)) {
                $form['planned_start']->addError($this->translator->translate('lr.form.planned_start_error_difference'));
                $form['planned_finish']->addError($this->translator->translate('lr.form.planned_finish_error_difference'));
            }

            // Check unique
            if ($lrModel->checkUnique($data->number, $data->id)) {
                $form['number']->addError($this->translator->translate('lr.form.request_number_error_unique'));
            }
        };

        $form->onSuccess[] = array($this->instance, $this->callback);

        //Return rendered Form
        return $form;
    }
duke
Člen | 650
+
+1
-

To, z kolika databázových tabulek (či jiných zdrojů) si načítáš hodnoty, není podstatné. Tvé druhé větě nerozumím. V čem tkví tvůj problém? Čeho se snažíš dosáhnout, co se ti nedaří?

steelbull
Člen | 244
+
0
-

Cely zdrojak este raz:

Otazka, nacitavam defaultne hodnoty korektne? Nie je to zly sposob?

@duke: Takto v prezenteri vytvaram komponent:


    /**
     * LrForm create
     *
     * @return type
     */
    public function createComponentLrform() {
        $form = (new LrFormFactory($this, 'LrFormSuccess', $this->context, $this->translator))->create();
        return $form;
    }

a takto naplnam (tiez v presenteri defaultne hodnoty):

    /**
     * LrForm defaults
     *
     * @param type $id
     */
    public function lrFormDefaults($id) {
        $model = new Model\LabRequestsModel($this->context);
        $data = $model->getLabRequest($id);

        if (!$data) {
            $this->flashMessage('flash.not_found');
            $this->redirect('Lr:');
        }

        $this['lrform']->setDefaults($data);
        $this['lrform']->setDefaults(array(
            'planned_start' => (new \DateTime($data->planned_start))->format('Y-m-d'),
            'planned_finish' => (new \DateTime($data->planned_finish))->format('Y-m-d')
        ));

        $tested_components = $model->getTestedComponents($id);
        $tested_components_id = array();
        foreach ($tested_components as $item) {
            array_push($tested_components_id, $item->id);
        }

        $this['lrform']->setDefaults(array('tested_components_id' => $tested_components_id));

        $requesters = $model->getRequesters($id);
        $requesters_id = array();
        foreach ($requesters as $item) {
            array_push($requesters_id, $item->requester_id);
        }

        $this['lrform']->setDefaults(array('requester_id' => $requesters_id));
    }

…a takto vyzera formular:

    /**
     * Create laboratory request form
     */
    function create($data = NULL) {

        //Create new instance
        $form = new UI\Form;

        //Call needed models
        $lrModel = new Model\LabRequestsModel($this->context);
        $projectsModel = new Model\LrProjectsModel($this->context);
        $procModel = new Model\ProceduresModel($this->context);
        $modelsModel = new Model\WuModelsModel($this->context);
        $componentsModel = new Model\TcComponentsModel($this->context);
        $modelUsers = new Model\UsersModel($this->context);
        $lrTypesModel = new Model\LrTypesModel($this->context);

        //Load Data from models
        $projects = $projectsModel->getProjects()->fetchPairs('id', 'title');
        $types = $lrTypesModel->getLrTypes()->fetchPairs('id', 'title');
        $models = $modelsModel->getModels()->fetchPairs('id', 'title');
        $components = $componentsModel->getComponents()->fetchPairs('id', 'title');

        //Get all requesters
        $requesters = array();
        foreach ($modelUsers->getUsers(array(1, 2, 3)) as $requester) {
            $requesters[$requester->id] = $requester->lastname . ', ' . $requester->firstname;
        }

        //Load components from database as object and convert to array to use in form multiselect
        $tested_components_id = array();
        if (isset($defaults->id)) {
            $tested_components = $lrModel->getTestedComponents($defaults->id);
            foreach ($tested_components as $component) {
                array_push($tested_components_id, $component->component_id);
            }
        }

        // Load data from procedure variant model
        $proc_variantlist = $procModel->getProcedureVariants();
        $proc_variants = array();
        foreach ($proc_variantlist as $proc_variant) {
            $proc_variants[$proc_variant->id] = $proc_variant->ref('proc', 'proc_id')->title . '/' . $proc_variant->title;
        }

        //Render form
        $form->method = 'post';
        $form->getElementPrototype()->addAttributes(array('id' => 'lrForm'));

        $form->getElementPrototype()->addAttributes(array('class' => 'ajax'));

        $form->addText('number', $this->translator->translate('lr.form.request_number'))
                ->setAttribute('class', 'form-control')
                ->addRule(Form::PATTERN, $this->translator->translate('flash.bad_format'), "^[a-zA-Z0-9.]{0,30}$");

        $form->addSelect('project_id', $this->translator->translate('lr.form.project'), $projects)
                ->setAttribute('class', 'chosen-select')
                ->setPrompt('')
                ->setRequired($this->translator->translate('lr.form.please_select_the_project'));

        $form->addSelect('type_id', $this->translator->translate('lr.form.type'), $types)
                ->setPrompt('')
                ->setAttribute('class', 'chosen-select')
                ->setRequired($this->translator->translate('lr.form.please_select_laboratory_request_type'));

        $form->addSelect('proc_variant_id', $this->translator->translate('lr.form.procedure_variant'), $proc_variants)
                ->setPrompt('')
                ->setAttribute('class', 'chosen-select')
                ->setRequired($this->translator->translate('lr.form.please_select_the_procedure_variant'));

        $form->addSelect('wu_model_id', $this->translator->translate('lr.form.model'), $models)
                ->setPrompt('')
                ->setAttribute('class', 'chosen-select')
                ->setRequired($this->translator->translate('lr.form.please_select_model'));

        $form->addMultiSelect('tested_components_id', $this->translator->translate('lr.form.tested_components'), $components)
                ->setAttribute('class', 'chosen-select')
                ->setDefaultValue(($data == NULL) ? NULL : $tested_components_id);

        $form->addMultiSelect('requester_id', $this->translator->translate('lr.form.requesters'), $requesters)
                ->setAttribute('class', 'chosen-select')
                ->setRequired($this->translator->translate('lr.form.please_select_requester'));

        $form->addTextArea('description', $this->translator->translate('lr.form.description'))
                ->setAttribute('class', 'form-control');

        $form->addText('planned_start', $this->translator->translate('lr.form.planned_start'))
                ->setAttribute('class', 'form-control bootstrap-datepicker')
                ->addRule(Form::PATTERN, $this->translator->translate('flash.bad_format'), '^([0-9]{4}-[0-1][0-9]-[0-3][0-9])?$');

        $form->addText('planned_finish', $this->translator->translate('lr.form.planned_finish'))
                ->setAttribute('class', 'form-control bootstrap-datepicker')
                ->addRule(Form::PATTERN, $this->translator->translate('flash.bad_format'), '^([0-9]{4}-[0-1][0-9]-[0-3][0-9])?$');

        $form->addTextArea('objective', $this->translator->translate('lr.form.objective'))
                ->setAttribute('class', 'form-control');

        $form->addTextArea('information', $this->translator->translate('lr.form.informations'))
                ->setAttribute('class', 'form-control');

        $form->addTextArea('monitoring_instructions', $this->translator->translate('lr.form.monitoring_instructions'))
                ->setAttribute('class', 'form-control');

        $form->addHidden('id');

        $form->addProtection();

        // Validate form
        $form->onValidate[] = function($form) {
            $lrModel = new Model\LabRequestsModel($this->context);
            $data = $form->getValues();

            // Check date difference
            if (strtotime($data->planned_finish) < strtotime($data->planned_start)) {
                $form['planned_start']->addError($this->translator->translate('lr.form.planned_start_error_difference'));
                $form['planned_finish']->addError($this->translator->translate('lr.form.planned_finish_error_difference'));
            }

            // Check unique
            if ($lrModel->checkUnique($data->number, $data->id)) {
                $form['number']->addError($this->translator->translate('lr.form.request_number_error_unique'));
            }
        };

        $form->onSuccess[] = array($this->instance, $this->callback);

        //Return rendered Form
        return $form;
    }

Editoval steelbull (6. 11. 2014 15:40)

steelbull
Člen | 244
+
0
-

duke napsal(a):

To, z kolika databázových tabulek (či jiných zdrojů) si načítáš hodnoty, není podstatné. Tvé druhé větě nerozumím. V čem tkví tvůj problém? Čeho se snažíš dosáhnout, co se ti nedaří?

A este jedna otazka:

v presenteri mam metodu:

public function renderEdit($id) {
...nieco
}

a komponent:

protected function createComponentPokus() {
// ...sem by som potreboval dostat ID z renderEdit()...
}
duke
Člen | 650
+
+1
-

Model by bylo elegantnější řešit pomocí DI Containeru (tvé modely a i tvá továrna by byly injektované služby), ale to přímo nesouvisí s otázkou defaultních hodnot, v čemž zásadní problém nevidím, snad jen tu redirekci bych hodil ven, a místo ní vyhazoval výjimku. Zodpovědností té metody, jak je patrné z jejího názvu, není přesměrovávat (to by měl presenter řešit na vyšší úrovni), nýbrž nastavovat výchozí hodnoty formuláře…

Parametr id z aktuálního dotazu, můžeš v tovární metodě (createComponentPokus) získat takto:

protected function createComponentPokus() {
	$id = $this->getParameter('id');
	// ...
}

Editoval duke (6. 11. 2014 16:49)

steelbull
Člen | 244
+
0
-

@duke Dakujem Ti, mozno ze to este prerobim.

Xethilos
Člen | 19
+
+1
-

@steelbull Nevím, jestli je to už je vyřešeno, proletěl jsem to rychle, ale tohle řešení tu není.

<?php
public HomePresenter extends Presenter {

	/** @var array */
	private $defaults = array();

	public function actionDefault($id) {
		$this->defaults = $this->context->getService('model')->get($id)->toArray();
		$this->defaults += $this->context->getService('model.other')->get(1)->toArray(); // Přidání hodnot
	}

	protected function createComponentForm() {
		$form = new Form;

		$form->setDefaults($this->defaults);

		return $form;
	}

	public function afterForm(Form $form, $values) {
		$this->defaults; // Výchozí hodnoty
		$values; // Odeslané hodnoty
	}

}
?>

Editoval Xethilos (6. 11. 2014 17:09)

steelbull
Člen | 244
+
0
-

@Xethilos Velmi pekne dakujem, ano. Presne tak som to urobil.

Azathoth
Člen | 495
+
0
-

ono se $this->context ještě pořád používá? Nemělo by se spíš použít správné DI?

steelbull
Člen | 244
+
+1
-

@Azathoth ano, ja som to uz cele prerobil na DI