Mint 🍃: Routing
Tags: javascript, webdev, mintlang
Published: 2019-05-29 11:30:41

_This is the seventh post in a series that showcases the features of Mint, you can find the previous posts here:_
* _[Mint 🍃: Getting Started](/gdotdesign/getting-started-with-mint-3k2o)_
* _[Mint 🍃: Components](/gdotdesign/components-in-mint-4a4n)_
* _[Mint 🍃: Events and State of Components](/gdotdesign/mint-events-and-state-of-components-3j3a)_
* _[Mint 🍃: Handling HTTP Requests](/gdotdesign/mint-handling-http-requests-2ep3)_
* _[Mint 🍃: Styling Elements](/gdotdesign/mint-styling-elements-295o)_
* _[Mint 🍃: Creating Packages](/gdotdesign/mint-creating-a-packages-5e9b/)_

In this post I will show you how to set up routes for your application.

--------

In JavaScript land you would use a third party routing library like [react-router](https://github.com/ReactTraining/react-router), [vue-router](https://github.com/vuejs/vue-router) or something similar (depending on the framework) to handle changes in the URL.

In Mint, routing is built into to language itself 🎉 so there is one less dependency to worry about.

### Defining routes

You can use the `routes` block to define routes:

```
routes {
  /path/to/match {
    /* Do something here... */
  }

  /an/other/path/to/match {
    /* Do something here... */
  }
}
```
Basically you just define the **path you want to match** and in **a block what should happen when that path is matched**.

There two things to keep in mind:
* routes are matched from top to bottom
* only one route matches per navigation event

### Matching parameters

You can use the standard colon parameters (`:param`) for path variables:

```
routes {
  /posts/:id (id : String) {
    /* Do something with the id here... */
  }

  /posts/:id/comments/:comment (id : String, comment : String) {
    /* Do something with the id and comment here... */
  }
}
```

> ℹ️ The order of the variables does not matter but the names must match. 

You can even match hash and query parameters:

```
routes {
  /posts?page=:page (page : String) {
    /* Do something with the page here... */
  }

  /#:hash (hash : String) {
    /* Do something with the hash here... */
  }
}
```

> ⚠️ Currently type coercion is not implemented in route parameters so everything is a `String`.

### Matching all (not defined) paths

Using the `*` block matches all (non defined) paths:

```
routes {
  * {
    /* Matches anything. Useful for displaying a 404 page. */
  }
}
```

> ℹ️ It does not matter where this block is, it will always match last.

### Navigating to a new URL

In Mint the language takes care of the navigation, all you have to do is render normal anchor tags `<a href="/path/to/navigate"></a>` and the runtime will do the rest:
* if the `href` attribute matches a route it will navigate to it and call the block without reloading the page, otherwise it will navigate to the URL normally
* browser specific behavior is kept:
  * if the default behavior was prevented with [`perventDefault`](https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault) it does not navigate
  * `ctrl` click opens the URL in a new tab (if applicable)

> ℹ️ If you are interested in the actual implementation you can find it [here](https://github.com/mint-lang/mint-runtime/blob/master/source/Program.js#L9).


### Practical usage and example

In a real application what I usually do is to have an `enum` that represents all the pages that can occur like this:

```
enum Page {
  NotFound
  Register
  Initial
  Login
  Home
}
```

I also have a store called `Application` with a state for the page:

```
store Application {
  state page : Page = Page::Initial

  fun setPage(page : Page) : Promise(Never, Void) {
    next { page = page }
  }
}
```

Then in the `Main` component I use that state to render the different pages:

```
component Main {
  connect Application exposing { page }

  fun render : Html {
    <div>
      <div>
        <a href="/register">"Register"</a>
        <a href="/login">"Login"</a>
        <a href="/asdf">"404"</a>
        <a href="/">"Home"</a>
      </div>

      <hr/>

      case (page) {
        Page::Register => <div>"Register"</div>
        Page::NotFound => <div>"404"</div>
        Page::Login => <div>"Login"</div>
        Page::Home => <div>"Home"</div>
        Page::Initial => <div></div>
      }
    </div>
  }
}
```

And in the routes set the pages accordingly:

```
routes {
  /register {
    Application.setPage(Page::Register)
  }

  /login {
    Application.setPage(Page::Login)
  }

  / {
    Application.setPage(Page::Home)
  }

  * {
    Application.setPage(Page::NotFound)
  }
}
```

And that is pretty much it 🎉 here you can find a repository with the actual code:

{% github mint-lang/mint-example-routing %}

That's it for today, thank you for reading 🙏

--------------


If you like to learn more about Mint check out the [guide](https://guide.mint-lang.com) 📖

In the next part I'm going to show [how you can use environment variables](/gdotdesign/mint-environment-variables-24gf) 😉 see you there 👋