Vue 2 make a div Clickable and image - vuejs2

I am playing around with Vue 2, and I want to make a whole div clickable.
This div have a link, image and text.
I used router-link for links in header and other links but when I try to use something else the page keeps refreshing.
Can someone please help me get over this somehow..
Cheers!

Add click event to you <div> that you want to be clickable as below:
<div #click="clickMethod"></div>
Now in your methods property add rhe clickMethod callback that you want to fire when clicked like below
methods: {
clickMethod() {
//add code that you wish to happen on click
}
}:

For anyone who is stuck here like I did on how to make a Div Clickable
<div #click="clickeMethod">
<p> Some Text Here </p>
</div>
script:
<script>
export default {
name: 'headers',
data() {
return {
};
},
methods: {
clickMethod() {
this.$router.push('home');
},
},
};
</script>
This Event will make a div Clickable.
Hope I helped someone :) and thnx to #user7814783

For those wondering how router.push method works, below are various ways you can use the method:
// literal string path
router.push('home')
// object
router.push({ path: 'home' })
// named route
router.push({ name: 'user', params: { userId: '123' } })
// with query, resulting in /register?plan=private
router.push({ path: 'register', query: { plan: 'private' } })
For me this implementation worked best:
<script>
export default {
name: 'home',
data() {
return {
};
},
methods: {
clickMethod() {
this.$router.push({ path: 'home' });
},
},
};
</script>

Related

How do you build page within a folder in Vue?

I'm trying to have my URL as /social/fb/, i've tried looking online and documentation but can't find the answer to this simple question for the life of me.
My folder structure is:
Pages
-social
--fb
I have a social.vue file in pages which works fine as www.example.com/social but can't get www.example.com/social/fb. Any direction would be much appreciated.
Create social folder inside pages, then create fb.vue inside social folder.
This should work
I normally load the layout.vue from the router and treat everything else as a child which is passed though as a router-view, this then saves having an index.vue for each parent.
But you would always want to make a directory to contain the social pages. Then would be a case of simply adding to the router.js file.
layouts/template.vue
<template>
<router-view></router-view>
</template>
<script>
export default {
name: 'layout-template'
}
</script>
router.js
...
/*
* Social
*/
{
path: '/social',
component: () => import('./layout/template.vue'),
props: true,
// rendered inside <router-view>
children: [{
path: '/',
component: () => import('./pages/social/index.vue')
}, {
path: 'fb',
component: () => import('./pages/social/fb.vue')
}, {
path: 'twitter',
component: () => import('./pages/social/twitter.vue')
},
// or do something more dynamic
{
path: ':network', // accessible in component though `$route.params.network`
props: true, // makes accessible though `props: ['network']`
component: () => import('./pages/social/network.vue')
}]
},
...
./pages/social/index.vue - could show something /social homepage or change route to import('./pages/not-found.vue') instead.
./pages/social/network.vue
<template>
...
</template>
<script>
export default {
name: "page-social-network",
props: {
network: {
type: String,
default: ''
}
},
created() {
// or through
this.$route.params.network
}
};
</script>
<style lang="scss" scoped></style>
See: https://router.vuejs.org/guide/essentials/passing-props.html#boolean-mode
Otherwise is just standard vue pages

Nuxt: Page crashing on page reload

Anyone know why a sub page crashes when user reloads the page? It is fine when you navigate to the page using nuxt-link from another page (using route params), but when the user reloads/refreshes the page, it will crash.
Here is my sandbox where you can test it out: Codesandbox
Code from nuxt link:
<nuxt-link :to="{name: 'photos-id-title', params: { id: photo.id, title: photo.title }}">
Code from photo details page:
<template>
<section>
<!-- <template v-if="photo"> -->
<img
:id="photo.filename"
:src="photo.url"
class="img-fluid thumbnail rounded"
:alt="photo.title"
/>
<h1 class="h3">{{ photo.title }}</h1>
</section>
</template>
<script>
import { Annotorious } from '#recogito/annotorious'
export default {
data() {
return {
photo: {},
anno: {},
title: this.$route.params.title
}
},
async mounted() {
await this.getPhotoDoc()
this.anno = await new Annotorious({ image: this.photo.filename })
},
methods: {
async getPhotoDoc() {
const docRef = await this.$fireStore
.collection('photos')
.doc(this.$route.params.id)
.get()
try {
if (docRef.exists) {
// data() returns all data about the doc
console.log('got the doc: ', docRef.data())
this.photo = docRef.data()
} else {
console.log('no docs exist')
}
} catch (error) {
console.log('Error getting document:', error)
}
}
},
head() {
return {
title: this.photo.title,
meta: [
{
hid: 'description',
name: 'description',
content: this.photo.description
}
]
}
}
}
</script>
User journey: Click PHOTOS from navbar, select any photo on the page. You shall see a "photo detail" page. Loads fine. Try to refresh the page -- it will crash.
Note: I also have this scaffolded in a regular/plain vue app using Vue-cli and have NO issues. Only seems to be a problem with Nuxt. Must be SSR related?
Thanks for any help...
If you think this is SSR related and the Annotorious plugin might cause the problem try this:
nuxt.config.js add the plugin with mode client
plugins: [
{ src: '~/plugins/client-only.js', mode: 'client' }, // only on client side
]
You can find more information in the nuxtjs docs here

How to achieve "visited recently" using Vue?

I'm trying to create a list of hyperlinks to the last 5 pages (views) visited by a user. However I don't really know where/ how to start...
I thought about somehow storing each route when visited but I don't know what's the best practice to do so.
I'm not asking for a working code, I just need some help to find the right direction to start with.
You can use router.beforeEach((to, from, next) =>{}) and store the url in an array. You can read more details about navigation guards here.
https://router.vuejs.org/guide/advanced/navigation-guards.html#global-before-guards
Found this, it may help:
https://codesandbox.io/s/mutable-glade-qnrxm
It stores the visited routes.
It works like this:
<template>
<div>
<span v-for="crumb in crumbs" :key="crumb.index">
<router-link :to="crumb.path">{{ crumb.name }}</router-link> |
</span>
</div>
</template>
<script>
export default {
data() {
return {
crumbs: []
};
},
watch: {
$route(to) {
if (this.crumbs.length > 3) {
this.crumbs.shift();
}
this.crumbs.push({
path: to.fullPath,
name: to.name/* */
});
}
},
mounted() {
this.crumbs.push({
path: this.$route.fullPath,
name: this.$route.name
});
}
};
</script>
Here, it gets the route name and path on mount and pushes it to crumbs array.
mounted() {
this.crumbs.push({
path: this.$route.fullPath,
name: this.$route.name
});
}
Then it constantly watches and changes on route. On change, it shifts(removes the last and adds a new one) any router if there are more than 3. And then it assignes the name and path for every new router.
watch: {
$route(to) {
if (this.crumbs.length > 3) {
this.crumbs.shift();
}
this.crumbs.push({
path: to.fullPath,
name: to.name/* */
});
}
},
And at last, it loops the crumbs and displays it.
<span v-for="crumb in crumbs" :key="crumb.index">
<router-link :to="crumb.path">{{ crumb.name }}</router-link> |
</span>

VueJs use props that comes from <router-link>

i have a navbar and there is a text field in that the user can search for posts by tags. If the user enters 1-3 tags, the written tags will be stored in a tags array.
My router-link in the navbar component looks like this: (only relevant part)
<router-link :to="{name:'posts', props:{searchTags: tags}}">
<button type="button" v-if="this.tags.length > 0"
class="...">Search
</button>
</router-link>
in my routes.js is my posts route (important snippet of my routes.js)
routes: [
{
path: "/posts",
component: posts,
name: 'posts'
},
]
The navbar should send the tags array to the posts component. Unfortunately I can't do it.
The posts component, sends a post request to an API that gets the latest posts. But I want that when tags are passed, not the newest posts are fetched, only posts with certain tags. But first I have to get the tags somehow.
I tried to get them with "this.$props.searchTags" and other things. Unfortunately the result is always "undefined".
export default {
name: "posts",
props: {
searchTags: Array,
required: false
},
data: function () {
return {
apiUrl: '/getPosts',
....
tags: [this.searchTags],
}
},
methods: {
getPosts: function (url) {
this.$http.get(url).then(function (data) {
// blabla
});
},
getPostsByTags: function() {
//
},
},
created() {
if(this.$props.searchTags == null)
this.getPosts(this.apiUrl);
else
this.getPostsByTags(bla);
},
}
Router link to property accepts string or Location as a value. Location object does not have props property.
Instead, it is possible to use params to send data to route component:
<router-link
:to="{ name: 'posts', params: { searchTags: tags } }"
>
...
</router-link>
This way searchTags with value of assigned tags will be accessible via this.$route.params.searchTags inside destination component.
So created hook of example above should be updated to:
created () {
if (!this.$route.params.searchTags) {
this.getPosts(this.apiUrl);
} else {
this.getPostsByTags(bla);
}
},
Try to add props: true in your route definition
routes: [
{
path: "/posts",
component: posts,
name: 'posts',
props: true
},
]

vue-router same route with different param

I am on the /entries/12 route. On the same component I would like to push /entries/13 when user clicks the next button.
Code is like :
//e is the next page number.
this.$router.push({ name: 'Entries', params: { pageNum: e }});
I get below error:
If i try different route that works.
Whole code:
<template>
<div class="entries">
<generic-entries #clicked="clicked" ></generic-entries>
</div>
</template>
<script>
import GenericEntriesComp from '#/components/GenericEntriesComp';
export default{
name: 'entries-comp',
components: {genericEntries: GenericEntriesComp},
mounted(){
var params = {id : this.$route.params.pageNum}
this.$store.dispatch("getEntries",params);
},
methods: {
clicked(e){
this.$router.push({ name: 'Entries', params: { pageNum: e.toString() }});
},
loadData(){
var params = {pageNum : this.$route.params.pageNum}
this.$store.dispatch("getEntries", params)
}
},
computed: {
items(){
return this.$store.state.entries
},
},
watch: {
'$route': 'loadData'
}
}
</script>
Btw the error comes from :
Vue.config.errorHandler = function (err, vm, info) {
console.error(err);
}
I solved my problem with :key. This way, I guarantee that all router-view content will be re-rendered whenever there is a $route change.
<router-view :key="$route.fullPath" #showLoading="showLoading"></router-view>
Found the answer.
Seems vue-router works as expected. In my case there were another problem.
If I have below code also in generic component I beleive it loops and produce an error.
watch: {
'$route': function(){
this.loadData();
}
}
In my case I removed the watcher from the generic component and it worked.
If you have decided to change the route parameter programmatically, then you should use replace instead of push as like below:
//e is the next page number.
this.$router.replace({ name: 'Entries', params: { pageNum: e }});