Commentaires
Dans cette partie, nous allons afficher une news et ses commentaires. Pour être très franc, la gestion des commentaires n'a rien de très pédagogique au niveau de vue router. Nous allons donc passer outre. Si cela t'intéresse, tu pourras essayer de l'implémenter de ton côté ;)

Arthur, l'apprenti développeurOk, noté chef !
Là, ce qui est intéressant, c'est comment récupérer l'id côté "NewsShow". Celui qui a été passé dans l'URL.
Mais avant cela, il faut s'intéresser à quelque chose de beaucoup plus bête... Notre API ne nous fournit pas d'id pour les articles. Du coup, on va en inventer un :). On va simplement dire que l'index de la news dans le tableau de news est son id. Cela implique forcément que s'il y a de nouvelles données offertes par notre API entre le moment où consulte toutes les news et au moment où en consulte une, évidemment, on risque de pas voir la bonne... Mais bon, c'est pas dramatique, c'est un projet fictif encore une fois.
Du coup, je modifie un peu le composant NewsAll.vue pour prendre en compte cette problématique :
{"language":"text/html","content":"<template>\n <h2 class=\"text-blue-400 text-xl\">Toutes les news</h2>\n\n <div v-if=\"error\" class=\"error\">{{ error }}</div>\n\n <div class=\"grid gap-16 pt-12 grid-cols-3 gap-x-5 gap-y-12\">\n <MiniNews v-for=\"currentNews in news\" v-bind=\"currentNews\" :key=\"currentNews\" />\n </div>\n\n</template>\n\n<script>\n import MiniNews from './../components/MiniNews.vue'\n export default {\n components:{MiniNews},\n data() {\n return {\n loading: false,\n news: null,\n error: null,\n }\n },\n created() {\n this.fetchData()\n },\n methods: {\n fetchData() {\n this.error = this.news = null\n this.loading = true\n fetch(`http://api.mediastack.com/v1/news?access_key=${process.env.VUE_APP_MEDIASTACK_KEY}&countries=fr`)\n .then(data => data.json())\n .then(data => {\n this.loading = false\n\n this.news = data.data.sort((a, b) => {\n return a.published_at < b.published_at\n })\n // Je crée de faux id\n let i = 0;\n const length = this.news.length\n for(; i < length; i++) {\n this.news[i].id = i;\n }\n })\n .catch(error => {\n this.error = (JSON.parse(error)).message\n })\n },\n },\n }\n\n</script>","filename":"NewsAll.vue"}

Arthur, l'apprenti développeurRien de bien compliqué, j'ai compris.

Parfait ;). Passons donc à la récupération de l'id dans notre composant NewsShow. Pour ça, nous avons deux possibilités :
- Utiliser l'API de Vue
- Utiliser les props
De manière usuelle, j'utilise les props. Mais nous allons voir les deux manières ;)

Pour récupérer un paramètre, il suffit d'utiliser $route. $route est un objet offert par l'API de Vue lorsqu'on utilise vue-router. Il a notamment un élément nommé "params" qui est un objet qui contient les paramètres de l'URL spécifiés lors de la création de notre route.
Voici donc notre composant :
{"language":"text/html","content":"<template>\n <div v-if=\"loading\" class=\"loading\">Loading...</div>\n <div v-if=\"error\" class=\"error\">{{ error }}</div>\n <h2 class=\"text-blue-400 text-xl py-12\">{{ title }}</h2>\n <div class=\"mx-auto flex justify-center\" v-if=\"image && !image.includes('youtube')\">\n <img class=\"h-24 w-30 object-cover\" :src=\"image\" :alt=\"title\">\n </div>\n <p class=\"mt-3 text-base text-gray-500\">\n {{ description }}\n </p>\n <p>Auteur : <span v-if=\"author\">{{ author }}</span><span v-else>Non communiqué</span></p>\n <p>Accéder à l'article : <a :href=\"url\">\"{{ title }}\" sur <u>{{ source }}</u></a></p>\n\n</template>\n<script>\n export default {\n data() {\n return {\n error: null,\n loading: null,\n title: null,\n image: null,\n description: null,\n source: null,\n author: null,\n url: null,\n }\n },\n created() {\n this.fetchData()\n },\n methods: {\n fetchData() {\n this.error = null\n this.loading = true\n fetch(`http://api.mediastack.com/v1/news?access_key=${process.env.VUE_APP_MEDIASTACK_KEY}&countries=fr`)\n .then(data => data.json())\n .then(data => {\n this.loading = false\n this.title = data.data[this.$route.params.id].title\n this.url = data.data[this.$route.params.id].url\n this.image = data.data[this.$route.params.id].image\n this.description = data.data[this.$route.params.id].description\n this.author = data.data[this.$route.params.id].author\n this.source = data.data[this.$route.params.id].source\n\n })\n .catch(error => {\n this.error = (JSON.parse(error)).message\n })\n },\n },\n }\n</script>","filename":"NewsShow.vue"}

Et comme je le disais, on peut utiliser les props. Pour ce, il faut le préciser directement dans notre router en utilisant l'élément props avec comme valeur "true", comme suit (bien regarder la route liée à NewsShow) :

{"language":"text/javascript","content":"const routes = [\n {\n path: '/',\n name: 'Home',\n component: Home\n },\n {\n path: '/mentions-legales',\n name: 'Legals',\n component: Legals,\n },\n {\n path: '/connexion',\n name: 'Connexion',\n component: Connexion\n },\n {\n path: '/news',\n name: 'News',\n component: News,\n children: [\n {\n path: '',\n name: 'News.All',\n component: NewsAll,\n },\n {\n path: ':id(\\\\d+)',\n props:true,\n name: 'News.Show',\n component: NewsShow\n }\n ]\n }\n]","filename":"index.js"}

Il ne nous reste plus qu'à définir la props côté composant et l'utiliser comme habituellement :

{"language":"text/html","content":"<template>\n <div v-if=\"loading\" class=\"loading\">Loading...</div>\n <div v-if=\"error\" class=\"error\">{{ error }}</div>\n <h2 class=\"text-blue-400 text-xl py-12\">{{ title }}</h2>\n <div class=\"mx-auto flex justify-center\" v-if=\"image && !image.includes('youtube')\">\n <img class=\"h-24 w-30 object-cover\" :src=\"image\" :alt=\"title\">\n </div>\n <p class=\"mt-3 text-base text-gray-500\">\n {{ description }}\n </p>\n <p>Auteur : <span v-if=\"author\">{{ author }}</span><span v-else>Non communiqué</span></p>\n <p>Accéder à l'article : <a :href=\"url\">\"{{ title }}\" sur <u>{{ source }}</u></a></p>\n\n</template>\n<script>\n export default {\n props:['id'],\n data() {\n return {\n error: null,\n loading: null,\n title: null,\n image: null,\n description: null,\n source: null,\n author: null,\n url: null,\n }\n },\n created() {\n this.fetchData()\n },\n methods: {\n fetchData() {\n this.error = null\n this.loading = true\n fetch(`http://api.mediastack.com/v1/news?access_key=${process.env.VUE_APP_MEDIASTACK_KEY}&countries=fr`)\n .then(data => data.json())\n .then(data => {\n this.loading = false\n this.title = data.data[this.id].title\n this.url = data.data[this.id].url\n this.image = data.data[this.id].image\n this.description = data.data[this.id].description\n this.author = data.data[this.id].author\n this.source = data.data[this.id].source\n\n })\n .catch(error => {\n this.error = (JSON.parse(error)).message\n })\n },\n },\n }\n</script>","filename":"NewsShow.vue"}


Fastoche ! On passe à la suite ?

Arthur, l'apprenti développeurOui !
Nous allons maintenant voir comment protéger nos routes sensibles, celles accessibles uniquement lorsqu'on est connecté ou qu'on est modérateur par exemple. À nous les navigation guards ! J'ai terminé cette partie
Demander de l'assistance