Laravel

DateTimeLocal with LaravelCollective Model Binding

Last week, we were working on one project where we were using LaravelCollective for generating our form. LaravelCollective is a really awesome package and reduces lots of efforts, specifically for automatically binding old inputs to our forms.

Problem

With LaravelColletive when we pass null as a second value, it tried to get old inputs if available and inject them. But for some reason, it was not working with datetimelocal.

datetimelocal need a date in Y-m-d\TH:i Format. When I went into the code of FormBuilder.php, it’s already managing that and tries to convert date into that format if you have passed DateTime object.



So it was completely working fine while creating a record when you do not have any value.

But I have the same form which was used at both the time of Create and Update. And I was passing null into value field at both of the time and LaravelCollective injects it automatically from model or old inputs if there is some error. Something like following,

<div class="form-group col-sm-6">
    {!! Form::label('due_date', 'Due Date:') !!}
    {!! Form::datetimeLocal('due_date', null, ['class' => 'form-control']) !!}
</div>

So, Due date will be automatically placed from the model. It’s working fine with all other fields except datetimelocal.

Solution

The reason behind that is, the value is retrieved from model due_date field, but it comes in Carbon instance and when it converts to a date string, it’s converted into default format which is Y-m-d h:i:s. So it will not work for datetimelocal input since it requires Y-m-d\TH:i format.

So as a solution, what change we did is, instead of passing null value, we first check, if the model is there then pass the value directly to the input. Something like,

<div class="form-group col-sm-6">
    {!! Form::label('due_date', 'Due Date:') !!}
    {!! Form::datetimeLocal('due_date', (isset($task)) ? $task->due_date : null, ['class' => 'form-control']) !!}
</div>

So, I will check if I have passed the model $task to the view and then I will pass a due_date value to input. So FormBuilder will convert it to the proper format and it will get displayed into an input.

Now, when we save the form, it will also return date into Y-m-d\TH:i format, so again we need to convert it to the proper format. For that, we created a mutate attribute for due_date in my Task Model.

public function setDueDateAttribute($value)
{
   $this->attributes['due_date'] = Carbon::parse($value);
}

And that’s it. Our datetimelocal input gets working. I have seen lots of issues on stackoverflow for it. So hope it may help someone.