Validace závislého select boxu

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

Ahoj,

rozchodil jsem si závislý select box z planette. Problém nastává ve chvíli, kdy se pokouším o editaci záznamu. Na závislý selectbox nefunguje ->setRequired() a tak je dependent select box nevalidovaný, čímž při nenastavení hodnoty a odeslání formuláře skončí chybou. Ve chvíli kdy přeci jen nastavím setRequired() to vypadá, že se neprovede onSuccess formuláře. Zkoušel jsem hledat řešení na foru, ale nedostal jsem se do funkčního stavu. Podařilo se někomu tento problém vyřešit?

jarda256
Člen | 130
+
0
-

Ahoj, jaký dependent select používáš?
Já používám NasExt. A můj kód vypadá takto. (Validace funguje jak má)

$form->addSelect('event','Event',$firstInput)->setRequired(TRUE)->setPrompt("Select event");

       $form->addDependentSelectBox('site', 'Site:', array($form['event']), function ($values) {
           $data =  new DependentSelectBoxData();
           if (isset($values['event'])) {
               $dataSite = $this->siteFacade->getNamesByEventId($values['event'],$this->locale);
               return $data->setItems($dataSite);
           }else{
               return $data;
           }
       })->setPrompt('- Select Site-')->setRequired()->setDisabledWhenEmpty(TRUE);
iNyxLadis
Člen | 48
+
0
-

jarda256 napsal(a):

Ahoj, jaký dependent select používáš?
Já používám NasExt. A můj kód vypadá takto. (Validace funguje jak má)

$form->addSelect('event','Event',$firstInput)->setRequired(TRUE)->setPrompt("Select event");

       $form->addDependentSelectBox('site', 'Site:', array($form['event']), function ($values) {
           $data =  new DependentSelectBoxData();
           if (isset($values['event'])) {
               $dataSite = $this->siteFacade->getNamesByEventId($values['event'],$this->locale);
               return $data->setItems($dataSite);
           }else{
               return $data;
           }
       })->setPrompt('- Select Site-')->setRequired()->setDisabledWhenEmpty(TRUE);

NASext se mi nepodařil rozchodit, tak jsem to vyřešil tímto: https://blog.nette.org/…-and-pure-js

Díky za odpověď.

jarda256
Člen | 130
+
0
-

Tak mně to nešlo přesně obráceně. Tam mi to pořád házelo nějaké chyby

iNyxLadis
Člen | 48
+
0
-

jarda256 napsal(a):

Tak mně to nešlo přesně obráceně. Tam mi to pořád házelo nějaké chyby

Já jsem se postupně těma chybama prokousal, ale tohle mi moc nejde do hlavy jak na to :/

public function handleTimesheetFormChange($cmpId)
{
    if ($cmpId) {
            $selectedProjects = $this->timesheetManager->getProjectsForSelectbox($cmpId);
            $this['timesheetForm']['Prj_ID']->setPrompt('Vybrat projekt')
                ->setItems($selectedProjects);
    } else {
            $this['timesheetForm']['Prj_ID']->setPrompt('Nejprve zvolit firmu')
                ->setItems(array())->setRequired();
    }

    $this->redrawControl('wrapper');
    $this->redrawControl('projectSnippet');
}

public function actionEdit($taskId, $cmpId)
{
    $task = $this->timesheetManager->getTask($taskId);
    if (!$task) {
        $this->error('Úkol nenalezen');
    } else
    {

    if (!$this->isAjax()) {         // pro nastaveni pocatecni hodnoty selectboxu, ve chvíli obsluhy selectboxu se o zbytek stará handle
          $selectedProjects = $this->timesheetManager->getProjectsForSelectbox($cmpId);
          $this['timesheetForm']['Prj_ID']->setItems($selectedProjects);
          $this['timesheetForm']->setDefaults($task);
        }
    }
    }

protected function createComponentTimesheetForm()
{
        $form = new Form;
        $form->addHidden('Tsk_ID'); // kvuli pridavani noveho zaznamu, kde pracuji s ID
        $form->addSelect('Cmp_ID', 'Firma', $this->timesheetManager->getCompanies()->fetchPairs('Cmp_ID', 'CmpName1'))
            ->setPrompt('Vybrat firmu')->setRequired();
        $form->addSelect('Prj_ID', 'Projekt')
            ->setPrompt('Vybrat projekt');
        $form->addText('TskName', 'Obor zájmu')->setRequired();
        $form->addText('TskDescription1', 'Popis úkolu')->setRequired();
        $form->addText('TskDateStart', 'Datum zahájení')->setRequired();
        $form->addText('TskDateEnd', 'Datum ukončení')->setRequired();
        $form->addText('TskTaskmaster', 'Zadavatel')->setRequired();
        $form->addText('TskWorked', 'Odpracováno (hod.)')->setRequired()->addRule(Form::INTEGER, 'Zadejte číselnou hodnotu');
        $form->addSelect('TskUser', 'Provedl', $employees = array(
            "user1" => 'user1',
            "user2" => 'user2',
            "user3" => 'user3',
            "user4" => 'user4',
            "user5" => 'user5',
            "user6" => 'user6',
        ))->setPrompt('Vybrat zaměstnance')->setRequired();
        $form->addSubmit('submit', 'Uložit');
        $form->onSuccess[] = [$this, 'timesheetFormSucceeded'];
        return $form;
}

public function timesheetFormSucceeded($form)
{

        $values = $form->getHttpData();
        unset($values['_submit']);
        unset($values['_do']);

        $this->timesheetManager->saveTask($values);
        $this->flashMessage('Záznam byl uložen.');
        $this->redirect(':Front:Timesheet:');
}
jarda256
Člen | 130
+
0
-

Nastav si setRequired při vytváření komponenty místo toho handleru. A stejně bych zvážil zkusit ten NasExt. Nemusí pak řešit ruční vykreslování formuláře ani snippety, které moc rády dělají bordel

iNyxLadis
Člen | 48
+
0
-

jarda256 napsal(a):

Nastav si setRequired při vytváření komponenty místo toho handleru. A stejně bych zvážil zkusit ten NasExt. Nemusí pak řešit ruční vykreslování formuláře ani snippety, které moc rády dělají bordel

Zkoušel jsem různé varianty nastavení setRequiredu(). I přímo při vytváření komponenty. :/ To v tom handleru zbylo při poslendím pokusu. Pokud ho nechám v createcomponentě, tak se právě zdá, že neproběhne vůbec onSuccess. Jako ten doplněk od NasExta vypadá dobře, ještě pouvažuju, třeba bych to teď už dal :)

iNyxLadis
Člen | 48
+
0
-

jarda256 napsal(a):

Nastav si setRequired při vytváření komponenty místo toho handleru. A stejně bych zvážil zkusit ten NasExt. Nemusí pak řešit ruční vykreslování formuláře ani snippety, které moc rády dělají bordel

Ještě se zeptám, zkoušel si, zda ten doplněk bez problému funguje také při editaci záznamu (formuláře), kde závislý selectbox figuruje? Dík

jarda256
Člen | 130
+
0
-

iNyxLadis napsal(a):

jarda256 napsal(a):

Nastav si setRequired při vytváření komponenty místo toho handleru. A stejně bych zvážil zkusit ten NasExt. Nemusí pak řešit ruční vykreslování formuláře ani snippety, které moc rády dělají bordel

Ještě se zeptám, zkoušel si, zda ten doplněk bez problému funguje také při editaci záznamu (formuláře), kde závislý selectbox figuruje? Dík

Editaci jsem nezkoušel, protože v mém případě editaci nepotřebuji

iNyxLadis
Člen | 48
+
0
-

jarda256 napsal(a):

iNyxLadis napsal(a):

jarda256 napsal(a):

Nastav si setRequired při vytváření komponenty místo toho handleru. A stejně bych zvážil zkusit ten NasExt. Nemusí pak řešit ruční vykreslování formuláře ani snippety, které moc rády dělají bordel

Ještě se zeptám, zkoušel si, zda ten doplněk bez problému funguje také při editaci záznamu (formuláře), kde závislý selectbox figuruje? Dík

Editaci jsem nezkoušel, protože v mém případě editaci nepotřebuji

Tak to zkouším na rychlovku překopat. V boostrapu mám na předposledním řádku inicializaci dle dokumentace. A neděje se vůbec nic, na tom jsem ztroskotal i posledně. Nenapadlo by tě, co kde mužu dělat blbě? Selectbox zkrátka vůbec nereaguje

Do main.js jsem přidal

$(function () {
    $('[data-dependentselectbox]').dependentSelectBox();
});

presenter:

$form->addSelect('Cmp_ID', 'Firma', $this->timesheetManager->getCompanies()->fetchPairs('Cmp_ID', 'CmpName1'))
    ->setPrompt('Vybrat firmu')->setRequired();
$form->addDependentSelectBox('Prj_ID', 'Projekt', array($form['Cmp_ID']), function ($values) {
    $data = new DependentSelectBoxData();
    if (isset($values['Cmp_ID'])) {
        $dataProjekt = $this->timesheetManager->getProjectsForSelectbox($values['Cmp_ID']);
        return $data->setItems($dataProjekt);
    }else{
        return $data;
    }
})->setPrompt('Vybrat projekt')->setRequired();

@layout.latte

<body>
        <header>
                <h1>Webová aplikace pro výkaz práce</h1>
        </header>

        <nav>
                <ul>
                        <li><a n:href=":Front:Homepage:">Homepage</a></li>
                        <li><a n:href=":Front:Timesheet:">Evidence práce</a></li>
                        <li><a n:href=":Front:Data:">Správa dat</a></li>
                </ul>
        </nav>
        <br clear="both" />

        {block scripts}
        <script src="{$basePath}/js/jquery.js"></script>
        <script src="{$basePath}/js/netteForms.js"></script>
        <script src="{$basePath}/js/nette.ajax.js"></script>
        <script src="{$basePath}/js/dependentSelectBox.js"></script>
        <script src="{$basePath}/js/main.js"></script>
        {/block}

        {include content} {* Vložení obsahu do šablony. *}

        <footer>

        </footer>


</body>

Model

public function getProjectsForSelectbox($cmpId)
{
        return $this->database->table(self::TABLE_PROJECT)->where(self::TABLE_PROJECT_COMPANY_ID, $cmpId)->fetchPairs('Prj_ID', 'PrjName');
}

Editoval iNyxLadis (13. 12. 2016 17:57)

jarda256
Člen | 130
+
0
-

V config.neon máš zapsán extension? Popřípadě ještě zkus vybrat firmu a koukni do konzole prohlížeče jestli ti tam nehážě nějakou chybu. Já mám layout takto

extensions:
    dependentSelectBox: NasExt\Forms\DI\DependentSelectBoxExtension
{**
 * @param string   $basePath web base path
 * @param array    $flashes  flash messages
 *}
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">

	<title>{ifset title}{include title|stripHtml} | {/ifset}A</title>

	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<meta name="description" content="">
	<meta name="author" content="">
	<link rel="icon" href="{$basePath}/images/favicon.png">
	<link rel="stylesheet" href="{$basePath}/css/project.css">
	{block head}{/block}
</head>

<body class="web">
	<header>
		<nav class="navbar navbar-inverse">
			<div class="container">
				<div class="navbar-header">
					<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
						<span class="sr-only">Toggle navigation</span>
						<span class="icon-bar"></span>
						<span class="icon-bar"></span>
						<span class="icon-bar"></span>
					</button>
					<p class="navbar-text ">
						{if $user->isLoggedIn()}
							Přihlášen: {$user->getIdentity()->username} Role: {$user->getIdentity()->role}
						{/if}
					</p>
				</div>
				<div id="navbar" class="collapse navbar-collapse">
					<ul class="nav navbar-nav" n:inner-foreach="$menuItems as $item => $link">
						<li {ifCurrent $link}class="active"{/ifCurrent}><a n:href="$link">{$item}</a></li>
					</ul>
				</div>
			</div>
		</nav>
		{block header}{/block}
	</header>
	<div class="contentWrap container">
		<div class="content">
			<div n:foreach="$flashes as $flash" class="alert alert-{$flash->type}">{$flash->message}</div>
			{include content}

		</div>
	</div>

	<!--[if lt IE 9]>
	<!-- oldIe:js -->
	<script src="{$basePath}/js/html5shiv.min.js"></script>
	<script src="{$basePath}/js/respond.min.js"></script>
	<!-- endinject -->
	<!--[endif]-->

	<!-- inject:js -->
	<script src="{$basePath}/js/jquery-3.1.1.min.js"></script>
	<script src="{$basePath}/js/nette.ajax.js"></script>
	<script src="{$basePath}/js/live-form-validation.js"></script>
	<script src="{$basePath}/js/happy.min.js"></script>
	<script src="{$basePath}/js/datagrid.min.js"></script>
	<script src="{$basePath}/js/datagrid-instant-url-refresh.min.js"></script>
	<script src="{$basePath}/js/datagrid-spinners.min.js"></script>
	<script src="{$basePath}/js/bootstrap.min.js"></script>
	<script src="{$basePath}/js/bootstrap-datepicker.js"></script>
	<script src="{$basePath}/js/cssrefresh.js"></script>
	<script src="{$basePath}/js/confirm.dialog.js"></script>
	<script src="{$basePath}/js/jquery-ui.min.js"></script>
	<script src="{$basePath}/js/jquery-ui-timepicker-addon.min.js"></script>
	<script src="{$basePath}/js/dateInput.js"></script>
	<script src="{$basePath}/js/chosen.jquery.js"></script>
	<script src="{$basePath}/js/bootstrap-select.min.js"></script>
	<script src="{$basePath}/js/dependentSelectBox.js"></script>
	<!-- endinject -->

	<!-- main:js -->
	<script src="{$basePath}/js/main.js"></script>
	<!-- endinject -->

	{block scripts}{/block}
</body>
</html>
iNyxLadis
Člen | 48
+
0
-

jarda256 napsal(a):

V config.neon máš zapsán extension? Popřípadě ještě zkus vybrat firmu a koukni do konzole prohlížeče jestli ti tam nehážě nějakou chybu. Já mám layout takto

Tohle vypadá OK. Ten extension tam nemusí být, pokud už je inicializováno v bootstrapu nee? Každopádně přidal jsem ho tam pro jistotu. Pustil jsem si jinej prohlížeč (firefox) a tam koukám, že se normálně spustí při kliknutí na firmu ajax a dependent selectbox se nabídne tak jak má. Ale v safari to nefrčí. Napadá tě co je blbě? Cache atd jsem vyčistil

EDIT: Tak jablko si to nějak podrželo :D ještě jednou jsem vyčistil a celé to utnul a už to letí. Kámo tak díky moc.

Editoval iNyxLadis (13. 12. 2016 18:30)

alNath
Člen | 17
+
0
-

Mozem potvrdit ze po vybere hodnoty v selectboxe ajaxom a kliknuti na odoslat, handler na spracovanie formulara sa nezachyti (v tomto pripade timesheetFormSucceeded) a nic sa nestane. Podotykam, ze odoslanie formulara je OK pred tym, nez nastane ajaxovy call.

Tato tema je rozoberana v mnozstve threadov a nikto sa nevyjadril v com moze byt problem.

Dodavam ze ja som postupoval bez externych komponent len s vyuzitim https://blog.nette.org/…-and-pure-js

iNyxLadis napsal(a):

jarda256 napsal(a):

Tak mně to nešlo přesně obráceně. Tam mi to pořád házelo nějaké chyby

Já jsem se postupně těma chybama prokousal, ale tohle mi moc nejde do hlavy jak na to :/

public function handleTimesheetFormChange($cmpId)
{
    if ($cmpId) {
            $selectedProjects = $this->timesheetManager->getProjectsForSelectbox($cmpId);
            $this['timesheetForm']['Prj_ID']->setPrompt('Vybrat projekt')
                ->setItems($selectedProjects);
    } else {
            $this['timesheetForm']['Prj_ID']->setPrompt('Nejprve zvolit firmu')
                ->setItems(array())->setRequired();
    }

    $this->redrawControl('wrapper');
    $this->redrawControl('projectSnippet');
}

public function actionEdit($taskId, $cmpId)
{
    $task = $this->timesheetManager->getTask($taskId);
    if (!$task) {
        $this->error('Úkol nenalezen');
    } else
    {

    if (!$this->isAjax()) {         // pro nastaveni pocatecni hodnoty selectboxu, ve chvíli obsluhy selectboxu se o zbytek stará handle
          $selectedProjects = $this->timesheetManager->getProjectsForSelectbox($cmpId);
          $this['timesheetForm']['Prj_ID']->setItems($selectedProjects);
          $this['timesheetForm']->setDefaults($task);
        }
    }
    }

protected function createComponentTimesheetForm()
{
        $form = new Form;
        $form->addHidden('Tsk_ID'); // kvuli pridavani noveho zaznamu, kde pracuji s ID
        $form->addSelect('Cmp_ID', 'Firma', $this->timesheetManager->getCompanies()->fetchPairs('Cmp_ID', 'CmpName1'))
            ->setPrompt('Vybrat firmu')->setRequired();
        $form->addSelect('Prj_ID', 'Projekt')
            ->setPrompt('Vybrat projekt');
        $form->addText('TskName', 'Obor zájmu')->setRequired();
        $form->addText('TskDescription1', 'Popis úkolu')->setRequired();
        $form->addText('TskDateStart', 'Datum zahájení')->setRequired();
        $form->addText('TskDateEnd', 'Datum ukončení')->setRequired();
        $form->addText('TskTaskmaster', 'Zadavatel')->setRequired();
        $form->addText('TskWorked', 'Odpracováno (hod.)')->setRequired()->addRule(Form::INTEGER, 'Zadejte číselnou hodnotu');
        $form->addSelect('TskUser', 'Provedl', $employees = array(
            "user1" => 'user1',
            "user2" => 'user2',
            "user3" => 'user3',
            "user4" => 'user4',
            "user5" => 'user5',
            "user6" => 'user6',
        ))->setPrompt('Vybrat zaměstnance')->setRequired();
        $form->addSubmit('submit', 'Uložit');
        $form->onSuccess[] = [$this, 'timesheetFormSucceeded'];
        return $form;
}

public function timesheetFormSucceeded($form)
{

        $values = $form->getHttpData();
        unset($values['_submit']);
        unset($values['_do']);

        $this->timesheetManager->saveTask($values);
        $this->flashMessage('Záznam byl uložen.');
        $this->redirect(':Front:Timesheet:');
}
iNyxLadis
Člen | 48
+
0
-

alNath: Já jsem to nakonec opravdu tou komponentou vyřešil, dosáhl jsem funkčního stavu ve všech ohledech, které jsem potřeboval. U vytvoření selectboxu Ajaxem jsem narazil na nepříjemnosti, když jsem daný formulář, ve kterém selectbox je, chtěl editovat.

Každopádně díky za komentář :-)