Vuetify: update URL when tab in v-tab is clicked - vuetify.js

I want to be able to update the URL when a user clicks on a tab defined in v-tab. That way, the url can be shared. When another user uses that shared url, they should be able to start with the same tab that's defined in the URL. Is this possible?

You can just attach a method to the #click event of the tab element, which will change the route on click.
If you want to automatically change the selected tab when the page is loaded, you can get the current route and simply set the tab in mounted() hook:
<v-tabs
v-model="selectedTab"
>
<v-tab
v-for="tab in tabs"
#click="updateRoute(tab.route)
>
...
data () {
return {
selectedTab: 0,
tabs: [
{
name: 'tab1',
route: 'route1'
},
{
name: 'tab1',
route: 'route1'
}
]
}
},
mounted() {
// Get current route name
// Find the tab with the same route (property value)
// Set that tab as 'selectedTab'
const tabIndex = this.tabs.findIndex(tab => tab.route === this.$route.name)
this.selectedTab = tabIndex
},
methods: {
updateRoute (route) {
this.$router.push({ path: route })
}
}

Related

Resetting navigation state after a deep link

After the app receives a deep link and navigates to it, the route (screen) that was specified as a deep link becomes the home screen! After receiving the deep link, each time the app is updated (and automatically re-loaded on the Android emulator), the app navigates to that deep link route (screen). How can I remove this route from the navigation state?
Demonstration of the Scenario:
adb shell am start -W -a android.intent.action.VIEW -d "casualjob://InvitedEmployee" com.casualjob
App is triggered by the command above and navigates to the route InvitedEmployee
User clicks on the Home screen link and navigates to it
I update the app's code
The app is automatically re-loaded to reflect the new code change
The app starts in InvitedEmployee, rather than the Home screen. I expect it to navigate to the Home screen!?
Deep Linking Configuration:
const config = {
screens: {
SingleStack: {
initialRouteName: "InitialScreen",
screens: {
EmployerActionVacancyScreen: "EmployerVacancyAction/:itemID/:opType/:itemStatus?",
ListShiftEmployeeInviteScreen: "InvitedEmployee",
InitialScreen: "*",
},
},
}
};
Stack Definition:
const SingleStack = () => {
const MyStack = createNativeStackNavigator();
return (
<MyStack.Navigator screenOptions={defaultScreenOptions}>
<MyStack.Screen name="InitialScreen" component={InitialScreen} options={{ title: "Home" }}/>
<MyStack.Screen name="ListShiftEmployeeInviteScreen" component={ListShiftEmployeeInviteScreen} options={{ title: "Shifts List", }}/>
</MyStack.Navigator>
);
};
I tried executing different pieces of code that I added to a useEffect hook in the route (screen) that the deep link leads to (InvitedEmployee in the example above). None of them seems to work!?
Solution 1 - throws an error:
The action 'RESET' with payload {"index":0,"routes":[{"name":"initialScreen"}]} was not handled by any navigator. This is a development-only warning and won't be shown in production.
const isFocused = useIsFocused();
useEffect( () => {
async function _fetchData() {
props.navigation.reset({
index: 0,
routes: [{ name: "initialScreen" }], // this is the home screen
});
}
if (isFocused) {
_fetchData();
}
}, [isFocused, ]);
solution 2: this does NOT seem to have any effect. As soon as the App is re-laoded after the code update, the deep-link's route appears back in the navigation state.
const isFocused = useIsFocused();
useEffect( () => {
async function _fetchData() {
props.navigation.dispatch(state => {
if (!state?.routes || state?.routes < 2) {
return;
}
const routes = state.routes.filter( (item, index) => {
if (item.name === "ListShiftEmployeeInviteScreen") { // This is the route (screen) that the deep link leads to
return false;
}
return true;
});
if (routes?.length > 0) {
return CommonActions.reset({
...state,
routes,
index: routes.length - 1,
});
}
return;
});
}
if (isFocused) {
_fetchData();
}
}, [isFocused, ]);

vue created doesn't update after changing route params

I am trying to make a search bar in my index component that is loading other components to show the results of the search and it is working for the first time when the route in any other url except the /search route which is the results page but when I am trying to do other search created() doesn't work / not called again with the new parameter's value .
index.vue
methods: {
search() {
this.$router.push({ name: "search", params:{id:this.words}})
}
}
component search.vue
data() {
return {
videos: null
}
},
created() {
axios.get('/api/search/'+this.$route.params.id)
.then(response=>(this.videos = response.data.data))
.then(document.title='search - '+this.$route.params.id)
}
i solved it
it is should be
window.location.replace("/search/"+this.words);
instead of
this.$router.push({ name: "search", params:{id:this.words}})

create dynamic events for a vue component

I have a problem with vue routes. I am using laravel 6 with vue#2.6.10
I want to create the actions button in the header dynamically (the actions are different which depends on the component). This AppHeader component is on every component and on the current component I want to create in the header the events for the current component.
For example the component CategoryDetails I want to have two actions in the header (save and exit).
The route foe the category is this:
path: '/',
redirect: 'dashboard',
component: DashboardLayout,
children: [
{
path: '/categories',
component: Category,
name: 'category',
meta: {
requiresAuth: true
}
},
{
path: '/categories/:CategoryID',
component: CategoryDetails,
name: 'category-details',
props: true,
meta: {
requiresAuth: true
}
},
]
In the component CategoryDetails:
<template>
<div>
<app-header :actions="actions"></app-header>
// other code
</div>
</template>
<script>
import AppHeader from "../../layout/AppHeader";
export default {
name: "CategoryDetails",
components: {AppHeader},
data() {
actions: [{label: 'Save', event: 'category.save'}, {label: 'Exit', event: 'category.exit'}],
},
mounted() {
const vm = this;
Event.$on('category.save', function(){
alert('Save Category!');
});
Event.$on('category.exit', function(){
vm.$router.push({name: 'category'});
});
}
}
</script>
I crated the action object which tells the header component what events to emit and listen to them in this component.
In the AppHeader component:
<template>
<div v-if="typeof(actions) !== 'undefined'" class="col-lg-6 col-sm-5 text-right">
{{ btn.label }}
</div>
</template>
<script>
export default {
name: "AppHeader",
props: [
'actions'
],
methods: {
onActionClick(event) {
Event.$emit(event);
}
}
}
</script>
The Event is the "bus event" defined in the app.js
/**
* Global Event Listener
*/
window.Event = new Vue();
So... let`s tested :)
I am in the category component. Click on the category details ... the actions are in the header (save and exit). Click on exit...we area pushed back to the category component... click again to go in the category details and click save ... the alert appears TWICE.
Exit and enter again ... the alert "Save Category!" appears 3 times.....and so on ...
Why ?
I think the issue is not with your routes. I don't know but try testing with your event locally (not globally) in the component of interest. There may be duplicate action (CategoryDetails).
According to this post: https://forum.vuejs.org/t/component-not-destroying/25008/10
I have to destroy the "zombie effect"
destroyed() {
Event.$off('category.save');
Event.$off('category.exit');
}

How to manage page titles dynamically in Vuejs?

I build an application. I have a header with the title of my page. Currently, I use view-router to define my titles.
{
path: '/events',
name: 'events',
component: Events,
meta: {
title: 'Liste des événements'
}
}
And in my blade view, in my header.blade.php I'm doing this to display the title
<h2 class="header__title title-header">
#{{ $route.meta.title }}
</h2>
It work BUT when I have a dynamic data, necessarily, it does not work. For example, when I post a post, how can I do to earn my title?
{
path: '/events/:id',
component: Event,
name: 'Event',
meta: {
title: 'my dynamic title',
page: 'event',
},
How to recover the title of the post page? I have the name of the post in my post, but I can not access it from my header ...
I do not have access to the other components. These are components coming from element-ui.
Thank you in advance
In your router, before export default router you can add
router.beforeEach((toRoute, fromRoute, next) => {
window.document.title = toRoute.meta && toRoute.meta.title ? toRoute.meta.title : 'Home';
next();
})
This will read the meta title if it exists and it will update the page title.
Or you can add it like this
const router = new Router({
beforeEach(toRoute, fromRoute, next) {
window.document.title = toRoute.meta && toRoute.meta.title ? toRoute.meta.title : 'Home';
next();
},
routes: [
...
]
})
Don't forget to change the default title value from Home to something else - maybe name of your project

Vue.js issue with computed property uon Chrome browser reload page

I have an issue with my Toolbar component. Upon logout the user is reset to null, and the router fires the home page.
One tab in the Toolbar is binded to the user value (user === null)
The home page is correctly displayed... and the suer can login again if wanted.
BUT, if the user hits the reload button in the browser ( to reload the home page) then the user value is set to "false" ( ???) so the condition in the Tolbar is now false ....
Why thiss user value is reset to "false" on reload ...
Is it a cache issue ? if yes, how to solve it ?
thanks for feedback
Toolbar.vue component
<template>
...
<!-- MENU MEMBERS - UNAUTHENTICATED -->
<v-btn v-if="showMembers && (user === null)" flat #click="$router.push(menuItems[2].link)">
<v-icon left>{{ menuItems[2].icon }}</v-icon>
<span>{{ menuItems[2].title | translate }}</span>
</v-btn>
...
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'Toolbar',
props: ['appName', 'menuItems'],
computed: {
...mapGetters(['sideNav', 'showAssociation', 'showMembers', 'showBlog', 'showShopping', 'user'])
},
methods: {
...
onLogout () {
this.$store.dispatch('logout')
.then(() => {
this.$router.push('/home')
})
}
}
</script>
store/root.js
// actions
export const actions = {
...
logout ({commit}) {
firebase.auth().signOut()
.then(() => {
console.log('SIGNED OUT')
commit(types.SET_USER, null)
}, function (error) {
console.error('Sign Out Error', error)
})
}
...
export const mutations = {
...
[types.SET_USER] (state, payload) {
state.user = payload
localStorage.setItem('user', payload)
},
...
...firebaseMutations
}
In y store/root.js I initialized user state this way
export const state = {
user: localStorage.getItem('user') || null,
If I don't use the localStorage, then the Toolbar behavior is correct . ... user is null
export const state = {
user: null,

Resources