diff --git a/.gitignore b/.gitignore
index 302e2f7..629ebde 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@
/vendor
/composer.lock
/tests/output
+/.idea
diff --git a/readme.md b/readme.md
index 20ea1c8..4610c01 100644
--- a/readme.md
+++ b/readme.md
@@ -11,7 +11,7 @@ In PHP this addon works with DateTime objects, in the browser it uses jqueryUI c
[](https://packagist.org/packages/voda/date-input)
-JS dependencies
+JS dependencies (recomended)
---------------
* [jQuery](http://jquery.com/) and [jQueryUI](http://jqueryui.com/)
* [Timepicker addon](http://trentrichardson.com/examples/timepicker/) version 1.1.0 or newer
@@ -30,11 +30,28 @@ insert required javascript and style files into your layout (order of scripts is
```
-register the addon in your bootstrap.php:
-```
+
+### Registering
+
+#### Register the addon in your bootstrap.php
+
+```php
Vodacek\Forms\Controls\DateInput::register();
```
+
+#### Or use DI extension
+
+config.neon:
+
+```neon
+extensions:
+ dateInput: Vodacek\Forms\Controls\Extension
+```
+
+### If you want use jQuery calendar (not necessary)
+
initialize the calendar using javascript:
+
```js
$(document).ready(function() {
$('input[data-dateinput-type]').dateinput({
@@ -71,4 +88,8 @@ $form->addDate('datetimeLocal', 'Local datetime', DateInput::TYPE_DATETIME_LOCAL
->setRequired()
->setDefaultValue(new DateTimeImmutable())
->addRule(Form::RANGE, null, array(new DateTimeImmutable('-2 years'), new DateTimeImmutable('+2 years')));
+
+$form->addDate('date', 'Date', DateInput::TYPE_DATE);
+
+$form->addDate('time', 'Time', DateInput::TYPE_TIME);
```
diff --git a/src/DateInput.php b/src/DateInput.php
index 2a27070..94bcfba 100644
--- a/src/DateInput.php
+++ b/src/DateInput.php
@@ -31,9 +31,9 @@
use DateTimeInterface;
use Nette\Forms\Container;
+use Nette\Forms\Control;
use Nette\Forms\Controls\BaseControl;
use Nette\Forms\Form;
-use Nette\Forms\IControl;
use Nette\Forms\Validator;
/**
@@ -44,15 +44,18 @@
class DateInput extends BaseControl {
public const
- TYPE_DATETIME_LOCAL = 'datetime-local',
- TYPE_DATE = 'date',
- TYPE_MONTH = 'month',
- TYPE_TIME = 'time',
- TYPE_WEEK = 'week';
+ TYPE_DATETIME_LOCAL = 'datetime-local',
+ TYPE_DATE = 'date',
+ TYPE_MONTH = 'month',
+ TYPE_TIME = 'time',
+ TYPE_WEEK = 'week';
/** @var string */
protected $type;
+ /** @var bool */
+ private $nullable;
+
/** @var array */
protected $range = ['min' => null, 'max' => null];
@@ -64,7 +67,7 @@ class DateInput extends BaseControl {
public static $defaultValidMessage = 'Please enter a valid date.';
- private static $formats = [
+ public static $formats = [
self::TYPE_DATETIME_LOCAL => 'Y-m-d\TH:i:s',
self::TYPE_DATE => 'Y-m-d',
self::TYPE_MONTH => 'Y-m',
@@ -109,6 +112,11 @@ public function __construct(string $label = null, string $type = self::TYPE_DATE
}
}
+ /**
+ * Sets control's value.
+ * @return static
+ * @internal
+ */
public function setValue($value = null) {
if ($value === null || $value instanceof DateTimeInterface) {
$this->value = $value;
@@ -136,6 +144,26 @@ public function setValue($value = null) {
return $this;
}
+ /**
+ * Returns control's value.
+ * @return mixed
+ */
+ public function getValue()
+ {
+ $value = parent::getValue();
+ return $this->nullable && $value === '' ? null : $value;
+ }
+
+ /**
+ * Sets whether getValue() returns null instead of empty string.
+ * @return static
+ */
+ public function setNullable(bool $value = true)
+ {
+ $this->nullable = $value;
+ return $this;
+ }
+
public function getControl() {
$control = parent::getControl();
$format = self::$formats[$this->type];
@@ -165,14 +193,14 @@ public function addRule($operation, $message = null, $arg = null) {
return parent::addRule($operation, $message, $arg);
}
- public static function validateFilled(IControl $control): bool {
+ public static function validateFilled(Control $control): bool {
if (!$control instanceof self) {
throw new \InvalidArgumentException("Cant't validate control '".\get_class($control)."'.");
}
return ($control->value !== null || $control->submittedValue !== null);
}
- private static function validateValid(IControl $control): bool {
+ private static function validateValid(Control $control): bool {
if (!$control instanceof self) {
throw new \InvalidArgumentException("Cant't validate control '".\get_class($control)."'.");
}
@@ -201,6 +229,10 @@ private function parseValue(string $value): ?DateTimeInterface {
}
} else {
$date = $this->createFromFormat('!'.self::$formats[$this->type], $value);
+ //try find in format without seconds
+ if(!$date && $this->type == self::TYPE_DATETIME_LOCAL) {
+ $date = $this->createFromFormat('!Y-m-d\TH:i', $value);
+ }
}
return $date;
}
diff --git a/src/Extension.php b/src/Extension.php
new file mode 100755
index 0000000..5a03b90
--- /dev/null
+++ b/src/Extension.php
@@ -0,0 +1,23 @@
+methods['initialize'];
+ /** @see DateInput::register() */
+ $init->addBody('Vodacek\Forms\Controls\DateInput::register();');
+ }
+
+}
diff --git a/tests/DateInput.validation.phpt b/tests/DateInput.validation.phpt
index 487b605..e134051 100644
--- a/tests/DateInput.validation.phpt
+++ b/tests/DateInput.validation.phpt
@@ -34,6 +34,28 @@ test(static function() { // no value and valid value for required input
Assert::false($control->hasErrors());
});
+test(static function() { // value and from browser come different format
+ $form = new Form();
+ $control = new DateInput('date', DateInput::TYPE_DATETIME_LOCAL);
+ $form->addComponent($control, 'date');
+ $control->setRequired();
+
+ $control->validate();
+ Assert::true($control->hasErrors());
+
+ $control->setValue('2022-04-01T15:15:15');
+ $control->validate();
+ Assert::false($control->hasErrors());
+
+ $control->setValue('2022-04-01T15:15:00');
+ $control->validate();
+ Assert::false($control->hasErrors());
+
+ $control->setValue('2022-04-01T15:15');
+ $control->validate();
+ Assert::false($control->hasErrors());
+});
+
test(static function() { // invalid value
$form = new Form();
$control = new DateInput('date', DateInput::TYPE_DATETIME_LOCAL);