Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Creating Item | Advanced Features
Next.js 14

Creating ItemCreating Item

Create an Invoice - Step by Step

  1. Make a Form: First, we need a form to get the details. This is where the user puts in the information for the new invoice;
  2. Use a Server Action: Make a special action on the server to handle the form data. When someone fills out the form, this action gets triggered;
  3. Get Data from the Form: Inside the Server Action, take out the information from the form. Think of it like unpacking a box - you want to see what's inside;
  4. Check and Prepare the Data: Look at the data and make sure it's all good. It's like checking that the ingredients for a recipe are fresh and correct. Once everything's okay, get it ready to put into the database;
  5. Insert Data: Put the data into the database;
  6. Refresh Cache and Go Back to Invoices Page: After adding the data, update the cache. It's like making sure everyone gets the latest information. Then, send the user back to the invoices page so they can see the new invoice they just created.

Back to the Project

1. Make a Form

Make a new folder named ' create ' within the app/dashboard/invoices directory. Create a new file called page.tsx inside this folder. This file will serve as a new page allowing users to generate an invoice.

Copy and paste the following code into the page.tsx file:

app/dashboard/invoices/create/page.tsx

The page uses a Server Component to gather user information and then sends it to a ready-made <Form> component. Here's a breakdown of the <Form> component:

  • Dropdown for users;
  • Input field for the amount;
  • Radio buttons for the status;
  • Submit button to complete.

If you click on the "Create Invoice" button, you should be directed to a form that will prompt you to fill out the necessary information.

2. Use a Server Action

  1. Navigate to the lib directory;
  2. Create a new file named actions.ts;
  3. Add the 'use server' directive at the top;
    • Why 'use server'? - It allows the functions to be versatile and usable in both Client and Server components. It's a handy way to organize Server Actions, but we can also embed them directly in Server Components if needed.
  4. Creating a Server Action function.
app/lib/actions.ts

Next, within the <Form> component, import createInvoice from the actions.ts file. Include an action attribute in the <form> element and invoke the createInvoice action.

app/ui/invoices/create-form.tsx

3. Get Data from the Form

Return to app/lib/actions.ts to extract the values of formData using the .get(name) method. Once you've completed this task, you can fill out the form and review the inputted data in the terminal console.

app/lib/actions.ts

Result:

4. Check and Prepare the Data

Before storing the form data in the database, it's crucial to check if it's in the right format and has the correct types. In our course, we've been using a specific format for the invoice table data.

To make this process easier, we have a couple of options for type validation. Instead of manually checking types, we can use Zod, a TypeScript-first validation library. It's a handy tool that simplifies the validation task.

Here's what we need to do in the actions.ts file:

  1. Import Zod into the actions.ts file;
  2. Create a schema using Zod that matches the structure of the form object. This schema acts as a set of rules to ensure the formData is correct before it goes into the database.
app/lib/actions.ts

Then, we pass the rawFormData to CreateInvoice to validate the types.

app/lib/actions.ts

Let's convert the amount to cents and create a new date with the format "YYYY-MM-DD" using vanilla JS.

app/lib/actions.ts

5. Insert Data

Now that we have all the necessary values, we can use sql to send them to the database.

app/lib/actions.ts

6. Refresh Cache and Go Back to Invoices

Next.js has a handy feature called the Client-side Router Cache. It keeps track of where users have been on the site for a certain period. This cache, combined with prefetching, ensures that users can switch between different pages quickly without bombarding the server with too many requests.

Now, here's what we want to do:

  1. Since we've updated the data on the invoices page, we want to ensure users see the latest information. To do this, we clear the cache using revalidatePath function. This ensures a fresh request is sent to the server, pulling in the most recent data;
  2. After updating the data and clearing the cache, we want to guide the user back to the invoices page smoothly. We achieve this by using redirect function. It's like giving them directions back to where they were.
app/lib/actions.ts

In Practice

Everything was clear?

Section 6. Chapter 5
course content

Course Content

Next.js 14

Creating ItemCreating Item

Create an Invoice - Step by Step

  1. Make a Form: First, we need a form to get the details. This is where the user puts in the information for the new invoice;
  2. Use a Server Action: Make a special action on the server to handle the form data. When someone fills out the form, this action gets triggered;
  3. Get Data from the Form: Inside the Server Action, take out the information from the form. Think of it like unpacking a box - you want to see what's inside;
  4. Check and Prepare the Data: Look at the data and make sure it's all good. It's like checking that the ingredients for a recipe are fresh and correct. Once everything's okay, get it ready to put into the database;
  5. Insert Data: Put the data into the database;
  6. Refresh Cache and Go Back to Invoices Page: After adding the data, update the cache. It's like making sure everyone gets the latest information. Then, send the user back to the invoices page so they can see the new invoice they just created.

Back to the Project

1. Make a Form

Make a new folder named ' create ' within the app/dashboard/invoices directory. Create a new file called page.tsx inside this folder. This file will serve as a new page allowing users to generate an invoice.

Copy and paste the following code into the page.tsx file:

app/dashboard/invoices/create/page.tsx

The page uses a Server Component to gather user information and then sends it to a ready-made <Form> component. Here's a breakdown of the <Form> component:

  • Dropdown for users;
  • Input field for the amount;
  • Radio buttons for the status;
  • Submit button to complete.

If you click on the "Create Invoice" button, you should be directed to a form that will prompt you to fill out the necessary information.

2. Use a Server Action

  1. Navigate to the lib directory;
  2. Create a new file named actions.ts;
  3. Add the 'use server' directive at the top;
    • Why 'use server'? - It allows the functions to be versatile and usable in both Client and Server components. It's a handy way to organize Server Actions, but we can also embed them directly in Server Components if needed.
  4. Creating a Server Action function.
app/lib/actions.ts

Next, within the <Form> component, import createInvoice from the actions.ts file. Include an action attribute in the <form> element and invoke the createInvoice action.

app/ui/invoices/create-form.tsx

3. Get Data from the Form

Return to app/lib/actions.ts to extract the values of formData using the .get(name) method. Once you've completed this task, you can fill out the form and review the inputted data in the terminal console.

app/lib/actions.ts

Result:

4. Check and Prepare the Data

Before storing the form data in the database, it's crucial to check if it's in the right format and has the correct types. In our course, we've been using a specific format for the invoice table data.

To make this process easier, we have a couple of options for type validation. Instead of manually checking types, we can use Zod, a TypeScript-first validation library. It's a handy tool that simplifies the validation task.

Here's what we need to do in the actions.ts file:

  1. Import Zod into the actions.ts file;
  2. Create a schema using Zod that matches the structure of the form object. This schema acts as a set of rules to ensure the formData is correct before it goes into the database.
app/lib/actions.ts

Then, we pass the rawFormData to CreateInvoice to validate the types.

app/lib/actions.ts

Let's convert the amount to cents and create a new date with the format "YYYY-MM-DD" using vanilla JS.

app/lib/actions.ts

5. Insert Data

Now that we have all the necessary values, we can use sql to send them to the database.

app/lib/actions.ts

6. Refresh Cache and Go Back to Invoices

Next.js has a handy feature called the Client-side Router Cache. It keeps track of where users have been on the site for a certain period. This cache, combined with prefetching, ensures that users can switch between different pages quickly without bombarding the server with too many requests.

Now, here's what we want to do:

  1. Since we've updated the data on the invoices page, we want to ensure users see the latest information. To do this, we clear the cache using revalidatePath function. This ensures a fresh request is sent to the server, pulling in the most recent data;
  2. After updating the data and clearing the cache, we want to guide the user back to the invoices page smoothly. We achieve this by using redirect function. It's like giving them directions back to where they were.
app/lib/actions.ts

In Practice

Everything was clear?

Section 6. Chapter 5
some-alt