How do you pass data in the router-view - vue.js

Like for example
<router-link :to="{ name : 'criminalView', params : { criminalId : this.criminal.id , criminal : this.criminal } }" tag="a" >
<img class="h-18 w-18 rounded-full mr-4 mt-2" src="{{ asset('assets/images/'.$criminal->photo) }}" id="criminalsPhoto" alt="Criminals View" >
</router-link>
how can i accept those params in my CriminalView.vue which handles the router-view component
This is my routes.js
import VueRouter from 'vue-router';
import CriminalView from './components/CriminalView.vue';
import GroupView from './components/GroupView.vue';
let routes = [
{
path : '/criminal/:criminalId',
name : 'criminalView',
component : CriminalView,
props : { criminals }
},
{
path : '/group/:groupId',
name : 'groupView',
component : GroupView,
},
]
export default new VueRouter({
routes,
linkActiveClass: 'is-active'
});
how am I gonna display this in my template such as like this
<section class="w-2/5 ml-2 font-basic" id="criminalProfile">
<p class="font-basic tracking-normal text-2xl mb-4 mt-4 font-normal text-black mr-2">Criminal Profile of {{ this.criminal.full_name }}</p>
<div class="bg-white px-8 py-8 pt-4">
<div class="text-center">
<div id="avatar" class="inline-block mb-6" >
<img :src="avatarPath" class="h-50 w-50 rounded-full border-orange border-2">
<p class="font-bold mt-2 text-blue">$15,000</p>
<p class="mt-2 text-lg font-bold" >Notable Crimes:
<p class="mt-2 text-lg font-normal" >
<em class="font-bold roman">Offenses</em>Descr..
</p>
</p>
<div class="w-full flex justify-between">
<button class="w-full bg-green-theme p-3 text-white mt-4 ml-2 hover:bg-green-second" href="/criminal/" >View Full Profile</button> </div>
</div>
</div>
</div>
</section>
This is in my script tag..
export default {
props : ['criminals'],
name: 'CriminalProfile',
data(){
return {
criminal : this.criminals,
url : window.App.apiDomain
}
},
}
How can i display the props in my router-view which is there in my CriminalView.vue

I'm not 100% sure about camelCasing for groupId so I'm using groupid. Try it out, and let us know about camelCase in the comments.
props: {
//you could set the watch to this if you need.
//groupid: {default: 1}
},
watch: {
$route(to, from) {
var groupid = (typeof to.params.groupid != 'undefined') ? to.params.groupid : 1;
//... do some stuff
}
},

In order to display data from the route params you should be doing something like this
// start route.js
export default new Router({
mode: 'hash', // https://router.vuejs.org/api/#mode
routes: [
{
path: 'my-route/:criminal',
name: 'MyRoute',
component: MyComponent
}
]
})
// End route.js
<template>
<section>
<div>
{{criminals}}
</div>
</section>
</template>
<script>
export default {
name: 'CriminalProfile',
data(){
return {
criminals: ''
}
},
created(){
this.criminals = this.$route.query.myparam
}
}
</script>
Here it's the router link
<router-link :to="{ name: 'CriminalView', params: { criminalId: 123 }}">Criminal</router-link>

In my case this work perfectly,
Try this:
Using this.$route.params.paramName you can access params in router-view component.
<script>
export default{
data() {
criminal_id:'',
criminal_data: ''
},
created() {
this.criminal_id = this.$route.params.criminalId;
this.criminal_data = this.$route.params.criminal;
}
}
</script>

Related

Vue : params value don't change in created method

I have this link to another component with params :
<div class="dropdown-menu bg-light" aria-labelledby="navbarDropdown">
<div v-for="category in categories" :key="category.id">
<div v-if="lang=='ku'"><li><a class="dropdown-item font-weight-bold py-2" href="#" ><router-link :to="{name:'category',params:{id:category.id}}">{{category.catagory_ku}}</router-link></a></li></div>
<div v-else><li><a class="dropdown-item font-weight-bold py-2" href="#" ><router-link :to="{name:'category',params:{id:category.id}}">{{category.catagory_ar}}</router-link></a></li></div>
</div>
</div>
the category component like this :
<template>
<div style="margin-top:132px">
Categories {{id}}
</div>
</template>
<script>
export default {
data(){
return {
id :''
}
},
created(){
this.id=this.$route.params.id
}
}
</script>
when i pressed the route link the id value changed in url but in the page view it just take first id value I clicked and not be changed after I clicked another same link by different id value
Try to define the id as computed property :
<template>
<div style="margin-top:132px">
Categories {{id}}
</div>
</template>
<script>
export default {
computed:{
id(){
return this.$route.params.id
}
}
}
</script>
this should be in the mounted hook
created(){
this.id=this.$route.params.id
}
// replace with
mounted(){
this.id = this.$route.params.id
}
also if you wanna perform some extra actions related to the id changes, you can watch the route
<template>
<div style="margin-top:132px">
Categories {{ id }}
</div>
</template>
<script>
export default {
data() {
return {
id: ''
}
},
mounted() {
this.id = this.$route.params.id
},
watch: {
$route(to) {
this.id = to.params.id
// do other logics here
}
}
</script>

Vue: how to navigate to specific user's profile

i have code below and i want to navigate the user's profile when click on the name after asked by, i tried code below but it's not working and my json file structured as below
**
questions:Array[10] 0:Object category:"General Knowledge" user:"Saffron" difficulty:"medium" incorrect_answers:Array[3] 0:"Cinnamon" 1:"Cardamom" 2:"Vanilla" question:"What is the world's most expensive spice by weight?" type:"multiple"
**
<template>
<div class="container" width=800px>
<b-row>
<b-col cols="8">
<h1> Recently Asked </h1>
<ul class="container-question" v-for="(question1,index) in questions" :key="index"
>
<li v-if="answered" >
{{question1.question.selectedAnswer[index]}}
<li v-else >
{{question1.question}}
<b-row id="asked-info">
<p>Asked by: </p>
<div
id="user"
v-for="(answer, index) in answers(question1)"
:key="index"
>
<router-link to='/profile'> {{ answer }} </router-link>
</div>
</b-row>
<b-row>
<div class="category" v-for="(category,index) in category(question1)" :key="index" #click="selectedAnswer(index)">
<mark> {{ category }} </mark>
</div>
<b-button class="outline-primary" style="margin:auto;">Answer</b-button>
</b-row>
</li></ul>
</b-col>
<b-col>
<div class="ask-button">
<b-button href="#" class="primary">Ask Question</b-button>
</div>
<div>
<b-card
title="Card Title"
style="max-width: 20rem;"
class="mb-2"
>
<b-card-text>
Some quick example text to build on the card title and make up the bulk of the card's content.
</b-card-text>
</b-card>
</div>
<div>
<b-card
title="Card Title"
style="max-width: 20rem;"
class="mb-2"
>
<b-card-text>
Some quick example text to build on the card title and make up the bulk of the card's content.
</b-card-text>
</b-card>
</div>
</b-col>
</b-row>
<router-view />
</div>
</template>
<script>
export default {
data(){
return{
questions: [],
answered: null,
index: 0,
selectedIndex: null,
}
},
watch: {
question1: {
handler() {
this.selectedIndex = null;
this.answered = false;
},
},
},
methods: {
answers(question1) {
let answers = [question1.correct_answer];
return answers;
},
category(question1){
let category = [...question1.incorrect_answers];
return category
},
selectedAnswer(index) {
this.selectedIndex = index;
this.answered = true;
},
// filteredCategory(question1){
// return (question1.filter((question) => question.incorrect_answers == "Kfc"));
// },
},
mounted: function(){
fetch('https://opentdb.com/api.php?amount=10&category=9&difficulty=medium&type=multiple',{
method: 'get'
})
.then((response) => {
return response.json()
})
.then((jsonData) => {
this.questions = jsonData.results
})
}
}
</script>
routes.js
import question from './views/question.vue';
import App from './App.vue';
import Register from '#/components/Register'
import Login from '#/components/Login'
import Logout from '#/components/Logout'
import profile from '#/components/profile'
import contactus from '#/views/contactus'
export const routes = [
{ path: "/question", component: question },
{ path: "/", component: App },
{
path: '/login',
name: 'Login',
component: Login
},
{
path: '/register',
name: 'Register',
component: Register
},
{
path: '/logout',
name: 'Logout',
component: Logout
},
{
path: '/profile',
name: 'profile',
component: profile
},
{
path: '/contactus',
name: 'contactus',
component: contactus
},
]
There are a few things I want to point out here, you don't have to implement all of these, but understand what you are doing wrong:
You are missing the <router-view> tag, which is where you want your component to render because you use <router-link>
params are ignored if a path is provided. Instead, you need to provide the name of the route or manually specify the whole path with any parameter. Here for your reference: https://router.vuejs.org/guide/essentials/navigation.html
if you don't v-bind your property to, it will treat the value as a string. So you want to go like this <router-link :to="yourLink" />
In your case, you want to use <router-link :to="" /> with a dynamic string. There are 2 ways to achieve this: Declarative (<router-link>) and Programmatic (router.push)
Declarative:
<router-link> is like an anchor tag, so you should return a string.
<router-link :to="yourLink"> {{ userr }} </router-link>
computed: {
yourLink() {
return `/profile/${user(question1)}`
}
}
Programmatic
When you do a router.push, you are not doing a “link” anymore. It’s just a click event at that point. So change your router-link to a button with a click event
<button #click="yourLink"> {{ userr }} </button>
methods: {
yourLink() {
this.$router.push({name:'yourComponentName'} ,params:{user(question1)}})
}
}
EDIT
In your router.js:
{
path:'/profile/:user',
name: 'profile,
component: profile,
props: true
}
In your router-link:
<router-link :to="`/profile/${user(question1)}`"> {{ userr }} </router-link>
Then in your profile.vue, you can query the params by this.$route.params.user, for example, if you want to output it in a <p> tag:
<p>{{ this.$route.params.user }}</p>

how do i render searched beer/beers?

hello I want to know how ik can render searched beers in vue
I have a component that renders a list of beers. I also have an component that searches beers. what i want to do is that when I search, my beer list component updates the list and shows me only the list of beers i searched.
this is my beer list component
<template>
<div class="container">
<div>
<Search v-bind:allBeers="allBeers" />
</div>
<div>
<b-card
v-bind:key="beer.id"
v-for="beer in allBeers "
:img-src="beer.image_url"
:alt="beer.name"
img-top
tag="article"
style="max-width: 22rem ;"
class="mb-2"
>
<b-card-text class="c-text">
<h4 class="title">{{ beer.name }}</h4>
<p>{{ beer.ingredients.malt[0].name }}</p>
<router-link
:to="{
name: 'BeerDetails',
params: { id: beer.id, beer:beer },
}"
>
<b-button class="link" size="sm" variant="outline-warning">View Beer details</b-button>
</router-link>
</b-card-text>
</b-card>
</div>
</div>
</template>
<script>
import Search from "./Search";
import { mapGetters, mapActions } from "vuex";
export default {
components: { Search },
name: "Beers",
// props: ["beers"],
methods: { ...mapActions(["fetchBeers"]) },
computed: mapGetters(["allBeers"]),
created() {
this.fetchBeers();
}
};
</script>
and this is my search component here I filter beers that match my input
<template>
<div>
<b-form #submit="onSubmit" #reset="onReset">
<b-form-group id="input-group-1">
<b-form-input id="input-1" v-model="form.search" type="text" required placeholder="search"></b-form-input>
</b-form-group>
</b-form>
</div>
</template>>
<script>
export default {
name: "Search",
props: ["allBeers"],
data() {
return {
form: {
search: ""
}
};
},
methods: {
onSubmit(evt) {
evt.preventDefault();
this.allBeers.filter(beer => {
console.log(beer.name.toLowerCase() == this.form.search);
});
//alert(JSON.stringify(this.form));
},
onReset(evt) {
evt.preventDefault();
this.form.search = "";
}
}
};
</script>
<style scoped>
</style>
How would I use the search component in my beer component to display only the searched beers?
In the search component set a property to each beer, something like this:
onSubmit(evt) {
evt.preventDefault();
this.allBeers.forEach(beer => {
beer.hidden = (beer.name.toLowerCase() == this.form.search);
});
},
And in the beers component, hide the irrelevant beers:
<template>
<div class="container">
<div>
<Search v-bind:allBeers="allBeers" />
</div>
<div>
<div v-for="beer in allBeers" v-bind:key="beer.id">
<b-card v-if="!beer.hidden"
...
</b-card>
</div>
</div>
</div>
</template>

Missing required prop in Vue.js

I am new to vue.js so maybe i'm missing something obvious. I have created 2 components Content.vue & ViewMore.vue. I am passing property "genre" which is inside array "animesByGenre" in Content.vue to ViewMore.vue but somehow it is not working.
Here is the Content.vue component:
<div v-for="(animesAndGenre, index) in animesByGenres" :key="index"
id="row1" class="container">
<h5>
{{animesAndGenre.genre.toUpperCase()}}
<button class="viewMore" v-bind:genre="animesAndGenre.genre"><router-link :to="{name: 'viewmore'}">view more</router-link></button>
</h5>
<vs-row vs-justify="center" class="row">
<vs-col v-for="(anime, i) in animesAndGenre.animes" :key="i"
vs-type="flex" vs-justify="center"
vs-align="center" vs-w="2" class="animeCard">
<vs-card actionable class="cardx">
<div slot="header" class="cardTitle">
<strong>
{{anime.attributes.canonicalTitle}}
</strong>
</div>
<div slot="media">
<img :src="anime.attributes.posterImage.medium">
</div>
<div>
<span>Rating: {{anime.attributes.averageRating}}</span>
</div>
<div slot="footer">
<vs-row vs-justify="center">
<vs-button #click="addAnimeToWatchlist(anime)"
color="primary" vs-type="gradient" >
Add to Watchlist
</vs-button>
</vs-row>
</div>
</vs-card>
</vs-col>
</vs-row>
</div>
<script>
import ViewMore from './ViewMore.vue';
import axios from 'axios'
export default {
name: 'Content',
components: {
'ViewMore': ViewMore,
},
data () {
return {
nextButton: false,
prevButton: false,
viewMoreButton: false,
results: '',
animes: '',
genres: ['adventure', 'action', 'thriller', 'mystery', 'horror'],
animesByGenres: []
}
},
created() {
this.getAnimes();
// this.getRowAnime();
this.genres.forEach( (genre) => {
this.getAnimeByGenres(genre);
});
},
}
</script>
Here is the ViewMore.vue component (i'm just trying to log genre for now):
<template>
<div>
</div>
</template>
<script>
import axios from 'axios'
export default {
props: {
genre: {
type: String,
required: true,
},
},
data() {
return {
allAnimes: '',
}
},
created() {
console.log(this.genre);
}
}
</script>
Passing props to routes doesn't work like that. Right now, all this code is doing is applying the genre prop to the button itself, not to the route it's going to. You'll need to add the genre to the URL as a param (/viewmore/:genre/), or as a part of the query (/viewmore?genre=...). See this page for how that works

VueJS + VueRouter + Bootstrap-vue (modal from modal) = <failed to convert exception to string>

I'll try display modal from modal (I'll create separate components for each modal). When second modal is closed I want to return to first modal. But after I'm display first modal second time I got error 'failed to convert exception to string' from administration.js. I'm using VueRouter too.
administration.js (main entry with router-view) -> partner.vue (with partnerEditor.vue component)
partnerEditor.vue
<template>
<div>
<b-modal ref="partnerEditor" title="Partner" :busy="isBusy" cancel-title="cancel" ok-variant="info" ok-title="save" v-on:ok="onCreate">
<div class="form-group">
<div class="input-group mb-3">
<select class="form-control">
<option v-for="contact in contacts">{{ contact.name }}</option>
</select>
<div class="input-group-append">
<b-btn v-on:click="$refs.contactEditor.show()"></b-btn>
</div>
</div>
</div>
</b-modal>
<contactEditor ref="contactEditor" v-on:hide="$refs.partnerEditor.show()"></contactEditor>
</div>
</template>
<script>
export default {
data() {
return {
contacts: [],
isBusy: false
}
},
methods: {
show() {
this.$refs.partnerEditor.show();
}
},
components: {
contactEditor: () => import('./contactEditor.vue'),
},
}
</script>
contactEditor.vue
<template>
<b-modal ref="contactEditor" title="Contact" :busy="isBusy" cancel-title="cancel" ok-variant="info" ok-title="save" v-on:ok="onCreate" v-on:hide="$emit('hide')">
<div class="form-group">
<label>name</label>
<input type="text" class="form-control" placeholder="" />
</div>
</b-modal>
</template>
<style></style>
<script>
export default {
model: {
event: 'hide'
},
data() {
return {
isBusy: false
}
},
methods: {
show() {
this.$refs.contactEditor.show();
},
}
}
</script>
routes
const router = new VueRouter({
routes: [
{
name: 'configuration', path: '/configuration', component: () => import('./administrator/configuration/index.vue'),
children: [
{ name: 'configuration-partner', path: '/configuration/partner', component: () => import('./administrator/configuration/partner.vue') }
]
}
]
});