Router link in vuetable? - vuejs2

I use vuetable 2 in the project. In this table I take data from json. It is necessary to do, for example:
There is a column to Order, in it information ORD1231 ** and so on. When you click on one of the cells, the order goes to another page with a dynamic id. Actually a question, how in vuetable to push router-link?

You can use __slot special field to user router-links.
Inside your <vuetable>, use <template slot=()>
<vuetable ref="vuetable" :fields="fields">
<template slot="code" slot-scope="props">
<router-link :to="props.rowData.code">
{{ props.rowData.code }}
</router-link>
</template>
</vuetable>
and in your script
data() {
return {
fields: {
{
name: '__slot:code'
title: 'Your Title'
}
}
}
}
You can access your data with props.rowData and props.rowIndex attributes.

Related

Component works only once using router-link - Laravel vue

I am working on a project that uses Laravel Vue SPA, and I got a problem accessing the data of the single product, it's only working when I click once, but when I select again with other product, I can't get the product data, but the URL is correct it's changes the ID but can't access the data.
It is working when I click another link like Services then select product, it can display the product data.
Here is my HTML
<ul >
<li v-for="product in products">
<router-link :to="{ name: 'edit-product', params: { id: product.id } }">
{{ product.title }}
</router-link>
</li>
</ul>
My Vue Routes
const EditProduct = require('./components/EditProduct').default;
{
path: '/edit/product/:id',
component: EditProduct,
name: 'edit-product'
}
my EditProduct component
<template>
<div>
<h1>this.$route.params.id</h1>
</div>
</template>
Cheers
Look at this answer. You have to watch the productId and execute your logic again.
Possible solution
try to define a computed property inside your EditProduct component for get product id
computed: {
productId(){
return this.$route.params.id
}
}
and use productId inside your <h1> tag
<template>
<div>
<h1>{{ productId }}</h1>
</div>
</template>
update
solution :
add this watcher to your EditProduct component for reacting with params change
watch: {
$route(to) {
console.log(to.params.id)
// you can call your method here and pass product id to them for example: this.getProductDetails(to.params.id)
},
beforeRouteEnter (to, from, next) {
next(vm => {
//also call your method here => vm.getProductDetails(to.params.id)
});
},
you can read more about params changes here: Reacting to Params Changes

Vue - v-for with modifying values

Template:
<template>
<nav>
<router-link :to="key" v-for="(value, key) in state.menu" :key="key">{{value}} | </router-link>
</nav>
</template>
Code:
export default {
setup() {
const menu = ['home', 'news', 'about'];
const state = reactive({
menu: {}
});
menu.map(item => {
state.menu[item] = Common.locs[item];
});
return {
Common,
state,
}
}
}
I want to update
:to="key"
to run it through some filter or function to modify it to add the prefix something like "/other/", so instead of rendered
<a href="/home" ...>
I would have
<a href="/other/home" ... >
(Of course, const menu values are mocked for the sake of example; those are fetched from the service so I have no saying in that, and I don't want to modify them after fetching for other reasons)
So in general, my question is not regarding proper routing, but how do you modify v-for data (in my case: key) in the runtime if you need to?
(I guess I could modify mapping line into
state.menu["/other/" + item] = Common.locs[item];
but I want to preserve state.menu as I wrote. I want change to happen during the v-for rendering.)
Have you tried the template literal:
<template>
<nav>
<router-link :to="`/other/${key}`" v-for="(value, key) in state.menu" :key="key">{{value}} | </router-link>
</nav>
</template>

VueJS making API calls for every item in v-for and returning them to the right position

Thank you in advance.
So I am fetching list of blog categories via API and rendering it in a list using v-for.
I also need to fetch the amount of blogs in every category and place them beside the category.
But the issue is I am calling a method that calls the api.
<li v-for="item in sidebar" :key="item.identifier">
<nuxt-link
tag="a"
:to="{
name: 'blog-page',
query: { category: item.identifier }
}"
>{{ $localize(item.translations).title }}
{{ getBlogCount(item.identifier) }}
</nuxt-link>
</li>
You know what it shows already example is Animals [Object Promise]
methods: {
async getBlogCount(identifier) {
axios
.get(
"https://example.com/posts?fields=created_at&filter[category.category_id.identifier]=" +
identifier +
"&meta=*"
)
.then(count => {
return count.data.meta.result_count;
});
}
}
What is the best way to handle this kinda thing?
You better call async methods in mounted or created hooks, and set the result to data, and then, use that data in template.
I'd suggest handling this in Script, instead of HTML Template.
What you can do is, depending on when the sidebar is initialized (maybe in the mounted hook), call getBlogCount method to fetch blog counts for each item in sidebar and store that may be in an array or object (or as a separate key-value pair to that same sidebar item object) and then use that data structure to display count values in the template.
Assuming the sidebar is populated in mounted hook and that it's an array of objects, you can do the following:
<template>
<li v-for="item in sidebar" :key="item.identifier">
<nuxt-link
tag="a"
:to="{
name: 'blog-page',
query: { category: item.identifier }
}"
>{{ $localize(item.translations).title }}
{{ item.blogCount }}
</nuxt-link>
</li>
</template>
<script>
mounted () {
// after the sidebar is populated
this.sidebar = this.sidebar.map(async item => {
item.blogCount = await this.getBlogCount(item.identifier)
return item
})
}
</script>
Hope this helps you out

Is it possible to use dynamic scoped slots to override column values inside <v-data-table>?

I'm trying to create a reusable table component that utilizes Vuetify's v-data-table component in order to group common aspects such as a search bar, table actions (refresh, create, etc.) and other features that all of my tables will have. However, I'm running into issues with implementing dynamic, scoped slots inside the table component to account for custom columns. Think of columns like actions, formatted ISO strings, etc.
Here's a simplified example of what I'm trying currently. In the example, I am passing the array customColumns to CustomDataTable.vue as a prop. customColumns has one element with two properties. The slotName property specifies the name of the slot that I'd like to reference in the parent component. The itemValue property specifies the header value that CustomDataTable.vue should override and replace with a scoped slot. The scoped slot is then used in the parent component to correctly format the date in the 'Created At' column.
Parent Component that is implementing the table component:
<template>
<custom-data-table
:items="items"
:headers="headers"
:customColumns="customColumns"
>
<template v-slot:custom-column="slotProps">
<span>{{ formatDate(slotProps.item.createdAt) }}</span>
</template>
</custom-data-table>
</template>
<script>
import CustomDataTableVue from '#/components/table/CustomDataTable.vue'
export default {
data: () => ({
items: [
{
id: 0,
createdAt: new Date().toISOString(),
...
},
...
],
headers: [
{
text: 'Created At',
value: 'createdAt',
sortable: true
},
...
],
customColumns: [
{
slotName: 'custom-column',
itemValue: 'createdAt'
}
]
})
}
</script>
CustomDataTable.vue
<template>
<v-data-table
:items="items"
:headers="headers"
>
<template v-for="column in customColumns" v-slot:item[column.itemValue]="{ item }">
<slot :name="column.slotName" :item="item"/>
</template>
</v-data-table>
</template>
<script>
export default {
name: 'custom-data-table',
props: {
items: {
type: Array,
required: true
},
headers: {
type: Array,
required: true
},
customColumns: {
type: Array
}
}
}
</script>
Is there a way to achieve this? The example does not override the column values and just displays the createdAt ISO string unformatted. I believe the problem might be coming from how I'm assigning the template's slot in CustomDataTable.vue, but I'm sure how else you could dynamically specify a template's slot. Any ideas?
I think the syntax for dynamic slots should be:
<template
v-for="column in customColumns"
v-slot:[`item.${column.itemValue}`]="{ item }"
>
<slot :name="column.slotName" :item="item"/>
</template>

Vue CLI clickable dynamic url from a news API

I'm fetching data from newsapi.org and I want there to be a clickable link after the headlines so that you can read more about the article. But I can't make it work.
Maybe this is too advanced for me since I'm no good at coding. I thought maybe there was a simple way of making the dynamic urls work.
<template>
<div class="api">
<h1>Latest gossip</h1>
<br />
<div v-for="item of items" v-bind:key="item.id">
<h3>{{ item.title }}</h3>
<p>{{ item.description }}</p>
<a v-bind:href="adress">
{{ item.url }}
</a>
</div>
</div>
</template>
I use axios.
<script>
import axios from "axios";
export default {
name: "Api",
props: ["articles"],
data() {
return {
items: [],
adress: "item.url"
};
},
mounted() {
this.getInfo();
},
methods: {
getInfo() {
axios({
method: "GET",
url:
"https://cors-anywhere.herokuapp.com/https://newsapi.org/v2/top-headlines?country=se&category=entertainment&apiKey=XXX",
dataType: "json",
headers: {
"X-Requested-With": "XMLHttpRequest",
"Access-Control-Allow-Origin": "*"
}
}).then(res => {
/* eslint-disable no-console */
console.log(res.data);
this.items = res.data.articles;
});
}
}
};
</script>
You can use vue-router in that case. You create a route with a parameter /news/:id in router/index.js eg.
const router = new VueRouter({
routes: [
{ path: '/news/:id', component: SingleNews }
]
})
then instead of
<a href=""/></a>
use
<router-link :to="{ name: 'news', params: { id: news.id }">{{news.headline}}</router-link>
And finally, retrieve parameter in a SingleNews.vue component using
this.$route.params.id
You can read more about vue-router and dynamic routes in the documentation https://router.vuejs.org/
So from what I understand, you're going to have a separate url for each different news article. It seems like there is a slight misunderstanding about how that information will be passed into the anchor tag, where it should be coming from, and how you're using data.
First, let's address your data method. If you look at the structure of your data you can see that you have an items property, which is an array and an adress property, which is set to a string.
data() {
return {
items: [],
adress: "item.url"
};
},
The problem here is that adress is not dynamic. It will always be the literal string "item.url", which is to say that it will always represent those characters ("item.url") in that order, but it doesn't actually represent any specific item's url property.
The good news is that you should already be seeing the correct url displayed on your page here:
<a v-bind:href="adress">
{{ item.url }}
</a>
Remember that an anchor tag in this case has two parts:
1. What we're displaying to the user.
2. Where we're telling the browser to redirect to.
The proper syntax here (without Vue) would be something like:
<a href="https://somelinktogoto.com">
Some text to display
</a>
What you're currently saying is: "I want an anchor tag to display the item's url to the user and redirect to whatever is stored in the data property called adress". Since adress is only storing the string "item.url", if you inspect your html that's been generated in your browser, I would suspect that all of your anchor tags look something like this:
<a href="item.url">
https://somenewsarticle.com
</a>
Luckily, the fix here is simple. Since you're already using v-bind, the href can use dynamic information, or information that's stored in your data somewhere, which can be referenced by its name. Then you can choose to display anything you'd like to your user. You can also delete your adress property from data, because it's not serving any purpose if all the urls are contained within items.
Try:
<a v-bind:href="item.url" target="_blank">
Read more...
</a>
data() {
return {
items: [],
}
}
Also, no one is good at coding at first, just keep trying to understand how data is flowing and you'll get there!
This line worked out great! Thank you!
<a v-bind:href="item.url" target="_blank">Read more here: </a>
I also deleted the adress data.