I have two pages routed:
Home > Results
Inside 'Home', I have a button/link which is not in <route-view/> and I want this button to redirect to Results.vue passing a parameter.
This parameter named activeTab, has to open the desired vue-tabs, which I can't accomplish, because it's getting nothing from variable:
code:
Home.vue
<div class="row">
<Notes refName="Relationship" />
<Notes refName="Support" />
</div>
...
<script>
import Notes from '#/components/Monthlynotes.vue'
export default {
name: 'home',
components: {
Notes
},
</script>
/components/Monthlynotes.vue
<b-card>
<p class="card-text">{{ refName }}</p>
<b-link class="right" :activeTab="refName" href="/results">More</b-link>
</b-card>
...
<script>
export default {
props: {
refName: String,
},
</script>
Results.vue
<vue-tabs type="pills" v-model="tabName">
<v-tab title="Relationship">
<RelDT msg="Results view"/>
</v-tab>
<v-tab title="Support">
<SupDT msg="Results view"/>
</v-tab>
</vue-tabs>
...
<script>
import RelDT from '#/components/DataTable.rel.vue'
import SupDT from '#/components/DataTable.sup.vue'
export default {
name: 'results',
props: {
activeTab: String
},
components:
{
RelDT,
SupDT,
},
data() {
return {
tabName: activeTab
}
}
}
</script>
App
<router-link :to="{name:'results', param:{activeTab}}">Results</router-link>
How can I make this <b-link> route if it was a <route-link />?
Even the b-link component supports the :to property. To be found here
The value of the property will be passed to router.push().
<b-link :to="{name:'results', param:{activeTab}}">Redirect me</b-link>
Related
I am confused with Vue Routes and sending params as props over all files. I have following structure
When I click on card(ProjectDashboard) I want to be redirected to card detail page(ProjectOverview). On Card detail page is sidebar navigation. When I click on navi1 or navi2 I want to display different component on dashboard. Everything stay fixed only dashboard component will be different.
router.js
const router = new VueRouter( {
mode: 'history',
routes: [
{
path: '/',
name: 'ProjectsDashboard',
component: ProjectsDashboard,
},
{
path: '/project/:id',
name: 'project',
props: true,
component: ProjectOverview,
},
{
path: '/project/:id/something',
name: 'project',
props: true,
component: ProjectOverview,
},
{
path: '/:catchAll(.*)',
component: error404,
name: 'NotFound'
}
],
} );
ProjectDashboard.vue
<template>
<div class="m-3">
<div class="text-center m-2">DASHBOARD</div>
<div v-for="item in customJsonAllClient" :key="item.id">
<router-link :to="{name:'project', params:{id:item.id, bexioId:item.bexioId, gitlabId:item.gitlabId, title:item.title}}">
<b-card-group deck>
<b-card
bg-variant="light"
text-variant="dark"
class="text-center"
>
<b-card-text>
{{item.title}}
</b-card-text
>
</b-card>
</b-card-group>
</router-link>
</div>
</div>
</template>
<script lang="ts">
import { BCard, BCardText, BLink, BCardGroup } from 'bootstrap-vue';
import Vue from 'vue';
import { VServices } from '#libTs/vue-base';
import { jsonDataService } from './../services/customJsonData.service';
const SERVICES = VServices({
json: jsonDataService,
});
export default Vue.extend({
name: 'ProjectsDashboard',
components: {
BCard,
BCardText,
BLink,
BCardGroup
},
data() {
return {
customJsonAllClient: [],
};
},
async mounted() {
await SERVICES.json.getCustomJsonAllClients();
this.customJsonAllClient = SERVICES.json.customJsonAllClient;
},
});
</script>
ProjectOverview.vue
<template>
<div>
<navbar></navbar>
<site-navbar :id="projectData.id"></site-navbar>
<div class="sidenav-overlay"></div>
<div class="app-content content">
<div class="content-overlay"></div>
<div class="header-navbar-show"></div>
<div class="content-wrapper">
<b-card bg-variant="light" text-variant="dark" class="text-center">
<b-card-text>
{{ title }}
</b-card-text>
</b-card>
<div v-if="jsonClientsProjects">
<b-card v-for="item in jsonClientsProjects" :key="item.id">
<b-card-text>Project id {{ item.id }}</b-card-text>
<b-card-text>Project name {{ item.name }}</b-card-text>
<b-card-text>Description {{ item.description }}</b-card-text>
<b-card-text>
Project Created: {{ date.getCreatedDate(item.created_at) }}
</b-card-text>
<b-card-text>
Last Project Update :
{{ date.getDateLastUpdate(item.last_activity_at) }}
</b-card-text>
</b-card>
</div>
<div v-else>
<b-card>
<b-card-text>Project id {{ projectData.id }}</b-card-text>
<b-card-text>Project name {{ projectData.name }}</b-card-text>
<b-card-text>Description {{ projectData.description }}</b-card-text>
<b-card-text>
Project Created: {{ date.getCreatedDate(projectData.created_at) }}
</b-card-text>
<b-card-text>
Last Project Update :
{{ date.getDateLastUpdate(projectData.last_activity_at) }}
</b-card-text>
</b-card>
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import { BCard, BCardText, BLink, BCardGroup } from 'bootstrap-vue';
import Vue from 'vue';
import { VServices } from '#libTs/vue-base';
import Navbar from './navbar.vue';
import SiteNavbar from './site-navbar.vue';
import { dateService } from './../services/date.service';
import { bexioDataService } from './../services/bexioData.service';
import { gitlabDataService } from './../services/gitlabData.service';
import { jsonDataService } from './../services/customJsonData.service';
const SERVICES = VServices({
date: dateService,
bexio: bexioDataService,
gitlab: gitlabDataService,
json: jsonDataService,
});
export default Vue.extend({
name: 'ProjectOverview',
props: { id: String, bexioId: String, gitlabId: String, title: String },
components: {
BCardGroup,
BCard,
BCardText,
BLink,
Navbar,
SiteNavbar,
},
data() {
return {
customJsonAllClient: [],
jsonClientsProjects: [],
projectData: [],
date: SERVICES.date,
};
},
created() {},
async mounted() {
await SERVICES.json.getCustomJsonAllClients();
this.customJsonAllClient = SERVICES.json.customJsonAllClient;
this.getCorrectUserData();
await SERVICES.gitlab.getClientsProjects(this.projectData.gitlabId);
this.jsonClientsProjects = SERVICES.gitlab.jsonClientsProjects;
this.getCorrectUserData();
},
methods: {
getCorrectUserData() {
const url = window.location.pathname;
const pathArray = url.split('/');
let last = pathArray[pathArray.length - 1];
let obj = this.customJsonAllClient.find((x) => x.id == last);
this.projectData = obj;
},
},
});
</script>
siteNavbar.vue
<ul class="navigation navigation-main">
<li class="nav-item active">
<router-link to="/project/:id"> this link should switch to ProjectOverview </router-link>
</li>
<li class="nav-item active">
<router-link to="/project/:id/something"> this link should switch to some other component </router-link>
</li>
</ul>
router link is on first main vue app.
I can sent data from ProjectDashboard as a param and it show correct data on its detail page but I don't know how I should set up router link in sidebar that it always show correct data for current prop param and how I can render only component which I need.
PS: is it possible to add active class for navi link somehow with routs or I have to create separate function in methods for this?
what you want to do is using nested routes.
Check out:
https://router.vuejs.org/guide/essentials/named-views.html#nested-named-views
and
https://router.vuejs.org/guide/essentials/nested-routes.html
for active class watch:
https://router.vuejs.org/api/#active-class
So this one is a bit tricky for me. I have a Sidebar.vue component with a link(Help). I want to trigger my Modal.vue component with different data for every main view eg. Home, About, Contact etc. So whenever I am on Home I want to trigger help modal with hints via that link for Home.vue, when I am on About I want to show hints for About.vue and so on..
My code:
Sidebar.vue
<template>
<ul>
<li>
<a #click="openHelp">Help</a>
</li>
</ul>
</template>
<script>
export default {
name: 'Sidebar',
methods: {
openHelp() {
this.$emit('help-modal');
},
},
};
</script>
Modal.Vue
<template>
<div class="modal" v-if="open">
<div class="modal-title">
<h4>Help</h4>
</div>
</div>
</template>
<script>
export default {
name: 'Modal',
props: {
open: {
type: Boolean,
default: false,
}
},
methods: {
close() {
this.$emit('closed');
},
},
};
</script>
Home.vue
<template>
<div>
Home
<modal
:open="helpOpen"
#closed="openHelpModal">
<p>Home Help</p>
</modal>
</div>
<template>
<sidebar/>
</template>
</template>
<script>
import Sidebar from '#/components/Sidebar.vue';
export default {
name: 'Home',
components: {
Sidebar,
},
data() {
return {
helpOpen: false,
}
}
methods: {
openHelpModal() {
this.helpOpen = !this.helpOpen;
},
}
}
</script>
I know that vuex would be the best solution but don't have an idea how to approach it. Modal would show only static images with a bit of text for every main view.
One way of doing this would be to simply add a property to the modal component e.g helpData and pass the relevant data to this prop in each of the main pages as shown below
Modal.vue
<template>
<div class="modal" v-if="open">
<div class="modal-title">
<h4>Help</h4>
</div>
</div>
</template>
<script>
export default {
name: 'Modal',
props: {
open: {
type: Boolean,
default: false,
},
helpData: {
type: String,
required: true
}
},
methods: {
close() {
this.$emit('closed');
},
},
};
</script>
Home.vue
<template>
<div>
Home
<modal
:open="helpOpen"
#closed="openHelpModal"
:help-data="This is a sample help data for the home view"
/>
</div>
<template>
<sidebar #help-modal="helpOpen = true"/>
</template>
</template>
<script>
import Sidebar from '#/components/Sidebar.vue';
export default {
name: 'Home',
components: {
Sidebar,
},
data() {
return {
helpOpen: false,
}
}
methods: {
openHelpModal() {
this.helpOpen = !this.helpOpen;
},
}
}
</script>
As indicated by #ljubadr, I have included the logic that would open the modal in the sidebar component of Home.vue. Also, I would recommend you change the name of the function openHelpModal to closeHelpModal (seeing as this function will basically close the modal) or toggleHelpModal (since from the logic of the function, it toggles the modal state).
HelloWorld.vue
<template>
<div>
<b>Vuejs dynamic routing</b>
<div v-for="item in items" :key="item.id">
<b>{{ item.id }}.</b>
<router-link :to="{ name: 'UserWithID', params: { id: item.id } }">
{{ item.kk }}
</router-link>
<router-link name="twoval"></router-link>
</div>
<br /><br /><br />
<User />
<Usertwo />
</div>
</template>
<script>
import User from "./User.vue";
import Usertwo from "./Usertwo.vue";
import { datalist } from "./datalist";
export default {
name: "HelloWorld",
components: {
User,
Usertwo,
},
data() {
return {
items: datalist,
};
},
};
</script>
User.vue
<template>
<div>
<div v-for="(item, key) in user" :key="key">
{{ item }}
</div>
</div>
</template>
<script>
import { datalist } from "./datalist";
export default {
name: "User",
data() {
return {
lists: datalist,
};
},
computed: {
user: function () {
return this.lists.find((item) => item.id === this.$route.params.id);
},
},
};
</script>
Usertwo.vue
<template>
<div>
<div v-for="usertwo in usertwos" :key="usertwo.mid">
{{ usertwo.doctor }}
</div>
</div>
</template>
<script>
import { datalisttwo } from "./datalisttwo";
export default {
name: "User",
data() {
return {
usertwos: datalisttwo,
};
},
};
</script>
main.js
import Vue from "vue";
import App from "./App.vue";
import VueRouter from "vue-router";
import HelloWorld from "./components/HelloWorld.vue";
Vue.use(VueRouter);
const router = new VueRouter({
routes: [
{ path: "/", name: "User", component: HelloWorld },
{ path: "/:id", name: "UserWithID", component: HelloWorld }
]
});
Vue.config.productionTip = false;
new Vue({
router,
render: (h) => h(App)
}).$mount("#app");
Logic trying to achieve, If i click on router-link id-1 from helloworld.vue component, then in User.vue and Usertwo.vue component. I need to show only array values list which is linked with id-1 only. from two arrray value list based on id.
Similarly on whatever the id, i click on from router-view from helloworld.vue. Same id value, i need to show inside the User and Usertwo.vue component.
Now only issue wit code is, Usertwo array value not loading correctly
I tried below code for that logic, But i couldn't make it.
This is my complete code:- https://codesandbox.io/s/pensive-williamson-n9bi6?file=/src/main.js:0-434
Something like this: https://codesandbox.io/s/white-bird-z6orf
Add props to the components
Send the id from the params to the components
Filter the list
I have three components component-1, component-2, and an App component, I pass a Boolean props from component-1 to component-2 then using #click event I change the props value from true to false and vice versa
App.vue
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png" width="20%" />
<component1 />
</div>
</template>
component-1.vue
<template>
<div>
<component2 :have-banner="true" />
</div>
</template>
<script>
import component2 from "./component-2";
export default {
components: {
component2,
},
};
</script>
component-2.vue
<template>
<div>
<button #click="AssignBanner = !AssignBanner">Click me</button>
<p>{{ AssignBanner }}</p>
</div>
</template>
<script>
export default {
name: "HelloWorld",
props: {
haveBanner: Boolean,
},
data() {
return {
AssignBanner: this.haveBanner,
};
},
};
</script>
I want to get the value of the props in component-1, that is, I want to track the changing value in component-1, since I want to write some logic, but I can’t keep track of the value in component-1.
You can see the given code in codesandbox
Looks like you want to achieve two-way binding for the prop haveBanner. You can achieve this with the .sync modifier if you are using Vue 2.3+.
component-1.vue
<template>
<div>
<component2 :have-banner.sync="haveBanner" />
</div>
</template>
<script>
import component2 from "./component-2";
export default {
components: {
component2,
},
data() {
return {
haveBanner: true,
}
},
};
</script>
component-2.vue
<template>
<div>
<button #click="assignBanner = !assignBanner">Click me</button>
<p>{{ assignBanner }}</p>
</div>
</template>
<script>
export default {
name: "HelloWorld",
props: {
haveBanner: Boolean,
},
data() {
return {
assignBanner: this.haveBanner,
};
},
watch: {
assignBanner(value) {
// propagate to parent component
this.$emit('update:haveBanner', value)
},
},
};
</script>
I have a splitted interface like you can see it in the following example image. On the left you can see the app.vue content. On the right the router-view content. With the menu bar on the top of the app.vue content you can switch between the different router-link and change therefore the router-view on the left side. so far so good.
But now the problem: in my app.vue there are user inputs which are stored in data variables. The user input is part of the app.vue content but is also needed in the router-view.
My current version sends the user input with router-link params to the router view. The problem is that on page load and when the user input changes the data on the router view is deprecated. To show the correct data again I have to trigger the router links.
App.vue:
<template>
<div>
<router-link :to="{ name: 'route01', params: { data: userinput } }">
01 route
</router-link>
<router-link :to="{ name: 'route02', params: { data: userinput } }">
02 route
</router-link>
</div>
</template>
<script>
export default {
data: function() {
return {
userinput: 'foo',
}
}
}
</script>
route01.vue:
<template>
<div class="container">
<h1>{{userinput}}</h1>
</div>
</template>
<script>
export default {
data: function() {
return {
userinput: 'no input',
};
},
created: function() {
this.userinput = this.$route.params.userinput;
}
}
</script>
How can I reload the router view everytime the user input changed? And How can I send the default user input value on page load to the default router link?
If you make your userinput an object it will be passed by reference. That way any updates made to this object would be reflected in any component that holds a reference to the same object ..
App.vue
<template>
<div>
<router-link :to="{ name: 'route01', params: { userinput } }">
01 route
</router-link>
<router-link :to="{ name: 'route02', params: { userinput } }">
02 route
</router-link>
</div>
</template>
<script>
export default {
data: function() {
return {
userinput: { text: 'foo' },
}
}
}
</script>
route01.vue
<template>
<div class="container">
<h1>{{ userinput.text }}</h1>
</div>
</template>
<script>
export default {
data: function() {
return {
userinput: { text: 'no input' },
};
},
created: function() {
this.userinput = this.$route.params.userinput;
}
}
</script>