formers / former

A powerful form builder, for Laravel and other frameworks (stand-alone too)
https://formers.github.io/former/
1.34k stars 205 forks source link

Former::populateField() doesn't override date format #554

Closed ehsanquddusi closed 6 years ago

ehsanquddusi commented 6 years ago

I am populating form using Former::populate(). After this, I want to override the value of one field using Former::populateField(). It is not working.

claar commented 6 years ago

Hi @ehsanquddusi,

It's working for me -- can you give us a simple example that's not working?

<?= Former::open() ?>

<?= Former::populate(['test' => 'A']) ?>
<?= Former::text('test')->forceValue('B') ?>  // populates with "B"

<?= Former::populate(['test2' => 'A']) ?>
<?= Former::populateField('test2', 'B') ?>
<?= Former::text('test2') ?>    // populates with "B"

<?= Former::close() ?>
ehsanquddusi commented 6 years ago

My form has one dob field which is casted as date in Laravel. First I am using Former::populate($player) which gives value of datetime string to dob, as expected. Then I want to override the value of dob, so I am writing, Former::populateField('dob', $player->dob->format('d/m/Y')), which is not updating the value of field and it still has datetime string in it. $player->dob->format('d/m/Y') gives the current date format, as expected.

Please note, I am using Former::populate() and Former::populateField() in controller and then returning the view.

ehsanquddusi commented 6 years ago

It worked by using

Former::populate($player->toArray());
Former::populateField('dob', $player->dob->format('d/m/Y'));

Here $player is a Collection object.

Thank you for the reply. Is this a bug or expected?

claar commented 6 years ago

Hi @ehsanquddusi,

This is expected behavior and not a bug in Former. $player->dob->format('Y-m-d') returns a simple string like 2017-01-01, which Laravel Eloquent internally converts into a Carbon object with no formatting specified.

When you later call Former::text('dob'), Former's Populator returns $player->dob, which Eloquent outputs in its default format of 2017-01-01 00:00:00 and ignores your desired formatting.

By calling ->toArray() first, you remove Eloquent from the picture and things work as expected. Another solution would be to wrap your model in a presenter class that formats dates correctly (something like https://github.com/laravel-auto-presenter/laravel-auto-presenter), or use Former::text('foo')->forceValue($player->dob->format('d/m/Y')) to ensure the value is exactly what you want.

You would have the same problem if you simply output $player->dob in your view rather than calling Former::text('dob'):

<?php
  $player->dob = $player->dob->format('Y-m-d');
  echo $player->dob;  // output like `2017-01-01 00:00:00`
?>