Normally in Nuxt when creating dynamic routing for things like blogs post, I would do something like the following structure.
Pages directory
pages/posts/
pages/posts/index.vue
pages/posts/_category/
pages/posts/_category/index.vue
pages/posts/_category/_sub-category/
pages/posts/_category/_sub-category/_id.vue
/pages/posts/_category/_sub-category/_id.vue
<template>
<div>
<h1>{{ title }}</h1>
</div>
</template>
<script>
import axios from 'axios'
export default {
data () {
return {
id: this.$route.params.id,
all_posts: '',
filtered_post: '',
post_data: '',
category: '',
sub_category: '',
title: ''
}
},
mounted () {
this.getSingle()
},
methods: {
getSingle () {
axios.get('someapiendpoint')
.then((response) => {
// get response data
this.all_posts = response.data
// filter response data by id
this.filtered_post = this.all_posts.filter(post => post.id === this.id)
// get data from index [0]
this.post_data = this.filtered_post[0]
// set data vars
this.category = this.post_data.category
this.sub_category = this.post_data.sub_category
this.title = this.post_data.title
})
}
}
}
</script>
Nuxt.config.js
generate: {
routes () {
return axios.get('https://someapiendpoint').then((res) => {
return res.data.map((post) => {
return {
route: '/posts/' + post.category + '/' + post.slug + '/' + post.id,
payload: (post)
}
})
})
}
},
Nuxt Links
<nuxt-link :to="{ path: '/posts/' + post.category + '/' + post.sub_category + '/' + post.id}" v-for="post in displayedPosts" :key="post.id">
{{ post.title }}
</nuxt-link>
And this would generate routes like
/posts/my-category/my-sub-category/my-article-title/12345
My question is how can I remove the ID from the URL and still get the data based on the ID but with a URL like this
/posts/my-category/my-sub-category/my-article-title/
Keeping the id on the URL is not really good for SEO. You can filter your posts only by slugs instead of IDs, a slug is unique for each post. or if you still want to use the ID as the key to filter, you can use Vuex to save the current post ID on click.
Related
I have a page that I use to show 3 differents html depending on where it is called.
In a page I have:
openCreateAnagraphics(){
this.router.navigate(["/anagraphics", {customerUpdate: true}]);
}
So I'm navigate to anagraphics.
there I have in my anagraphics.page.ts:
ngOnInit() {
this.handleParams();
}
handleParams() {
let params = this.route.snapshot.params;
console.log("this.route.snapshot", this.route.snapshot)
console.log("params", params)
this.customerUpdate = params.customerUpdate ? params.customerUpdate : false
console.log("this.customerUpdate ", this.customerUpdate)
}
and in the anagraphics.page.html
<div *ngIf="....">
<div>
//this is showed if I come from another way
</div>
</div>
<div *ngIf="customerUpdate">
<div>
HELLO // there is the problem
</div>
</div>
but I see only a white page and my url is
http://localhost:4200/anagraphics;customerUpdate=true
I would to obtain that I if i click on the button that calls openCreateAnagraphics, I'll go in a page that show the html when customerUpdate = true.
EDIT 1:
In my app-routing.module.ts
{ path: 'anagraphics', loadChildren: () => import('./anagraphics/anagraphics.module').then(m => m.AnagraphicPageModule), canActivate: [AuthGuard], data: { configurator: true, customerUpdate: false } },
but in this way customerUpdate is always on false.
My solution reference link: https://angular.io/api/router/RouterEvent
In your .routing.module.ts file add data like the below.
const routes: Routes = [{
path: '',
component: AlertsComponent,
data: {
// What data you want to pass add that here
}
}]
Then get that value in your common component like below. (Like: app or nav component)
constructor(public router: Router) {
router.events.pipe(
filter((e: Event): e is RouterEvent => e instanceof RouterEvent)
).subscribe((e: RouterEvent) => {
// Get your route data here
});
}
I have a vue application where I am displaying information inside of vuetify chips. When I want to click on a specific chip I want the console to log the value inside it. I tried accessing the array which the information originate from but I am getting an undefined error. Could someone look at my code and tell me what is wrong with it?
html:
<v-chip-group
v-model="selection"
active-class="deep-purple--text text--accent-4"
mandatory
>
<v-chip
v-for="(time, i) in dateTimeArray"
:key="time"
:value="time.startTime+' | '+time.endTime"
#click="pushSelected()"
>
{{ time.startTime +" : "+ time.endTime }}
</v-chip>
</v-chip-group>
Script:
export default {
name: "MeetingAdminComponent",
data : ()=>({
singleSelect: false,
selection: "",
dateTimeArray:[],
availableTimes: [
],
}),
created() {
this.getAvailableMeetingTimes()
},
methods:{
getAvailableMeetingTimes() {
var pageURL = window.location.href;
var lastURLSegment = pageURL.substr(pageURL.lastIndexOf('/') + 1);
axios.get("http://localhost:8080/api/voterAvailableTime/findBy", {
params: {
meetingName: lastURLSegment,
}
})
.then(response => (this.availableTimes = response.data)
)
},
getTimesFilteredByDate() {
var pageURL = window.location.href;
var lastURLSegment = pageURL.substr(pageURL.lastIndexOf('/') + 1);
var selectedDate = this.selectedDate
axios.get("http://localhost:8080/api/voterAvailableTime/find", {
params: {
meetingName: lastURLSegment,
date: selectedDate
}
})
.then(response => (this.dateTimeArray = response.data))
},
pushSelected(){
console.log(this.availableTimes.startTime+ " " + this.availableTimes.endTime)
}
}
};
</script>
Pass the current item as parameter to the method :
<v-chip
v-for="(time, i) in dateTimeArray"
:key="time"
:value="time.startTime+' | '+time.endTime"
#click="pushSelected(item)"
in methods:
pushSelected(item){
console.log(item.startTime+ " " + item.endTime)
}
I am trying to complete a CRUD application with Vuejs and Laravel. Right now I can add an article but cannot delete and I ssee this error in my console:
SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
The html inside the template is like the following:
<div class="card card-body"v-for="article in articles" :key="article.id">
<h3>{{ article.title }}</h3>
<p>{{ article.body }}</p>
<button #click="deleteArticle(article.id)" class="btn btn-danger">Delete</button>
</div>
Then inside the script I have this:
How can I make the delete work?
<script>
export default {
data(){
return{
articles: [],
article: {
id: '',
title: '',
body: ''
},
article_id: '',
pagination: {},
edit: false
}
},
created(){
this.fetchAllArticles();
},
methods: {
fetchAllArticles(){
fetch('/api/articles').then(res => res.json()).then(res => {
this.articles = res.data;
})
.catch(err => console.log(err));
},
deleteArticle(id){
if(confirm('Are you sure?')){
fetch('api/article/${id}', {
method: 'delete'
})
.then(res => res.json())
.then(data => {
alert('Article removed');
this.fetchAllArticles();
})
.catch(err => console.log(err));
}
}
}
}
</script>
If I type my url for the delete method I can view the data as you can see in the image:
My delete controller looks like this:
public function destroy($id)
{
// Get article
$article = Article::findOrFail($id);
if($article->delete()) {
return new ArticleResource($article);
}
}
From the netwok in the browser I see this:
Thanks in advance
I have never use fetch i love using axios, but through googling i found that you have to use not those symbols '' but those `` so:
fetch(`api/article/${id}`, {
method: 'delete'
})
From what I see in your console the API address is incorrect, should be 'api/article/' + id
I build following component:
var Modal = Vue.component('modal', {
template: `
<div id="modal" class="modal">
<div class="modal-content">
<p>{{ link }}</p>
</div>
</div>
`,
props: [
'link'
],
});
And I would like to change the link data dynamically after I sent successfully an axios post.
My vue instance
new Vue({
el: '#form',
components: {
'modal': Modal
},
data: {
userId: '',
title: '',
body: '',
snippetLink: '',
},
methods: {
publish (e) {
var self = this;
axios.post('/snippets', {
title: this.title,
body: this.content,
})
.then(function (response) {
console.log("success");
self.link = response.data.hash; // Here I tried to add the reponse content to the vue component's p
})
.catch(function (error) {
console.log(error);
})
},
My Html Markup:
<modal link=""></modal>
...
<button type="button"
v-bind:class="{ 'modal-trigger': !isActiveModal }"
#click="publish">Publish
<i class="material-icons right">send</i>
</button>
So I am sending an axios post to my server successfully and get the data, I would like to open a modal window and put the data in a p tag, so far the modal pops up after my post but I am not sure my it does not change the content of the p tag.
As per my understanding , Snippetlink property can be used to hold data from server.
self.Snippetlink = response.data.hash;
and Pass Snippetlink to link attribute of the snippet-model
<snippet-modal :link="Snippetlink"></snippet-modal>
rupesh_padhye's answer is correct. This is just a further explanation.
First of all, to store the response data to a Vue component, you need to define a key in data for that purpose first. So to make this line work: self.link = response.data.hash;, you need to add link as a key for the Vue component's data:
data: {
userId: '',
title: '',
body: '',
snippetLink: '',
link: ''
},
If you mean snippetLink, change the line to self.snippetLink = response.data.hash;
Secondly, to pass the data as a prop to a child component, you have to specify the prop name, as well as the data key being passed. For instance, to pass your component's link as a prop with the same name to the snippet-modal component, you need: <snippet-modal :link="link"></snippet-modal>
I'm trying to reference child nodes of a firebase database using a for loop. I'm using Vue and Vue-fire. The problem is that in the following code, categories[addItem.category] doesn't reference the correct data.
<el-select v-model="addItem.category" placeholder="Select a category." id="category-select">
<el-option
v-for="(val, key) in categories"
:key="val['.key']"
:label="val['.key']"
:value="val['.key']">
</el-option>
</el-select>
<el-button #click="showAdd=true">new category</el-button>
<el-select v-model="addItem.subcategory" placeholder="Select a subcategory." id="subcategory-select" v-show="addItem.category!=''">
<el-option
v-for="subcat in categories[addItem.category]"
:key="subcat['.key']"
:label="subcat['.key']"
:value="subcat">
</el-option>
</el-select>
<el-button v-show="addItem.category!=''" #click="showAdd=true">add subcategory</el-button>
I am trying to get all the keys of the selected category, which should give 'machinery' if 'mechanical' is selected. Currently, selecting 'mechanical' makes categories[addItem.category] equal to undefined. Here is what the data looks like in my db:
[![enter image description here][1]][1]
Can anyone tell me why my firebase reference categories[addItem.category] isn't referencing the child values?
If it helps, this is how I save the data:
methods: {
add(){
var updates = {};
if (this.addItem.category==''){
updates['/' + this.addItem.text + '/'] = "null";
}
else if (this.addItem.subcategory==''){
console.log('adding a subcategory: ' + this.addItem.subcategory);
console.log(this.addItem.category + ' is the category name');
updates['/' + this.addItem.category + '/' + this.addItem.text + '/'] = "null";
}
db.ref('categories').update(updates).then((successMessage) => {
// successMessage is whatever we passed in the resolve(...) function above.
// It doesn't have to be a string, but if it is only a succeed message, it probably will be.
console.log("Yay! " + successMessage);
});
Which references the following data:
data(){ return {
addItem: {
open: false,
count: 0,
category: '',
subcategory: '',
kks: {
name: ''
},
document: {
name: ''
},
product: {
name: ''
},
text: ''
},
}}
}
and here is the firebase property:
firebase: function(){
return {
categories: db.ref('categories')
}
}
[1]: https://i.stack.imgur.com/hYZN6.png
Here's what I ended up doing. The following was added as a computed property:
subcategories: function(){
if (this.addItem.category){
var val;
db.ref('categories/' + this.addItem.category).on('value', function(snapshot){
val = snapshot.val();
});
return val;
}
return this.categories;
}