Sean
Sean

Reputation: 670

Pass data with beforeEnter to route components

How would I go about having a function called with beforeEnter pass data to the corresponding route component(s)?

The purpose of beforeEnter in this case is to confirm that a valid bearer token is present as a cookie.

Currently, I have beforeEnter hitting aws api gateway on /verify/auth, and then the component loads and makes a call to dynamodb on /list/repos. The thing is, both routes are protected with a builtin AWS api gatewayV2 JWT authorizer, so it's kind of pointless to hit /verify/auth.

What I would like is to make beforeEnter hit /list/repos, leverage the built in JWT authorizer, and load the next page with the data obtained from the api call. If the user isn't properly authenticated, beforeEnter won't send the user to the route.

So:

rather than

Here's my code. I had a look at a similar question here, but wasn't able to figure it out. passing data to route's component beforeEnter

index.js

let repositories = [];

async function listRepositories(to, from, next) {
  var isAuthenticated = false;
  console.log("testing listRepositories...");
  if (Vue.$cookies.get("Authorization")) {
    try {
      const response = await fetch(
        process.env.VUE_APP_API_GATEWAY_ENDPOINT + "/list/repos",
        {
          method: "POST",
          body: '{"repo_owner": "sean"}',
          headers: {
            Authorization: Vue.$cookies.get("Authorization")
          }
        }
      );
      repositories = await response.json();
      console.log(repositories);
      if (repositories.message != "Unauthorized") {
        isAuthenticated = true;
        // return {
        //   repositories
        // };
        next();
      }
    } catch (error) {
      console.error(error);
    }
  }
  if (!isAuthenticated) {
    console.log("error not authenticated");
    to("/");
  }
}

const routes = [
  {
    path: "/",
    name: "Login",
    component: () => import("../views/Login.vue")
  },
  {
    path: "/repos",
    name: "Repos",
    // beforeEnter: isAuthenticated,
    beforeEnter: listRepositories,
    props: repositories => {
      {
        repositories;
      }
    },
    component: () => import("../views/Repos.vue")
  }
];

./views/Repos.vue

<template>
  <div id="app" class="small-container">
    <repo-table
      :repositories="repositories"
    />
  </div>
</template>

<script>
import RepoTable from "@/components/RepoTable.vue";

export default {
  name: "Home",
  components: {
    RepoTable
  },
  data() {
    return {};
  },
  props: {
    repositories: {
      type: Array
    }
  }
</script>

./components/RepoTable.vue

<template>
  <div id="repository-table">
    <table border="0">
      <tr>
        <th style="text-align:left">Repository</th>
        // omitted for brevity
      </tr>
      <tbody>
        <tr v-for="(repo, index) in repositories" :key="repo.repo_name">
          <td>
            <b>{{ repo.repo_name }}</b>
            // omitted for brevity
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
export default {
  name: "repository-table",
  data() {
    return {
      // repositories: []
    };
  },
  props: {
    repositories: {
      type: Array
    }
  },

Upvotes: 7

Views: 4151

Answers (1)

Dan
Dan

Reputation: 63059

Using route params with beforeEnter

You can pass data from beforeEnter using route params. When the value of props is true, route params will be converted to props:

props: true

Now you just need a param called repositories and it will be passed as a prop to the destination. In your beforeEnter, when the user is authenticated you can add that param:

if (repositories.message != "Unauthorized") {
  isAuthenticated = true;
  to.params.repositories = repositories;  // ✅ Adding the data to the param
  next();
}

Other fixes:

  • Change to('/') to next('/')
  • Add a next in every logic path, for example when there is an error and when neither if condition is met.
  • Each time you call next call it with return like return next

Another option:

You could also achieve this using the beforeRouteEnter in-component guard.

Upvotes: 6

Related Questions