Ready to get started?

Join Adocasts Plus for $8/mo, or sign into an existing Adocasts Plus account, to get access to all of our lessons.

robot mascot smiling

User Registration with InertiaJS

@tomgobich
Published by
@tomgobich
In This Lesson

We'll complete our user registration flow by validating our registration form data, creating a new user, logging that user in, and forwarding them to the next page in the flow.

Chapters

00:00 - Creating Our Register Controller
01:05 - Using Our Register Controller Methods On Our Routes
02:40 - Handling Our Register Form Submission
03:39 - Introducing Actions
05:45 - Completing Our WebRegister Action
07:20 - Injecting & Using Our WebRegister Action
07:56 - Testing Our Registration Flow

Join the Discussion 6 comments

Create a free account to join in on the discussion
  1. @tdturn2
    @tdturn2

    When changing over routes to:

    router.get('/register', [RegisterController, 'show']).as('register.show').use(middleware.guest())

    I'm' getting Error: The import "#controllers/auth/register_controller" is not imported dynamically from start/routes.ts. You must use dynamic import to make it reloadable (HMR) with hot-hook.

    is my register_controller.ts not setup or registered properly?

    I can work around this, but not as clean as your walkthrough

    router.get('/register', async (ctx) => { const { default: RegisterController } = await import('#controllers/auth/register_controller') return new RegisterController().show(ctx) }).as('register.show').use(middleware.guest())

    1
    1. Responding to tdturn2
      @tomgobich

      Hi tdturn2!

      First, your import is valid and will work, it just won't work with hot module reloading (HMR). HMR is enabled by default in newer AdonisJS 6 projects. Rather than fully restarting the application when a change is made in development, HMR enables the single updated spot to be updated on the fly.

      AdonisJS uses NodeJS Loader Hooks to perform HMR, and loader hooks require dynamic imports to work and hot-swap modules when updated. If you'd like to read more on this, they walk through the full what & whys in the documentation.

      So rather than importing your controller like this, which will not work with HMR:

      import RegisterController from '#controllers/auth/register_controller'
      
      router.get('/register', [RegisterController, 'show'])
      Copied!

      You can instead dynamically import the controller, which will work with HMR:

      const RegisterController = import('#controllers/auth/register_controller')
      
      router.get('/register', [RegisterController, 'show'])
      Copied!

      If you have your text editor fix lint errors on save, this change will happen automatically when you save your file. You'll see this happen for me in the lesson around the 2:20 mark. If you're using VSCode, you can turn this on by installing the ESLint extension, and then adding the below to your JSON user settings.

      {
        "editor.codeActionsOnSave": {
          "source.fixAll.eslint": "explicit"
        },
      }
      Copied!
      1
      1. Responding to tomgobich
        @tdturn2
        @tdturn2

        Awesome, that was it! Thank you!

        1
        1. Responding to tdturn2
          @tomgobich

          Anytime!! 😊

          1
  2. @usources
    @usources

    Hi! I'm trying to add a new confirmPassword field only for validation purposes; it has no effect on the user model.

    Everything looks good until creating the user model because the user model does not have a confirmPassword field.

    Is there any way to omit a value from the validateUsing function?

    I followed this approach, but I'm not sure if it's the best one:

    import User from '#models/user'
    import { registerValidator } from '#validators/auth'
    import { inject } from '@adonisjs/core'
    import { HttpContext } from '@adonisjs/core/http'
    import { Infer } from '@vinejs/vine/types'
    
    type Params = {
      data: Infer<typeof registerValidator>
    }
    
    @inject()
    export default class WebRegister {
      constructor(protected ctx: HttpContext) {}
    
      async handle({ data }: Params) {
        const { confirmPassword, ...userData } = data
    
        const user = await User.create(userData)
    
        await this.ctx?.auth.use('web').login(user)
    
        return { user }
      }
    }
    
    Copied!
    0
    1. Responding to usources
      @tomgobich

      Hi usources!

      Yeah, what you're doing there is perfectly valid, and what I do in most cases where I don't need to omit a ton of fields. Alternatively, you could use an omit utility, like what is offered from Lodash, but what you have is absolutely fine!

      1