Skip to main content

Black Friday 2025! Only until December 1st: coupon FRIDAY25 for 40% off Yearly/Lifetime membership!

Read more here

Due Date: Can't Use Shadcn Date Picker

Premium
5 min read

Now, let's try to add one more field to our form and database: due_date with a date picker.


Prepare Database/Controller

I will just show you the code without any comments. These are Laravel fundamentals, I'm sure you know them.

Migration:

php artisan make:migration add_due_date_to_tasks_table
Schema::table('tasks', function (Blueprint $table) {
$table->date('due_date')->nullable();
});

Then, we run:

php artisan migrate

Adding to Model fillables:

app/Models/Task.php:

class Task extends Model
{
use HasFactory;
 
protected $fillable = [
'name',
'is_completed',
'due_date',
];
 
protected function casts(): array
{
return [
'is_completed' => 'boolean',
'due_date' => 'date'
];
}
}

Validation rules:

app/Http/Requests/StoreTaskRequest.php:

// ...
public function rules(): array
{
return [
'name' => ['required', 'string', 'max:255'],
'due_date' => ['nullable', 'date'],
];
}

app/Http/Requests/UpdateTaskRequest.php:

public function rules(): array
{
return [
'name' => ['required', 'string', 'max:255'],
'is_completed' => ['required', 'boolean'],
'due_date' => ['nullable', 'date'],
];
}

No modifications are needed for the Controller since we use $request->validated() to create/update tasks.

Ok, the back end is ready. It's time to dive into the JavaScript/TypeScript side.


Adding Field to TypeScript Types

We need to update our type in the file of all types:

resources/js/types/index.d.ts

export interface Task {
id: number;
name: string;
is_completed: boolean;
due_date?: string;
created_at: string;
updated_at: string;
}

Also, in our Create.tsx page, we need to...

The Full Lesson is Only for Premium Members

Want to access all of our courses? (29 h 14 min)

You also get:

54 courses
Premium tutorials
Access to repositories
Private Discord
Get Premium for $129/year or $29/month

Already a member? Login here

Comments & Discussion

RA
Richard A. Hoyle ✓ Link copied!

How hard would it be to set the calende picker with the date and time aswell ?

PK
Povilas Korop ✓ Link copied!

If we go for native browser, maybe input type="datetime-local"?

LA
Luis Antonio Parrado ✓ Link copied!

I had problems with the date-fns library, incorrect format in the picker, I used dayjs instead.

RA
Richard A. Hoyle ✓ Link copied!

Can you show us what you changed to get this to work? I added the npm install dayjs –save But what else do I have to do to get this to work?

SP
Steve Popoola ✓ Link copied!

date-fns worked for me without any problems.

npm install  date-fns --save

In Create.tsx

import { format } from 'date-fns'; 

Use the format function

<Input
                        id="due_date"
                        value={data.due_date}
                        onChange={(e) => setData('due_date', format(new Date(e.target.value), 'yyyy-MM-dd'))}
                        className="mt-1 block w-full"
                        type="date"
                    />

What problems were you having?

SP
Steve Popoola ✓ Link copied!

Hi Povilas,

Something minor but important: In Create.tsx, the form is defined in the article as;

interface CreateTaskForm {
    name?: string,
    due_date?: string 
}

But it was actually created earlier as type and should be:

type CreateTaskForm = {
    name?: string;
   due_date?: string;
}

The same with EditTaskForm:

type EditTaskForm = {
    name: string;
    is_completed: boolean;
    due_date?: string;
};
M
Modestas ✓ Link copied!

Hi, thanks for letting us know! I've updated the lesson to fix this :)

ps. This was a left-over update from following starter kit changes https://github.com/laravel/react-starter-kit/commit/bb97832a09926ab9c28b6bde87262fca4bc1800a#diff-6dcdf3ad723e9f82263160236fdb941e99915e8171a4f807b8a95a5c2aa89841R13

SP
Steve Popoola ✓ Link copied!

Under "Adding the Input Date to the Form" (For Create) , the following is missing:

const { data, setData, errors, post, reset, processing } = useForm<Required<CreateTaskForm>>({ 
        name: '', 
        due_date: format(new Date(), 'yyyy-MM-dd'),   // This needs to be added
    }); 
M
Modestas ✓ Link copied!

This would set the due_date to today, but we intentionally left it null as we don't want to fill it with any default value.

Or was there any other reason for this?

SP
Steve Popoola ✓ Link copied!

I meant the due_date property is missing which throws an error

M
Modestas ✓ Link copied!

But it is there, no?

type CreateTaskForm {
    name?: string,
    due_date?: string 
}
 
export default function Create() {
    // ...
 
    const { data, setData, errors, post, reset, processing } = useForm<Required<CreateTaskForm>>({
        name: '',
        due_date: '', 
    });
}

This is taken from the lesson and seems to be exactly what you are referring to

SP
Steve Popoola ✓ Link copied!

Ah! seen that it was previously set before that secton. No worries!

SP
Steve Popoola ✓ Link copied!

While the Edit form works with the addition of due_date, TypeScript is complaining, "Type 'string | undefined' is not assignable to type 'string'. Type 'undefined' is not assignable to type 'string'." I believe this is because we have defined due_date as optional in the type but by wrapping EditTaskForm with Required, we are making all the properties of EditTaskForm required.

I was able to fix the TypeScript error by making due_date optional as follows:

type EditTaskForm = {
    name: string;
    is_completed: boolean;
    due_date: string | null;
};

I removed the Required from useForm and passed due_date or null

const { data, setData, errors, put, reset, processing } = useForm<EditTaskForm>({
        name: task.name,
        is_completed: task.is_completed,
        due_date: task.due_date || null, 
    });