babis95
babis95

Reputation: 622

How to pass <slots> content (provided by router-view) data back to component where slot is declared

I have 3 components: App.vue (Entry point), slotWrapper.vue (Wrapping component), About.vue (Page Content).

Inside the 'App.vue' i have the router-view setup which is wrapped with 'slotWrapper.vue' component. The 'slotWrapper' component has a <slot> where the current route will be rendered.

My question: Inside the About.vue page (which will be rendered instead of the <slot>, of the slotWrapper.vue component) I have a computed value which I somehow need to pass back to 'slotWrapper.vue' component to use. How would I achieve such a thing.

I looked into ScopedSlots but I can't figure our how to use it where the content rendered is provided by a router.

Link to: CodeSanbox

App.Vue

<template>
  <div id="app">
    <slotWrapper>
      <router-view />
    </slotWrapper>
  </div>
</template>

<script>
import slotWrapper from "./components/SlotWrapper.vue";
export default {
  name: "app",
  components: {
    slotWrapper,
  },
};
</script>

SlotWrapper.vue

<template>
  <div class="wrpperClass">
    <slot />
  </div>
</template>

<script>
export default {
  name: "SlotWrapper",
};
</script>

<style scoped>
.wrpperClass {
  width: 50%;
  height: 50%;
  color: black;
  background-color: lightblue;
}
</style>

About.vue

<template>
  <div id="app">
    <slotWrapper>
      <router-view />
    </slotWrapper>
  </div>
</template>

<script>
import slotWrapper from "./components/SlotWrapper.vue";
export default {
  name: "app",
  components: {
    slotWrapper,
  },
};
</script>

<style>
#app {
  margin: 60px;
}

.link {
  display: inline-block;
  padding: 10px;
}

.router-link-active {
  color: green;
}
</style>

Router: index.js

import Vue from "vue";
import Router from "vue-router";
import About from "../components/About";

Vue.use(Router);

export default new Router({
  mode: "history",

  routes: [
    { path: "/", redirect: "about" },
    {
      path: "/about",
      component: About
      // props: (route) => ({ name: route.query.name })
    }
  ]
});

Upvotes: 0

Views: 1202

Answers (2)

Todd Nagel
Todd Nagel

Reputation: 1

Since it has been a challenge for so many things for me using Vue, I wanted to put this out here since it took me hours to figure out, and seems so simple and logical, it does not make sense as to why it was so dificult to figure out:

In App, if you want to use an emit in a slot that comes from a router-view in App, this solved it for me:

  <LayoutWrapper v-slot:default="{ toggleDrawer }">
<router-view @toggleDrawer="toggleDrawer" :key="$route.fullPath" />

Upvotes: 0

babis95
babis95

Reputation: 622

For those who might face this issue. I figured that you can pass props to <router-view> and listen to emits. Since you can listen to emits I simply emit from the about.vue page and listen on the app.vue, and later using props I pass the variable down to slotWrapper.vue.

App.vue

<template>
  <div id="app">
    <slotWrapper :propToPass="propToPass">
      <router-view @comp-data="receiveFunction" />
    </slotWrapper>
  </div>
</template>

<script>
import slotWrapper from "./components/SlotWrapper.vue";
export default {
  name: "app",
  data() {
    return { propToPass: null };
  },
  components: {
    slotWrapper,
  },
  methods: {
    receiveFunction(data) {
      this.propToPass = data;
      console.log("From emit: ", data);
    },
  },
};
</script>

About.vue

<template>
  <div>
    <h3>About Page</h3>
    <p>
      I need this data:
      <span style="color: green">'ComputedData'</span> available inside
      'SlotWrapper'
    </p>
    <p>{{ ComputedData }}</p>
  </div>
</template>

<script>
export default {
  name: "About",
  data() {
    return {
      someVariable: "'someVariable'",
    };
  },
  mounted() {
    setTimeout(this.sendData, 2000);
  },
  computed: {
    ComputedData() {
      return (
        this.someVariable + " How do I become accessible inside slotWrapper?"
      );
    },
  },
  methods: {
    sendData() {
      this.$emit("comp-data", this.ComputedData);
    },
  },
};
</script>

Upvotes: 0

Related Questions