Nette formular – defaultne hodnoty

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
steelbull
Člen | 241
+
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 | 241
+
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 | 241
+
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 | 241
+
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 | 241
+
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 | 241
+
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 | 241
+
+1
-

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