Řešení vkládání datumu?

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

Zdravím, opět jedna teoretická otázka.

Dejme tomu, že máme aplikaci, kde je potřeba pomocí html/php vkládat datum do databáze. Jak to udělat co nejlépe v Nette?

Napadlo mě udělat si selecty a ty naplnit mesicem/rokem a pak po odeslání formuláře vkládat datum do databáze.
Pak mě napadla varianta s využitím ajaxu nebo javascriptu.
A asi uplně nejhorší je použít obyčejný text-box a čas si pak naformátovat ručně, ale to mi přijde nejhorší?

Any idea?:-)

kravčo
Člen | 721
+
0
-

TanisCZ napsal(a):

Zdravím, opět jedna teoretická otázka.

Dejme tomu, že máme aplikaci, kde je potřeba pomocí html/php vkládat datum do databáze. Jak to udělat co nejlépe v Nette?

Napadlo mě udělat si selecty a ty naplnit mesicem/rokem a pak po odeslání formuláře vkládat datum do databáze.
Pak mě napadla varianta s využitím ajaxu nebo javascriptu.
A asi uplně nejhorší je použít obyčejný text-box a čas si pak naformátovat ručně, ale to mi přijde nejhorší?

Any idea?:-)

To podľa mňa dosť záleží od použitia. Mňa osobne napríklad selectboxy pri dátume dosť vytáčajú a rád ho zadávam do jediného textového políčka, iné to môže byť u užívateľa, ktorý je na selectboxy odniekiaľ zvyknutý a nemôže bez nich existovať. Teda, podľa mňa znie otázka skôr: „Ako to urobiť čo najlepšie, aby to vyhovovalo používateľom.“


samozrejme nechcem zadávať dátum v SQL formáte 2008-11-05 ale podľa slovenských/českých pravidiel 5.11.2008

A.
Člen | 87
+
0
-

Ja to delam asi takto (s vyuzitim jquery ui datapickeru).

<?php
require_once LIBS_DIR . '/Nette/Forms/Controls/FormControl.php';

class Calendar extends Nette\Forms\FormControl
{
	private $name;
	private $el;

	public function __construct($name, $label)
	{ # {{{
		parent::__construct($label);

		$this->name = $name;
		$this->control->name = $name;
		$this->control->type = 'text';
		$this->control->id = $name;

	} # }}}


	public function getValue()
	{ # {{{
		if (strlen($this->value)) {
			$tmp = explode('.', $this->value);
			// tady si to preved na format, kterej vyzaduje db.
			return $tmp[2] . '-' . $tmp[1] . '-' . $tmp[0];
		}

		return $this->value;
	} # }}}


	public function getControl()
	{ # {{{
		$this->control->value = $this->value;
		ob_start();
		echo $this->control;
		echo '<script type="text/javascript">

		$("#' . $this->name . '").datepicker($.extend({},
			$.datepicker.regional["cs"], {
		    	showOn: "both",
				dateFormat: "dd.mm.yy",
				defaultDate: "' . $this->value . '",
				buttonImage: "' . ICON_CALENDAR . '",
				buttonImageOnly: true,
				buttonText: "Vybrat z kalendáře"
			}));
		</script>';
		return ob_get_clean();
	} # }}}
}
?>

Pak si jen udelej nejakou vlastni class rozsirenim Nette Formu, pridas metodu addCalendar a je po starostech :-). Samozrejme, ze si takto muzes udelat i variantu s trema inputama apod.

TanisCZ
Člen | 80
+
0
-

Velice, velice zajímáavé řešení a krásný kod.

Zkusim to testnout někdy koncem týdne :)

Dík za odpovědi

TanisCZ
Člen | 80
+
0
-

Tak jsem na to koukal a nedaří se mi přijít jak z toho příkladu dokončít tvorbu toho formuláře.
Popravdě nikdy jsem nevyužil třídu, která by dědila od FormControl.

Formuláře dělám tak, že je v presenteru připravim, vykreslim a pomoci handlerů odchytávám stisk tlačítek? Mohl by jsi ten příklad ještě rozvézt víc do hloubky?

Díky moc a sorry za otravování, přeci jen jsou ještě místa, kde je pro mě Nette celkem neznámé…

A.
Člen | 87
+
0
-

Treba takto? :-)

<?php
class MyTurboForm extends Nette\Application\AppForm
{
	public function addCalendar($name, $label)
	{ # {{{
		return $this[$name] = new MyTurboCalendar($name, $label);
	} # }}}
}
...
$form = new MyTurboForm($presenter, 'form');
$form->addCalendar('calendar', 'Kalendar:');
$form->addSubmit('submit', 'Odeslat');

?>

Editoval A. (10. 11. 2008 13:40)

RaR
Člen | 42
+
0
-
<?php
$form = new AppForm($this, 'form');

$form->addText('termineDate', 'Datum:')
     ->addRule(FORM::REGEXP, 'Datum není zadáno správně. Použij formát d.m.y','/[0-9]+/')
     ->addRule('MyLib::validateDate', 'Chybně zadané datum.');
?>

Mohl by mě někdo prosím poradit, jak provést validaci datumu?
S validací pomocí FORM::REGEXP zase nemůžu najít správný regulární výraz.
Představoval bych si něco jako

<?php
'0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.](19|20)\d\d'
?>

ale nette říká, že výraz není kompaktibilní s javou.
V tom vlastním validátoru bych to taky mohl nějak kontrolovat, ale asi potřebuju aspoň nějaký rozumný formát toho řetězce.

Dál bych se chtěl zeptat, jak docílit toho, aby po odeslání formuláře se chybně vyplněné položky zobrazily vypsané nad formulářem (nebo jestli to jde, tak pod ním, nebo jinde a třeba červeně, asi pomocí css) a ne javou. Jednou mě to udělá tak a podruhý jinak, asi podle nálady.

S tím nápadem od A. s datepickerem jsem strávil půl dne a nepodařilo se to rozchodit, tak jsem se vrhl na cestu addText, ale taky tápu. Už mě to nějak přestává bavit, tak zkouším hledat pomoc.
Děkuji.

kravčo
Člen | 721
+
0
-

RaR napsal(a):

<?php
$form = new AppForm($this, 'form');

$form->addText('termineDate', 'Datum:')
     ->addRule(FORM::REGEXP, 'Datum není zadáno správně. Použij formát d.m.y','/[0-9]+/')
     ->addRule('MyLib::validateDate', 'Chybně zadané datum.');
?>

Mohl by mě někdo prosím poradit, jak provést validaci datumu?
S validací pomocí FORM::REGEXP zase nemůžu najít správný regulární výraz.
Představoval bych si něco jako

<?php
'0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.](19|20)\d\d'
?>

ale nette říká, že výraz není kompaktibilní s javou.

chýbajú ti tam delimitery, ono to totiž nie je ani platný perl-compatible regulárny výraz, a keďže Nette najprv kontroluje kompatibilitu s javascriptom, tak PCRE sa k slovu ani nedostane… tým pádom budeš samozrejme musieť v regulári použité slashe escapovať…

IMHO takýto výraz síce vyzerá super rafinovane, no na správny dátum nestačí, totiž preň platný dátum 02/31/2007 platný v skutočnosti nie je. Ja používam na kontrolu formátu veľmi benevolentný regulárny výraz /^\s*\d{1,2}\s*\.\s*\d{1,2}\s*\.\s*(?:\d{2}|\d{4})\s*$/, ktorý odhaľuje najmä preklepy a následne vo vlastnom validátore spravím ozajstnú validáciu.

V tom vlastním validátoru bych to taky mohl nějak kontrolovat, ale asi potřebuju aspoň nějaký rozumný formát toho řetězce.

Dál bych se chtěl zeptat, jak docílit toho, aby po odeslání formuláře se chybně vyplněné položky zobrazily vypsané nad formulářem (nebo jestli to jde, tak pod ním, nebo jinde a třeba červeně, asi pomocí css) a ne javou. Jednou mě to udělá tak a podruhý jinak, asi podle nálady.

ak sa nemýlim, štandardne (pri použítí ConventialRenderer:https://api.nette.org/…enderer.html) sa chyby vykresľujú do <ul class="error">...</ul> elementu pred samotný formulár, stačí pridať jemu zodpovedajúce css pravidlo a budú červené.

opravený regulár – chýbajúce spätné lomítko v časti pre mesiac

Editoval kravco (20. 11. 2008 19:23)

RaR
Člen | 42
+
0
-

Děkuji za radu, zkusil jsem to ale nevím, jestli správně

<?php
$form->addText('termineDate', 'Datum:')
     ->addRule(FORM::REGEXP, 'msg','/^\s*\d{1,2}\s*\.\s*d{1,2}\s*\.\s*(?:\d{2}|\d{4})\s*$/')
     ->addRule('MyLib::validateDate', 'Neplatné datum.');
?>

datum 1.1.2008 se vyhodnotí jako chyba.

Pořád mě při validaci vyskakují ty java hlášky. Vyskakují i u vzorových forms z distribuce. (browser Mozzila)

kravčo
Člen | 721
+
0
-

RaR napsal(a):

Děkuji za radu, zkusil jsem to ale nevím, jestli správně

<?php
$form->addText('termineDate', 'Datum:')
     ->addRule(FORM::REGEXP, 'msg','/^\s*\d{1,2}\s*\.\s*d{1,2}\s*\.\s*(?:\d{2}|\d{4})\s*$/')
     ->addRule('MyLib::validateDate', 'Neplatné datum.');
?>

datum 1.1.2008 se vyhodnotí jako chyba.

chybička v regulári… už je opravený…

Pořád mě při validaci vyskakují ty java hlášky. Vyskakují i u vzorových forms z distribuce. (browser Mozzila)

ak tým myslíš úplne vypnúť javascript validáciu, tak sa to riešilo inde na fóre.

kravčo
Člen | 721
+
0
-

dokonca aj tento je zbytočne dlhý, Nette totiž zo všetkých textových políčok už pred validáciou odstráni medzery zo začiatku a konca, teda zjednodušený vyzerá takto:

/^\d{1,2}\s*\.\s*\d{1,2}\s*\.\s*(?:\d{2}|\d{4})$/
xTrip
Člen | 15
+
0
-

Díky za dobrý typ.

Nabízím drobné vylepšení zapracování předchozího kódu:

<?php
  /**
   * Calendar support
   *
   * @param FormContainer $_this
   * @param string $name
   * @param string $label
   * @return unknown
   */
  function FormContainer_prototype_addCalendar(FormContainer $_this, $name, $label)
  {
    return $_this[$name] = new DatePicker($name, $label);
  }
?>

k tomu samozřejmě kód z příspěvku #3 od A. – díky moc

Ovšem mně to nešlo, jednak kvůli zřejmě překlepu ve velikosti písmen a jednak kvůli chybějicí lokalizaci (v manuálu je to jinak a patřičný soubor jsem nenašel) – přikládám upravený kód, tak jak mně funguje

<?php
require_once LIBS_DIR . '/Nette/Forms/Controls/FormControl.php';

class DatePicker extends /*Nette\Forms\*/FormControl
{
        private $name;
        private $el;

        public function __construct($name, $label)
        { # {{{
                parent::__construct($label);

                $this->name = $name;
                $this->control->name = $name;
                $this->control->type = 'text';
                $this->control->id = $name;

        } # }}}


        public function getValue()
        { # {{{
                if (strlen($this->value)) {
                        $tmp = explode('.', $this->value);
                        // tady si to preved na format, kterej vyzaduje db.
                        return $tmp[2] . '-' . $tmp[1] . '-' . $tmp[0];
                }

                return $this->value;
        } # }}}


        public function getControl()
        { # {{{
                $this->control->value = $this->value;
                ob_start();
                echo $this->control;
                echo '<script type="text/javascript">
                      $("#' . $this->name . '").datePicker({clickInput:true})
                      </script>';
                /*echo '<script type="text/javascript">

                $("#' . $this->name . '").datePicker($.extend({},
                        $.datePicker.regional["cs"], {
                        showOn: "both",
                                dateFormat: "dd.mm.yy",
                                defaultDate: "' . $this->value . '",
                                buttonImage: "' . ICON_CALENDAR . '",
                                buttonImageOnly: true,
                                buttonText: "Vybrat z kalendáře"
                        }));
                </script>';*/
                return ob_get_clean();
        } # }}}
}
<!-- jQuery -->
<script type="text/javascript" src="/js/jquery-1.2.6.min.js"></script>

<!-- required plugins -->
<script type="text/javascript" src="/js/date.js"></script>
<!--[if IE]><script type="text/javascript" src="scripts/jquery.bgiframe.js"></script><![endif]-->

<!-- jquery.datePicker.js -->
<script type="text/javascript" src="/js/jquery.datePicker-2.1.1.js"></script>
<!-- css -->
<link type="text/css" href="/css/datePicker.css" media="screen,projection,tv" rel="stylesheet">

A pak lze používat jednoduše

$form = new Form;
$form->addCalendar('datum', 'Kdy to bude?');
....

Tak snad to pomůže všem, kteří po půl dni propadli depresi :-)

Golf

Editoval xTrip (6. 12. 2008 20:45)