How to use children path in Vue.Js - vue.js

This code
index.js
{
path: '/test',
name: 'test',
component: Test,
children: [{
path: 'p1',
name: 'p1',
component: P1
}]
}
in Component Test
test.vue
<template>
<div>
<h1>Test</h1>
<button v-on:click="navigateTo('/test/p1')">p1</button>
</div>
</template>
<script>
export default {
methods: {
navigateTo(route) {
this.$router.push(route)
}
}
}
</script>
in Component P1
<template>
<div>
<h1>P1</h1>
</div>
</template>
When i click button p1 i has path in browser but not load component p1. why??
I'm new in vue.js

I think you missed the <router-view></router-view> in your parent template (in test.vue). Router view is where the child component gets rendered. i.e.
<template>
<div>
<h1>Test</h1>
<button v-on:click="navigateTo('/test/p1')">p1</button>
<router-view></router-view>
</div>
</template>

Related

Vue.JS - Avoid re-rendering of slots when parent re-renders

I'm struggling on Vue.JS with a component that has as children/slots some "complex" components with canvas data (e.g. Maps).
I want to avoid that when the parent component re-renders, their inner slots re-render. Because of how this components work (or any other scenario), every time it re-renders it needs to do all of it's "loading" steps. Even when saving their real-time state.
For example:
Component.vue
<template>
<div>
<span>{{value}}</span>
<slot></slot>
</div>
</template>
View
<Component v-model="value">
<Map :latitude="0" :longitude="0"/>
</Component>
<script>
this.value = "Hello";
setTimeout(()=>{
this.value="Hello world!";
},1000);
</script>
Is there any way to prevent from slots from re-rendering when their parent re-renders?
Thanks in advance.
Hello use props for a child component, and this child is not will rerender
App
<template>
<div id="app">
<HelloWorld msg="Hello Vue in CodeSandbox!" :somedata="key">
slot information key: {{ key }}
</HelloWorld>
<button #click="key++">key++</button>
</div>
</template>
<script>
import HelloWorld from "./components/HelloWorld";
export default {
name: "App",
components: {
HelloWorld,
},
data() {
return {
key: 0,
};
},
};
</script>
Child
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<h3>somedata from props: {{ somedata }}</h3>
<hr />
<slot></slot>
<hr />
</div>
</template>
<script>
export default {
name: "HelloWorld",
props: {
msg: {
type: String,
default: "",
},
somedata: {
type: Number,
default: 999,
},
},
created() {
console.log("renred");
},
};
</script>
How you can see I used console.log("renred"); in the child component, you can check the console, the information will be shown only one time.
https://codesandbox.io/s/naughty-platform-ib68g?file=/src/components/HelloWorld.vue

Vue - Unable pass specific value to higher component

I am getting the following - Cannot read property 'free' of undefined.
I will be adding this button component on multiple pages and I have data object which will allow me to add text based on whatever page I want displayed on a page. For example if its on the homepage I would like to use <buttons :text="buttonText.free" /> and on about us page I would like to use <buttons :text="buttonText.spend" />
Template file
<template>
<main class="container">
<buttons :text="buttonText.free" />
</main>
</template>
<script>
import Buttons from '~/components/atoms/buttons.vue'
export default {
components: {
Buttons
}
}
</script>
Component file
<template>
<div>
<button class="button"">
<span>{{ buttonText }}</span>
</button>
</div>
</template>
<script>
export default {
props: {
text: String
},
data () {
return {
buttonText: {
free: 'free',
spend: 'spend',
now: 'now',
nowFree: 'now free'
}
}
}
}
</script>
Could you tell me what I am doing wrong?
You should define your data in your parent component's data property. All the variables that is used inside the template tag will be fetched from data, computed or props of the component. You are passing an undefined buttonText data to your buttons component.
<template>
<main class="container">
<buttons :text="buttonText.free" />
</main>
</template>
<script>
import Buttons from '~/components/atoms/buttons.vue'
export default {
data() {
return {
buttonText: {
free: 'free',
spend: 'spend',
now: 'now',
nowFree: 'now free'
}
}
},
components: {
Buttons
}
}
</script>
and in your buttons component, just accept the props passed by the parent component. In this case, you are using text as the props of the buttons component.
<template>
<div>
<button class="button"">
<span>{{ text }}</span>
</button>
</div>
</template>
<script>
export default {
props: {
text: String
}
}
</script>
template.vue
<template>
<main class="container">
<buttons :text="your customized text" />
</main>
</template>
<script>
import Buttons from '~/components/atoms/buttons.vue'
export default {
components: {
Buttons
}
}
</script>
buttons.vue
<template>
<div>
<button class="button">
<span>{{ text }}</span>
</button>
</div>
</template>
<script>
export default {
props: {
text: String
}
}
</script>
here is a simple solution to solve your problem
but you need to learn more fundamentals on vue components
vue component doc

Vuetable2 slot in slot

I use vue(2.6.10) an Im trying to build a universal table with vuetable2 (2.0.0-beta.4).
I created a component for the general methods of vuetable.
I tried to place my "MyCustomTemplate" in the slot section of the "MyVueTable", but I got no error and nothing is shown.
My goal is to use the "MyVueTable" in other vue pages and replace the "MyCustomTemplate".
I have currently 3 entries in my data but in the List.vue component nothing is shown
List.vue
<template>
<MyVueTable :data="data" :fields="fields">
<MyCustomTemplate v-slot="vueTableTemplateSlot"/>
</MyVueTable>
</template
<script>
export default {
name:"List",
data(){
return{
data: [],
fields: [
{
name: 'vueTableTemplateSlot'
}
]
};
}
}
</script>
MyVueTable.vue
<template>
<vuetable ref="vuetable">
<slot name="vueTableTemplateSlot" slot-scope="props"/>
</vuetable>
</template>
<script>
export default {
name: 'MyVueTable',
props: ['data', 'fields'],
methods:{
//vuetable methods
}
}
</script>
MyCustomTemplate.vue
<template>
<div>
{{rowData.id}}
</div>
</template>
<script>
export default {
name: 'MyCustomTemplate',
data(){
return{
rowData: null
}
}
</script>
You can test to put your component(in List.vue) in a div or a template that will be the slot content :
<template #nameOfYourSlot>
<NameOfYourComponent>
</template>
This was answered in the official repository, you need to do this to be your custom global component: https://github.com/ratiw/vuetable-2-tutorial/wiki/lesson-17

can't rendering router children

i have a router called '/shop' and the children is /list/:id for the component named is listproduct
but when i render on the link i go like mylocalhost/shop/list/0812018381 it does render ?
here is my routes
{
path: '/shop',
name: 'shop',
component: () => import('./components/shop.vue'),
children: [
{
path: '/list/:id',
name: 'list',
component: () => import('./views/detail.vue'),
},
],
}
the component on my shop is something like this
<b-col>
<div class="thiscaption my-4 p-2">
<b-link :to="`/shop/${product._id}`">
<h4>{{ product.productName }}</h4>
</b-link>
<span>
{{
product.desc
.split(' ')
.slice(0, 8)
.join(' ')
}}...</span
>
<br />
<span>
<b>${{ product.price }} </b>
</span>
<br />
<b-button type="submit" variant="primary" class="p-2
my-4">add to cart</b-button>
</div>
</b-col>
i have tried to move that component list to not in children of shop, it was work, but when i use it on children shop, it doesnt render and work
If you use the children property of a route, any child routes are mounted in the parent component. In your case it means it is mounted in shop.vue. To be able to mount the component in the parent component, the parent component must contain a <router-view /> element.
Take for example the following components:
<!-- App.vue -->
<template>
<div id="app">
<span>Start App.vue</span>
<router-view/>
<span>End App.vue</span>
</div>
</template>
<!-- ParentComponent.vue -->
<template>
<div class="parent-component">
<span>Start Parent component</span>
<router-view/>
<span>End Parent component</span>
</div>
</template>
<!-- Child1.vue -->
<template>
<div class="comp-child1">Child1.vue</div>
</template>
Furthermore, we have the following router:
// router.js
import Vue from "vue";
import VueRouter from "vue-router";
import ParentComponent from "./components/ParentComponent";
import Child1 from "./components/Child1";
import Child2 from "./components/Child2";
Vue.use(VueRouter);
const routes = [
{
path: "/",
component: ParentComponent,
children: [
{
path: "",
redirect: "/child1"
},
{
path: "child1",
component: Child1
},
{
path: "child2",
component: Child2
}
]
}
];
export default new VueRouter({
routes
});
In this case, App.vue is the root component, because this is defined in main.js. The router says that child1 is a child route from /, which renders component ParentComponent. Therefore we will see the start and end of app.vue. Nested in there we will see the start and end of ParentComponent. Then nested inside of that, we see Child1. Without router-view in either of these components, there would be no place for their children to be mounted.

Getting a value from a nested template in vue

So basically I have something like this in my home page
<template>
<div id="body">
<sideBar :menu="menu" :tableName='tableName' titleOfPage='titleOfPage'></sideBar>
<div id="menu">
HOME PAGE
</div>
</div>
</template>
In the sidebar template you can select your page. It will forward you this template
<template>
<div id="body">
<sideBar :menu="menu" :tableName='tableName' :titleOfPage='titleOfPage'></sideBar>
<div id="main">
<h1>{{ titleOfPage }}</h1>
....
I need the sidebar template to set the titleOfPage as it corresponds to the page clicked. I tried different ways but didn't manage. I appreciate the help by explaining me how to solve this issue.
The Vue docs recommend not using $router directly but instead configuring props to pass to the routed components:
const routes = [
{ path: '/', redirect: '/page-a', component: { template: `<router-view></router-view>` }, name: 'Home' },
{ path: '/page-a', component: Page, props: { titleOfPage: 'Page A' }},
{ path: '/page-b', component: Page, props: { titleOfPage: 'Page B' }},
];
If your props are dynamic and depend on the current route, you can pass a function to the props property of each route configuration:
{ path: '...', component: ..., props: (route) => ({ query: route.query.q }) }
To solve your issue, you can simply create a page component which receives the props from the router and render your sidebar component in its template:
<!-- template for page component -->
<template>
<div id="body">
<sideBar :menu="menu" :tableName='tableName' :titleOfPage='titleOfPage'></sideBar>
<div id="main">
<h1>{{ titleOfPage }}</h1>
<!-- ... -->
</div>
</div>
</template>
DEMO: stackblitz