Nette/Forms – addDatetime smazatelný?

dms
Člen | 94
+
0
-

Ahoj, zkouším nově přidané metody addDatetime etc. Ale nemůžu přijít na to, jak udělat aby bylo pole nullable? Vždy to vrací aktuální datum i pokud není v HTML formu nic vyplněno. Nelze pak datum vůbec vymazat.

Pavel Kravčík
Člen | 1195
+
0
-

My jsme to v našem rozšíření dělali tak, že jsme dědili TextBase kvůli nullable, akorát ve forms: 3.1.13 už to takhle snadno nepůjde.

David Grudl
Nette Core | 8227
+
+3
-

fixed

dms
Člen | 94
+
0
-

díky, je to boží. Ještě addColor a můžu v aplikaci úplně vynechat setHtmlType :)

David Grudl
Nette Core | 8227
+
+2
-

Je fakt, že podpora color už je napříč prohlížeči plná, tak ho přidat můžu.

m.brecher
Generous Backer | 871
+
0
-

@DavidGrudl

Prosím doplnit do nových DateTimeControl prvků (addDate(), addDateTime(), addTime()) automatickou hodnotu setOption(‚type‘, ‚datetime‘). Všechny existující formulářové prvky mají hodnotu ‚type‘ automaticky nastavenu.

Já tato option používám pro nastavení custom css tříd ve formulářích:

$class = $component->getControl()->getAttribute('class');

$class .= $class ? ' ' : '';
$class .= match($component->getOption('type')){
    'text', => 'text-input block-input',
    'increment', => 'increment-input block-input',
    'datetime' => 'date-input block-input',               // toto option nyní chybí
    'textarea' => 'text-area-input block-input',
    'select' => 'select-input block-input',
    'checkbox' => 'checkbox',
    'radio' => 'radio',
    'file' => 'upload-input',
    'dialogButton' => 'submit-button',
    'button' => $component instanceof SubmitButton
        ? 'submit-button'
        : 'control-button',
    default => '',
};

evromalarkey
Nette Blogger | 20
+
0
-

@DavidGrudl vesměs u všech input typů by měla být dobrá podpora v prohlížečích až na week a month, viz. https://developer.mozilla.org/…lement/input#…, ale ty se dají přípaně polyfillovat

David Grudl
Nette Core | 8227
+
+2
-

@mbrecher doplním

m.brecher
Generous Backer | 871
+
-1
-

@PavelKravčík

My jsme to v našem rozšíření dělali tak, že jsme dědili TextBase kvůli nullable

To by mě docela zajímalo, jaké potíže jste měli s nullable ve formulářích ?? Formuláře Nette vracejí pro nevybranou hodnotu (nullable) prázdný řetězec, což je v souladu s html normami. Nullable problémy začínají v okamžiku, kdy jdeme ukládat nullable data do databáze. Kupříkladu, když chci uložit '' do MySQL tabulky do sloupce typu int, který je nullable, obdržím chybovou hlášku „Incorrect integer value“, což je správně, protože jsem měl ukládat null. Stejný problém vyvstane, když půjdu uložit „nullable“ hodnotu '' z html inputu datetime-local, který když není vybráno datum vrací '';

Také jsem zkoušel tento problém fixovat přímo ve formulářovém custom inputu, který jsem si pro Date/DateTime udělal, protože v Nette chyběly. Custom input vracel místo "" hodnotu null. Ono to takto funguje. Jenže jsem došel k názoru, že je to nesprávný postup a jediné správné místo, kde by se mělo řešit nastavení nullable hodnot je databázová knihovna.

Téma ukládání nullable do databáze je ale OT tohoto vlákna a tak na toto téma založím nové vlákno k diskuzi. Je to složitější než na první pohled vypadá.

David Grudl
Nette Core | 8227
+
+1
-

@mbrecher předpokládám, že tím myslel, že nemůže přepsat metodu addDatetime() protože nevrací TextBase. Nicméně nullable se tohle téma stejně vůbec jinak netýká.

m.brecher
Generous Backer | 871
+
-2
-

@DavidGrudl

Nicméně nullable se tohle téma stejně vůbec jinak netýká.

Ano, netýká, proto budu pokračovat v novém vláknu „nullable“. Z příspěvku @PavelKravčík je ale vidět, že lidi s nullable hodnotami určitý problém mají a každý se to snaží řešit, jak nejlíp umí. Mělo by se to rozebrat v novém vlákně.

dms
Člen | 94
+
+1
-

@DavidGrudl koukám že type=color nelze vlastně nulovat a nulová hodnota je černá, což je totální shit. Všechny ostatní html inputy jdou normálně mazat, ale tohle ne. Pro úplnou podporu výběru barvy, aby šlo mít i prázdnou hodnotu to asi nepůjde bohužel použít

Pavel Kravčík
Člen | 1195
+
0
-

m.brecher napsal(a):

@DavidGrudl

Nicméně nullable se tohle téma stejně vůbec jinak netýká.

Ano, netýká, proto budu pokračovat v novém vláknu „nullable“. Z příspěvku @PavelKravčík je ale vidět, že lidi s nullable hodnotami určitý problém mají a každý se to snaží řešit, jak nejlíp umí. Mělo by se to rozebrat v novém vlákně.

Asi nemusíš nové vlákno. Po vydání nové verze jsou tyhle informace stejně nepodstatné. Když to rychle shrnu:

  • AddDate jsme si dali do naší nadstavby před několika roky (dřív JS datepicker)
  • Používáme s ORM (entity public ?\Datetime date_publish)
$form->addDate('date_publish', 'Datum publikování článku')
  ->setNullable();

//success Form
$entity->date_publish = $values->date_publish;
Pepiik
Člen | 10
+
0
-

addTime je super.
@DavidGrudl Šlo by plnit pomocí ActiveRow kde se na TIME používá DateInterval?

m.brecher
Generous Backer | 871
+
0
-

@DavidGrudl

prvek addTime() vrací v objektu DateTimeImmutable hodnotu ‚0000–01–01 17:53:00.000000‘. Tuto hodnotu nelze uložit do MySQL sloupce DATETIME:

Invalid datetime format: 1292 Incorrect datetime value: '0000-01-01 17:53:00' for column 'my_time'

Napadlo mne, vzhledem k tomu, že datumová část není nastavena na ‚0000–00–00‘, ale na ‚0000–01–01‘, jestli nebylo záměrem umožnit uložení Time i do sloupce DATETIME, jehož rozsah začíná na ‚1000–01–01 00:00:00‘, kdyby addTime() vracel ‚1000–01–01 17:53:00.000000‘ tak by to šlo.

David Grudl
Nette Core | 8227
+
0
-

DateTimeImmutable nemuže mít den a měsíc 00, protože to je mimo povolené hodnoty (i ten rok 0 je nesmysl, ale to projde). Naopak s uložením 0000-01-01 17:53:00 do MySQL žádný problém nemám…

Marek Bartoš
Nette Blogger | 1274
+
+2
-

do MySQL sloupce DATETIME

time → time
datetime → datetime / timestamp
date → date

?

m.brecher
Generous Backer | 871
+
0
-

@DavidGrudl

DateTimeImmutable nemuže mít den a měsíc 00, protože to je mimo povolené hodnoty

aha to jsem nevěděl, díky hodnotě datumu ‚0000–01–01‘ lze addTime() uložit do MySQL TIME a nejde uložit do MySQL DATETIME, což je ideální řešení.

David Grudl
Nette Core | 8227
+
0
-

@mbrecher jak jsem psal, s uložením do MySQL DATETIME žádný problém nemám. MySQL 8.0.24

dms
Člen | 94
+
0
-
  • addDate, addDatetime a addTime – vyzkoušeno a funguje super
  • addColor – funguje jak má, ale bohužel nelze hodnotu mazat (což je default chování browserů), takže stále potřeba workaround

Ještě jsem procházel aplikaci a máme tam často tyto případy (jen taková idea co by se mi líbilo):

$form->addText('tel')->setHtmlType('tel');

// $form->addTel('tel') by bylo víc cool

a

$form->addText('recipients', 'E-mail příjemnce (nebo více oddělené čárkou)');
$form->setHtmlType('email');
$form->setHtmlAttribute('multiple');

// $form->addEmail() s možností parametru multiple
// a automatickou validací zda jsou zadány jen validní e-maily oddělené čárkou
David Grudl
Nette Core | 8227
+
0
-

Jakou konkrétní výhodu má ten tel?

Pavel Kravčík
Člen | 1195
+
+1
-

Dá se tam dát pattern v HTML a na telefonech se například zobrazuje „volat“ a „speciální klávesnice na čísla bez písmen“, když máš on-focus.

Editoval Pavel Kravčík (3. 11. 2023 14:50)

dms
Člen | 94
+
0
-

Ano přesně tak, většina těch type u inputů mění klávesnici na telefonu více přizpůsobenou danému inputu a nebo přidává drobné vylepšení (třeba search input dává ikonu na smazání inputu) více o jednotlivých inputech pak zde:

https://developer.mozilla.org/…lement/input

m.brecher
Generous Backer | 871
+
-1
-

@MarekBartoš

time → time
datetime → datetime / timestamp
date → date

Ano, použít v MySQL odpovídající typ pro datum a čas je ideální. Ale:

MySQL type TIME je v Nette Explorer problematicky podporován. ActiveRow z databázové knihovny vrací nikoliv Nette\Utils\DateTime, ale DateInterval. Ten nelze jednoduše vykreslit v šablonách latte:

{$row->datetime}  {* MySQL DATETIME - latte vykreslí *}

{$row->date}  {* MySQL DATE - latte vykreslí *}

{$row->time}  {* MySQL TIME - latte NEUMÍ vykreslit *}

{$row->time|date 'H:i'}  {* MySQL TIME - toto filtr latte také NEUMÍ *}

Jak zaznělo v této diskuzi, nově přidaný prvek addTime() také nedokázal načíst čas z objektu DateInterval, což @DavidGrudl bleskově opravil, ale ne tak, že by změnil v ActiveRow DateInterval na Nette\Utils\DateTime s datumem ‚0000–01–01‘, ale přidal do addTime() schopnost zpracovat i DateInterval.

Jenže situace jaká byla v addTime() je i v šablonách Latte (code samply výše). Pokud by někdo opravdu chtěl použít pro čas typ MySQL TIME, tak si bude muset pro latte udělat speciální filtr.

Udělat si pro MySQL TIME speciální latte filtr není složité, nevyřeší se tím ale přímý výpis bez filtru {$row->time}, což se často používá při psaní šablon – nejprve nahodím do šablony data, až potom doplním filtry.

Nebo použít pro čas MySQL DATETIME – také ne ideální. V budoucnu bychom mohli využívat metadata uložená v MySQL serveru jako support pro automatické generování formulářů. Když budou správně nastaveny datové typy, tak pro DATE použijeme ve formuláři prvek addDate(), pro DATETIME použijeme addDateTime() a pro TIME použijeme addTime().

Ideální je věci nekomplikovat a mít stejné API pro datum a čas jak ve formulářích, tak v databázi, tak i v databázových tabulkách – tedy používat pro čas MySQL typ TIME, ale zbavit se DateInterval-u v ActiveRow.

Ještě je zde možnost jít v Latte stejnou cestou jako v addTime() a pozměnit latte tak, aby si automaticky převedlo DateInterval na Nette\Utils\DateTime. To by řešilo skoro vše, ale pořád zde zůstane nekonzistentní DateInterval v ActiveRow pro sloupec TIME.

Přitom DateInterval není nic speciálně navrženého jenom pro čas, umožňuje vyjádřit časový interval i v letech a měsících, takže by nejlepší ho z Nette úplně vyřadit. Bohužel je to BC, ale čas se moc nepoužívá a většina lidí bezpochyby stejně pro čas používá DATETIME právě kvůli nemožnosti výpisu v latte.

Editoval m.brecher (3. 11. 2023 17:21)

Pepino
Člen | 257
+
0
-

@mbrecher MySQL sloupec time není určen pro čas ve smyslu 0–23h ale pro časový interval. HTML input time je pouze pro 0–23h. Takže je správně, že vrací DateInterval.

Kamil Valenta
Člen | 820
+
0
-

evromalarkey napsal(a):

@DavidGrudl vesměs u všech input typů by měla být dobrá podpora v prohlížečích až na weekmonth

Jen na okraj: datetime-local má trochu nepříjemnou podporu ve Firefoxu, kde picker nabízí jen datum a čas se musí dopsat ručně. Jiné prohlížeče nabízí picker pro datum i pro čas.

m.brecher
Generous Backer | 871
+
0
-

@Pepino

@mbrecher MySQL sloupec time není určen pro čas ve smyslu 0–23h ale pro časový interval. HTML input time je pouze pro 0–23h. Takže je správně, že vrací DateInterval.

Díky za připomínku, máš pravdu, dokumentace MySQL: „TIME values may range from ‚-838:59:59‘ to '838:59:59“ a záměrem je poskytnout typ TIME: a) pro reprezentaci času během dne (0–24 h), b) pro reprezentaci časového intervalu mezi dvěma událostmi.

Proto je jak píšeš pro typ MySQL TIME správná reprezentace v ActiveRow pomocí DateInterval. Ze stejného důvodu není vhodné aby Latte automaticky vykreslovalo DateInterval jako čas, protože vývojář musí určit, zda se jedná o čas nebo časový interval.

Pak je nejlepším řešením navrhovat pro Nette aplikace datové typy pro datum a čas v MySQL takto:

date → DATETIME nebo DATE
datetime → DATETIME
time → DATETIME, nikdy TIME
dateInterval → TIME

Ne každého napadne, že by neměl v aplikacích Nette používat pro time TIME, protože dokumentace MySQL ho k tomu naopak vybízí: „je určen a) pro čas během dne, b) pro časový interval“. Viz příspěvek uživatele @Pepiik , který pro time používá typ TIME, jak vyplývá z jeho příspěvku: https://forum.nette.org/…e-smazatelny#…

Hledal jsem v dokumentaci Database\Explorer popis formátů sloupců v objektu ActiveRow, ale nic jsem nenašel. Asi by bylo vhodné doplnit do dokumentace Database\Explorer samostatný odstavec s popisem objektu ActiveRow, popsat formáty výstupních dat + doporučit optimální datové typy MySQL pro datum a čas a vysvětlit proč. Stejně tak vysvětlit jak Nette pracuje s nullable hodnotami (formuláře) a doporučit nějaký optimální postup (setNulable(), setPrompt(), …). Zkusím nějaké PR napsat.

Editoval m.brecher (3. 11. 2023 20:55)