Skip to content

Commit db81b15

Browse files
DateTime, Date and Time inputs (#31)
1 parent b29b6db commit db81b15

21 files changed

+2982
-37
lines changed

.docs/README.md

Lines changed: 193 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,21 @@
33
## Content
44

55
- [Setup](#setup)
6-
- [ApplicationFormFactoryExtension - provides Nette\Application\UI\Form factory](#application-form-factory)
7-
- [StandaloneFormFactoryExtension - provides Nette\Forms\Form factory](#standalone-form-factory)
6+
- Form factory DI extensions
7+
- [ApplicationFormFactoryExtension](#application-form-factory) (Nette\Application\UI\Form)
8+
- [StandaloneFormFactoryExtension](#standalone-form-factory) (Nette\Forms\Form)
9+
- Controls
10+
- [Date/time inputs](#date-time-inputs) (DateTimeInput, DateInput, TimeInput)
811

912
## Setup
1013

1114
```bash
1215
composer require contributte/forms
1316
```
1417

15-
## Application Form Factory
18+
## DI extensions
19+
20+
### Application Form Factory
1621

1722
ApplicationFormFactory returns instance of `Nette\Application\UI\Form`. It should be used in place of StandaloneFormFactory if [nette/application](https://github.com/nette/application) is installed.
1823

@@ -85,7 +90,7 @@ final class UserFormFactory
8590
}
8691
```
8792

88-
## Standalone Form Factory
93+
### Standalone Form Factory
8994

9095
StandaloneFormFactory returns instance of `Nette\Forms\Form`. It should be used only if [nette/application](https://github.com/nette/application) is not installed.
9196

@@ -157,3 +162,187 @@ final class UserFormFactory
157162

158163
}
159164
```
165+
## Controls
166+
167+
### Date/time inputs
168+
169+
Features:
170+
* support both native date/time/datetime-local html inputs and text input with custom format
171+
* in custom format text input variant accept multiple formats
172+
* can be configured to return value as `\DateTime`, `\DateTimeImmutable` object or any offspring (like `\Nette\DateTime` or `\Carbon\DateTime`)
173+
* can be configured to return value as any object by setting callback that would transform DateTimeImmutable to required type (for example `\Brick\DateTime\LocalDate`)
174+
* set (default) value by `\DateTimeInterface` object, string (in configured or any of standard formats) or int timestamp
175+
* pass parameters (like formats, min/max, custom settings) to data attributes of control (so it can be used to configure JS date picker)
176+
* support MIN, MAX and RANGE rules
177+
* can handle different input/server timezones
178+
179+
#### Usage
180+
181+
You can either register extension methods by calling
182+
183+
```php
184+
\Contributte\Forms\Controls\DateTime\DateTimeInput::register();
185+
\Contributte\Forms\Controls\DateTime\DateInput::register();
186+
\Contributte\Forms\Controls\DateTime\TimeInput::register();
187+
```
188+
189+
then you can use it simply as
190+
191+
```php
192+
$form = new \Nette\Forms\Form();
193+
$form->addDateTime('datetime', 'Enter date and time');
194+
$form->addDate('date', 'Enter date');
195+
$form->addTime('time', 'Enter time');
196+
```
197+
198+
Without additional parameter it will create native HTML5 inputs. If you want to create custom format text input add parameter with desired format.
199+
200+
```php
201+
// to register extension method to add custom format text inputs by default
202+
\Contributte\Forms\Controls\DateTime\DateTimeInput::register('d.m.Y H:i');
203+
204+
// or for single input
205+
$form->addDateTime('datetime', 'Enter date and time', 'd.m.Y H:i');
206+
```
207+
208+
Alternatively you can manually create control instance and add it to form
209+
210+
```php
211+
$form = new \Nette\Forms\Form();
212+
$control = new DateTimeInput($label);
213+
$form->addComponent($control, $name);
214+
```
215+
216+
or you can add this as method to your base form
217+
218+
```php
219+
220+
class MyForm extends \Nette\Forms\Form
221+
{
222+
223+
public function addDateTime(string $name, ?string $label = null)
224+
{
225+
$form = new \Nette\Forms\Form();
226+
$control = new DateTimeInput($label);
227+
$form->addComponent($control, $name);
228+
return $control;
229+
}
230+
231+
}
232+
```
233+
234+
#### Native input types (datetime-local, date, time)
235+
236+
Default mode for all date/time inputs is to render native HTML5 inputs.
237+
* DateTimeInput `<input type="datetime-local" />`
238+
* DateInput `<input type="date" />`
239+
* TimeInput `<input type="time" />`
240+
241+
#### Text input type - formats
242+
243+
If you set optional parameter `$format` then text input is generated and input is parsed against given format.
244+
245+
```php
246+
$control = new DateTimeInput($label, "d.m.Y H:i");
247+
```
248+
249+
* DateTimeInput `<input type="text" data-format="Y-m-d H:i" />`
250+
* DateInput `<input type="text" data-format="Y-m-d"/>`
251+
* TimeInput `<input type="text" data-format="H:i"/>`
252+
253+
You can set multiple accepted formats. First of then is considered as desired format and will be passed to rendered HTML.
254+
255+
```php
256+
$control = new DateTimeInput($label, ["d.m.Y H:i", "Y-m-d H:i"]);
257+
```
258+
259+
#### Returned value type
260+
261+
All inputs return value as \DateTimeImmutable by default, but you can change value type.
262+
263+
You can set vale type to any class implementing \DateTimeInterface.
264+
265+
```php
266+
$control->setValueType(\DateTime::class);
267+
```
268+
```php
269+
$control->setValueType(\Nette\Utils\DateTime::class);
270+
```
271+
272+
Or set any factory callback that creates required value type from DateTimeInterface
273+
```php
274+
$control->setValueType([\Brick\DateTime\LocalDate::class, 'fromNativeDateTime'])
275+
```
276+
```php
277+
$control->setValueType(function (\DateTimeImmutable $value) {
278+
return new MyValueType($value);
279+
});
280+
```
281+
282+
You can also manually get value as different type using method `getValueAs` that accepts same argument as `setValueType`:
283+
```php
284+
$control->setValueAs(\DateTime::class);
285+
```
286+
287+
#### Default value
288+
289+
Default value can se set as:
290+
291+
* \DateTimeInterface object
292+
* string with any custom format
293+
* string with of standard date/time formats (for example "Y-m-d H:i:s")
294+
* int representing timestamp.
295+
296+
#### Data attributes - for JavaScript picker
297+
298+
If you use custom format text input then all relevant settings are aautomatically passed to rendered HTML in form of data attributes. So oyu can use then to initialize your favourite JavaScript datetime picker.
299+
300+
* `data-format="..."` - desired value format
301+
* `data-value="..."` - value in standard format
302+
* `data-min="..."` - minimal value in standard format
303+
* `data-max="..."` - maximal value in standard format
304+
* `data-settings="..."` - additional settings in JSON (see bellow)
305+
306+
Note: Standardized formats are same as for related HTML5 native inputs - "Y-m-d H:i", "Y-m-d" or "H:i".
307+
308+
To set additonal settings use:
309+
```php
310+
$control->setOption('settings', ['option1' => 'val1', 'option2' => 2]);
311+
```
312+
313+
#### Validation - min, max, range, invalidFormat
314+
315+
Validation of minimum, maximum and range is supported. Validation arguments accepts same values as setValue.
316+
317+
```php
318+
$control->addRule(Form::RANGE, 'Range %d - %d', [
319+
new DateTimeImmutable('2022-01-05 12:15:00'),
320+
new DateTimeImmutable('2022-01-05 12:45:00')]
321+
);
322+
```
323+
324+
#### DateTimeInput - input timezone
325+
326+
DateTime input does not do any timezone conversions by default.
327+
328+
Values are transformed to/from input format as they are and timezone information is ignored or expected to be same as server timezone. This is all right as long as you server time zone, client timezone and all values timezone matches.
329+
330+
You can enable timezone conversions for given input by setting optional parameter `$inputTimezone`.
331+
332+
```php
333+
$control = new DateTimeInput($label, "d.m.Y H:i", new DateTimeZone("America/New_York"));
334+
```
335+
336+
Then all values (`setValue`, `setDefaultValue`, `addRule`) are converted to selected timezone before transforming it to given format. And returned value from control have given input timezone set.
337+
338+
You can also manually get value as in different Time zone using `getValueInTz` or `getValueInTzAs`. If timezone argument is null then default server timezone is used.
339+
```php
340+
$control->setValue(); // value in input timezone
341+
$control->setValueInTz(); // value in server default timezone
342+
$control->setValueInTz(new DateTimeZone('Americe/New_York')); // value in given timezone
343+
```
344+
```php
345+
$control->setValueAs(DateTime::class); // value in input timezone as \DateTime
346+
$control->setValueInTzAs(DateTime::class); // value in server default timezone as \DateTime
347+
$control->setValueInTzAs(DateTime::class, new DateTimeZone('Americe/New_York')); // value in given timezone as \DateTime
348+
```

composer.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@
4444
"Contributte\\Forms\\": "src"
4545
}
4646
},
47+
"autoload-dev": {
48+
"psr-4": {
49+
"Tests\\Fixtures\\": "tests/fixtures"
50+
}
51+
},
4752
"config": {
4853
"sort-packages": true,
4954
"allow-plugins": {

ruleset.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
<properties>
99
<property name="rootNamespaces" type="array">
1010
<element key="src" value="Contributte\Forms"/>
11+
<element key="tests/fixtures" value="Tests\Fixtures"/>
1112
</property>
1213
</properties>
1314
</rule>

0 commit comments

Comments
 (0)