I'm trying to get only 1 response from the Nasa images API using VueJS and Axios. I've followed the tutorial here(https://www.youtube.com/watch?v=GiIQce7Rx4Y&t=939s) and the app is working just like shown. But this tutorial shows how to get the complete list of images available through this API, I only want the first image but can't figure out how.
Here's the code for the api component:
<template>
<div class="search">
<section id="sectionB">
<h2>Type in your search term</h2>
<form v-on:submit.prevent="getResult(query)">
<input type="text" placeholder="Type in your search" v-model="query" />
</form>
<br/>
<div v-if="results">
<div v-for="result in results" v-bind:key="result">
<img v-bind:src="result.links[0].href" class="imgContainer" />
</div>
</div>
</section>
</div>
</template>
<script>
import axios from "axios";
export default {
name: "search",
data() {
return {
msg: "Search",
query: "",
results: "",
};
},
methods: {
getResult(query) {
axios.get(
"https://images-api.nasa.gov/search?q=" + query + "&media_type=image"
)
.then((response) => {
console.log(response.data.collection.items);
this.results = response.data.collection.items;
});
},
},
};
</script>
I tried removing f-for to stop the loop but that removed all images, not just everyone after the first.
You should refer to the documentation of the API on the website of Nasa: https://images.nasa.gov/docs/images.nasa.gov_api_docs.pdf. The only endpoint they have that returns images is the search endpoint that you are using.
However, reading your question again.. You can just show the first of the list (array) of results: results[0], like below:
<div v-if="results">
<img v-bind:src="results[0].links[0].href" class="imgContainer" />
</div>
Related
Main.vue:
<template>
<div>
<div class="home_page_header">
<h1>My Recipe</h1>
<button #click="toggleOpen">Add New Recipe</button>
</div>
<div v-for="recipe in $store.state.recipes" :key="recipe.Recipe_Name">
<h1 >{{recipe.Recipe_Name}}</h1>
<p>{{recipe.Ingredients}}</p>
<router-link :to="`/recipe/${recipe.Recipe_Name}`">
<button>View Recipe</button>
</router-link>
<router-view/>
</div>
<div>
<h1></h1>
<p></p>
</div>
<div class="popUp" v-show="openUp">
<div>
<label for="receipe_name">Recipe Name</label>
<input type="text" id="receipe_name" v-model="values.receipeName"/>
</div>
<div>
<label for="ingredients_name">Ingredients</label>
<input type="text" id="ingredients_name" v-model="values.ingredientsName" v-for="i in values.ingredientsRows" :key="i"/>
<button #click="addrows" >Add Ingredients</button>
</div>
<div><button #click="onSubmit">Submit</button></div>
<div><button #click="toggleClose">Close</button></div>
</div>
</div>
</template>
<script>
import store from '#/store/index.js'
export default {
data() {
return {
values:{
receipeName:'',
ingredientsName:'',
ingredientsRows:1
},
values_final:{
receipeName:'',
ingredientsName:'',
ingredientsRows:1
},
openUp : false
}
},
methods: {
toggleOpen(){
this.openUp = true
},
toggleClose(){
this.openUp = false
},
onSubmit(){
if(this.values.receipeName || this.values.ingredientsName == ''){
alert('enter the full details')
}
},
addrows(){
this.values.ingredientsRows++;
},
},
computed: this.$store.commit('Add_Recipes',{...values_final})
}
</script>
store:
import { createStore } from 'vuex'
export default createStore({
state: {
recipes:[
{
Recipe_Name: 'curd',
Ingredients:'xxxxxx'
}
]
},
mutations: {
Add_Recipes (state,recipe) {
state.recipes.push(recipe)
}
},
Error : app.js:340 Uncaught TypeError: Cannot read properties of undefined (reading '$store')...
I'm trying to create a recipe app by using option API, I have one main page. In that main page that contains one title and add recipe button to add the details. And another one is a popup to enter the recipe details. so here after entering all the details that should show in a main page. I'm trying to access the store in a main page but iam getting the above error.
I guess you need to move the import statement of your store to your main.js file (not your Main.vue). And add app.use(store) after you created the app there with const app = createApp(…).
I'm installing #nuxtjs/recaptcha on my nuxt project, which is google reCaptcha V3. It looks like it's working great it's always returning success result from the servers like below.
{success: true, challenge_ts: '2022-05-05T11:37:06Z', hostname: 'localhost', score: 0.9}
But I'm not sure this work properly because the challenge does not appear. Recaptcha as I know it, should have a challenge that must be met. But why doesn't the challenge appear here?
Maybe it needs to be triggered with some event handler? But in the documentation example I didn't saw any things related about it or maybe I just do not realize it.
May be im missing something important, so I need your help to figure it out.
My template code
<template>
<div class="container">
<h1 align="center">SEND EMAIL TO US!</h1>
<div class="layout">
<form #submit.prevent="onSubmit">
<div class="basic-info">
<div class="name">
<label for="">Name :</label>
<b-form-input v-model="data.name" placeholder="Name"></b-form-input>
<div v-if="validation.name" class="mt-2">
<b-alert show variant="danger">{{ validation.name[0] }}</b-alert>
</div>
</div>
<div class="email">
<label for="">Email :</label>
<b-form-input
v-model="data.email"
placeholder="Email"
></b-form-input>
<div v-if="validation.email" class="mt-2">
<b-alert show variant="danger">{{ validation.email[0] }}</b-alert>
</div>
</div>
<div class="messege">
<label for="">Messege :</label>
<b-form-textarea
id="textarea"
v-model="data.messege"
placeholder="Enter Messege..."
rows="8"
max-rows="8"
></b-form-textarea>
<div v-if="validation.messege" class="mt-2">
<b-alert show variant="danger">
{{ validation.messege[0] }}
</b-alert>
</div>
</div>
<hr />
<b-button type="submit" variant="outline-primary">
SEND EMAIL
</b-button>
<hr />
<b-alert v-model="alert" show :variant="variant">
{{ result_messege }}
</b-alert>
</div>
</form>
</div>
</div>
</template>
my script code
<script>
export default {
async mounted() {
try {
await this.$recaptcha.init()
} catch (e) {
console.log(e)
}
},
methods: {
async onSubmit() {
try {
this.loading = true
// Start the verification process
const response = await this.verifyCaptcha()
console.log(response)
// Display error message if verification was not successful
if (!response.success) {
this.$recaptcha.reset()
this.loading = false
this.errorStatus = true
this.notificationMessage =
'There was an error with your reCaptcha verification. Please try again.'
return
}
// If verification was successful, send the message
await this.sendMail()
this.errorStatus = false
this.notificationMessage =
'Thank you for reaching out. We will get back to you as soon as possible'
this.loading = false
this.$recaptcha.reset()
} catch (error) {
this.loading = false
console.log(error)
}
},
async verifyCaptcha() {
try {
const token = await this.$recaptcha.execute()
console.log(token)
const response = await this.$axios.$post(
`/captcha-api/siteverify?secret=${process.env.SECRET_KEY}&response=${token}`
)
return response
} catch (error) {
this.loading = false
return error
}
},
},
}
</script>
This is totally normal, this is the whole concept of the v3 as you can see in this video: https://youtu.be/tbvxFW4UJdU
More details are also here: https://developers.google.com/recaptcha/docs/v3
And here: https://www.google.com/recaptcha/about/
So far, the feature is exactly this: do not require any interaction from the user but rather use some mouse trackers/AI to know if it's potentially malicious or not.
I'm just starting to use VueJS & Tailwind, having never really used anything related to npm before.
I have the below code, making use of Tailwind & Headless UI which through debugging, I know I'm like 99% of the way there... except for the continuous error message
Uncaught ReferenceError: posts is not defined
I know this should be straight forward, but everything I've found either here or with Google hasn't worked. Where am I going wrong?
<template>
<Listbox as="div" v-model="selected">
<ListboxLabel class="">
Country
</ListboxLabel>
<div class="mt-1 relative">
<ListboxButton class="">
<span class="">
<img :src="selected.flag" alt="" class="" />
<span class="">{{ selected.name }}</span>
</span>
<span class="">
<SelectorIcon class="" aria-hidden="true" />
</span>
</ListboxButton>
<transition leave-active-class="" leave-from-class="opacity-100" leave-to-class="opacity-0">
<ListboxOptions class="">
<ListboxOption as="template" v-for="country in posts" :key="country" :value="country" v-slot="{ active, selected }">
<li :class="">
<div class="">
<img :src="country.flag" alt="" class="" />
<span :class="[selected ? 'font-semibold' : 'font-normal', 'ml-3 block truncate']">
{{ country.latin }}
</span>
</div>
<span v-if="selected" :class="">
<CheckIcon class="" aria-hidden="true" />
</span>
</li>
</ListboxOption>
</ListboxOptions>
</transition>
</div>
</Listbox>
</template>
<script>
import { ref } from 'vue'
import { Listbox, ListboxButton, ListboxLabel, ListboxOption, ListboxOptions } from '#headlessui/vue'
import { CheckIcon, SelectorIcon } from '#heroicons/vue/solid'
import axios from 'axios'
export default {
data() {
return {
response: null,
posts: undefined,
};
},
components: {
Listbox,
ListboxButton,
ListboxLabel,
ListboxOption,
ListboxOptions,
CheckIcon,
SelectorIcon,
},
mounted: function() {
axios.get('http://localhost')
.then(response => {
this.posts = response.data;
});
},
setup() {
const selected = ref(posts[30])
return {
selected,
}
},
}
</script>
The offending line is const selected = ref(posts[30]) which I know I need to somehow define posts, but I don't get how?
CAUSE OF YOUR ERROR:
You are trying to access an array element before the array is populated. Thus the undefined error.
EXPLANATION
You are using a mix of composition api and options api. Stick to one.
I am writing this answer assuming you will pick the composition api.
Follow the comments in the below snippet;
<script>
// IMPORT ONMOUNTED HOOK
import { ref, onMounted } from 'vue'
import { Listbox, ListboxButton, ListboxLabel, ListboxOption, ListboxOptions } from '#headlessui/vue'
import { CheckIcon, SelectorIcon } from '#heroicons/vue/solid'
import axios from 'axios'
export default {
// YOU DO NOT NEED TO DEFINE THE DATA PROPERTY WHEN USING COMPOSITION API
/*data() {
return {
response: null,
posts: undefined,
};
},*/
components: {
Listbox,
ListboxButton,
ListboxLabel,
ListboxOption,
ListboxOptions,
CheckIcon,
SelectorIcon,
},
// YOU DO NOT NEED THESE LIFE CYCLE HOOKS; COMPOSITION API PROVIDES ITS OWN LIFECYCLE HOOKS
/*mounted: function() {
axios.get('http://localhost')
.then(response => {
this.posts = response.data;
});
},*/
setup() {
// YOU ARE TRYING TO ACCESS AN ELEMENT BEFORE THE ARRAY IS POPULATED; THUS THE ERROR
//const selected = ref(posts[30])
const posts = ref(undefined);
const selected = ref(undefined);
onMounted(()=>{
// CALL THE AXIOS METHOD FROM WITHIN THE LIFECYCLE HOOK AND HANDLE THE PROMISE LIKE A BOSS
axios.get('http://localhost')
.then((res) => {
selected.value = res[30];
});
});
return {
selected,
}
},
}
</script>
According to your comment; you should first check if the “selected != null” before using ‘selected’ inside the template. You can use a shorthand version like this
<img :src=“selected?.flag” />
I'm using vue + laravel and i try do display the data from api like this:
<div v-for="article in articles" :key="article.id" class="hieght">
<div class="NewArticle">
<h6 class="NewArticleTitle">{{ article.title.ar }}</h6>
</div>
<div>
<p class="NewArticleBody">{{ article.excerpt.ar }}</p>
</div>
</div>
and the script is:
<script>
export default {
data() {
return {
articles: []
}
},
created() {
this.axios
.get('http://localhost:8000/api/articles/')
.then(response => {
this.articles = response.data;
});
}
}
But I want the post to open when I click on the title, I don't know how can i do that using vue
You need to create a view component for your post. and make the h6 title tag a router-link tag that takes you to the post (or article) details page.
Axios setting response data in Vue component variable but variable not displaying data on the browser. We can see data on console but when I display, Browser shows me nothing. Data are in JSON Format.
Snapshot:
Output:
<template>
<div class="card">
<div class="card-header">Subject</div>
<div class="card-body" >
<!-- <ul class="list-group">
<li class="list-group-item" :key = "message.id" v-for = "message in messages"> {{ message.subject}}</li>
</ul> -->
{{messages}}
</div>
</div>
</template>
<script>
export default{
name: 'subject-component',
data () {
return {
messages:{}
}
},
mounted () {
},
created(){
axios.get('http://127.0.0.1:8000/subject/get')
.then(response => {this.messages = response.data})
.catch((error) => console.log(error));
}
}
</script>
By setting up the project again, this issue has been resolved. And again I used the same approach for axios request like.
axios.get('http://127.0.0.1:8000/get/subjects')
.then((response)=>(this.subjects = response.data))
.catch(function(error){console.log(error)});
Thank you all for your effort.