Fetch request renders undefined in html - javascript

I have this Vanilla JS code inside my html block
<label for="weather"></label><input value="copenhagen" type="text" id="weather" placeholder="Enter your name to get weather">
<button onClick="getValue()">Submit</button>
<div id="weather-box"></div>
<script>
function getValue() {
const form = document.getElementById('weather').value;
const weatherBox = document.getElementById('weather-box')
console.log(form);
fetch(`http://localhost:3000/weather?city=${form}`)
.then(res => res.json())
.then(data => {
console.log(data)
weatherBox.innerHTML = `
weather is ${data.summary}
temperature is ${data.temperature}
`
})
}
</script>
the problem is that, even though the data is logged out correctly, it gives undefined inside the rendered html code.
Why is this happening, and how cani fix it?
EDIT:
I have added the output from the console.log(data)

Your console.log(data) indicates that your response (data) has a property also called data, which holds the information you want.
You could access it via data.data.summary (or better yet, rename your response to something like response).
An alternative would be to destructure it:
.then(({data}) => {
weatherBox.innerHTML = `
weather is ${data.summary}
temperature is ${data.temperature}
`
})

Related

Script returns an empty list data with 200 response, fetching data from django backend

I am working on an autocomplete app that I want users be able to make address search through the backend of Django but somehow the Api doesn't fetch data through the script, why is the payload not showing any data in the log console but rather an empty list?, I have tried calling the data from the browser as in example http://127.0.0.1:8000/search/?address=val , which fetches the json data response with a payload of data of addresses that match my search, but when i pass the url in my javescript it returns an empty data list with a 200 response. My experience in Js is mediocre, since I'm a novice.
<script>
new Autocomplete('#autocomplete',{
search : input => {
console.log(input)
const url = "/search/?address=${input}"
return new Promise(resolve => {
fetch(url)
.then( (response) => response.json())
.then( data => {
console.log(data)
resolve(data.data)
})
})
},
onSubmit : result => {
console.log(result)
window.open('/search/?address=${result}')
}
})
</script>
here is my search box Html
<h4>Seacrh for places</h4>
<div id="autocomplete" class="autocomplete">
<input class="autocomplete-input"/>
<ul class="autocomplete-result-list"></ul>
</div>
my view for search
def search_address(request):
address = request.GET.get('address')
playload = []
if address:
fake_address_objs = Address.objects.filter(address__icontains=address)
for fake_address_obj in fake_address_objs:
playload.append(fake_address_obj.address)
return JsonResponse({'status':200 , 'data': playload })
Returned empty data in the console log
Returned data in browser using http://127.0.0.1:8000/search/?address=v

How to focus on a specific input text after the component is rendered?

I'm struggling to make this work properly every time I rendered the component by pushing it using the router object something like this this.$router.push('/Home/mypath'); which will focus only on the first input text element with index = 0 after the component is rendered even if I passed another value for index. Basically, I passed an index value to the ref of the input text element which is inside the v-for loop of a component and so at mounted(), I have something like this
mounted() {
this.$nextTick(() =>
{
this.$refs.newInp[index].focus();
});
}
but it keeps focusing on the first input element even though I passed a value of 1 or 2. When I looked at the console log, it shows this error on the console.
TypeError: Cannot read property '0' of undefined
pointing on this line this.$refs.newInp[index].focus();
Sample Code to fetch the data in the v-for
async GetContentDetails() {
let testRes =
await axios.get('myUrl/api', {
params: {
ContentId: this.$cookie.get('OpV-ContId')
}
}).then(res => this.contentItems = res.data)
.then()
.catch(error => console.log(error));
this.testData = testRes;
}
Template:
<div v-for="(contItem, index) in contentItems" :key="contItem.commentId">
<textarea class="reply-commented" ref="newInp"></textarea>
</div>
How to fix this type of issues? What is the solution for this?
Thanks.
From what I understood, you want to focus a textarea after fetching some data, that said trying to focus inside the mounted method wont work because you can't tell if the data has been fetch and the textareas already exist in the DOM.
So the best way to do this is to focus after being sure the data has been fetched, inside the then callback.
new Vue({
el: '#app',
data: {
posts: [],
index: 3 // Change this to focus whatever textarea you want
},
mounted () {
this.fetchItems();
},
methods: {
fetchItems () {
const url = 'https://jsonplaceholder.typicode.com/posts'
axios.get(url).then(response => {
this.posts = response.data
this.$nextTick(_ => {
this.$refs.newInp[this.index].focus()
})
})
}
}
});
<div id="app">
<div v-for="(post, index) in posts" :key="post.id">
<textarea class="reply-commented" ref="newInp" v-text="post.body"></textarea>
</div>
</div>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
For few days of research and thorough testing and observation on DOM behavior on how vue.js renders component and of course basing on the suggestions from other folks on this thread. I realized you can't really focus in the created/mounted properties on a specific index of an element within the for loop particulary in this case the input text element if the data being fetch to bind on the component is coming from the server due to its asynchronous behavior and you have to wait until the component is completely rendered. So I found a solution at least on my case to use a dynamic watcher either in the created or mounted properties and set a dummy or duplicate data properties for the default change of the data properties for the purpose of only to activate the watcher to focus on the specific element after the component has been rendered. This how it looks like. Hope this help to folks that encountering the same scenario as me.
created() {
this.GetContentDetails();
this.$watch('commentItems2', function () {
this.$nextTick(() => {
this.$refs.newRep[mapCredential.state.index2].focus();
});
});
},
methods: {
async GetComment2() {
let testRes =
await axios.get('myUrl/api/GetContent/GetComments')
.then(this.GetReply2())
.catch(error => console.log(error));
this.commentItems = testRes.data;
this.commentItems2 = testRes.data;
},
}

VueJS / v-html shows empty page (Bokeh-html)

I am new to VueJS and I am trying to display a local html-file inside of the Vue Application.
I fetch the html file with axios like following:
<template>
<div>
<h1>bla</h1>
<div v-html="input"></div>
</div>
</template>
<script>
import axios from 'axios'
export default {
data() {
return {
input: null,
}
},
created() {
this.loadFile()
},
methods: {
loadFile() {
axios({
method: "get",
url: "../../test.html"
})
.then(result => {
this.input = result.data;
console.log("Data: " + result.data)
})
.catch(error => {
console.error("error getting file: " + error);
});
},
}
}
</script>
We generate the html-Files with Bokeh (interactive Charts). If I open the html Files in the Browser they are shown correctly. These files contain
<script type="text/javascript">
and <script type="application/json">.
I tried this with a simple "Hello World"-html Example and this works fine and gets displayed in Vue. But when I read the actual file, I just get an empty page. The console.log(result.data) shows me the correct and complete html Code but I don't get any errors, so I can't figure out the problem.
Does anyone know, what I have to adjust to make this work?
Thanks !
The reason is the statement this.input = result.data tries to parse result.data as json but it is not.
Send the json from the server and use it in your code properly.
Are you doing this inside of a .vue file or is all of this in a .html file. If in html you need to remember to set the el property on your Vue model to ensure it knows where to render. If this is a .vue there has to be a defined template for the same reason.
Here is a fiddle with an example. Yes the site has issues rendering with correct layout, but it renders. This is an example for <script> tags in your html file or just a raw .js file. Looks like you were making a Vue component (.vue) but the premise is still the same as long as you define the template where the Vue code is to be rendered.
Edit:
What does your vue file look like? This is what I'm expecting.
<template id="foo">
<div v-html="input"></div>
</template>
<script>
export default {
template:'#foo',
data: {
input: null
},
created() {
this.loadFile();
},
methods: {
loadFile() {
let _this = this;
axios({
method: "get",
url: 'https://jsfiddle.net/',
})
.then(result => {
console.log(result);
_this.input = result.data;
console.log("Data: " + result.data)
})
.catch(error => {
console.error("error getting file: " + error);
});
},
}
};
</script>

How do I get my api call to call a different file?

I am using the api http://aws.random.cat/meow and it gives me a result of
{"file": "https://purr.objects-us-east-1.dream.io/i/rEJ7q.jpg"}
The file changes every time I refresh the api call on the browser which gives me a different cat pic. For example, if I refresh it would give me a different .jpg like
{"file": "https://purr.objects-us-east-1.dream.io/i/ferbus.jpg"}
I call the api in my React app, and I want to randomize the cat pic after an onClick of a button. Unfortunately, I get the same picture back when I do my api call. I put the file in an img src, but it doesn't change when I do another api call.
componentDidMount() {
this.getCats();
}
getCats = () => {
axios.get(`http://aws.random.cat/meow`)
.then(res => {
let cats = res.data.file;
console.log(cats)
this.setState({
cats
})
})
.catch(err => console.log(err))
}
render() {
return (
<div>
<img
src={this.state.cats}
alt='cat'
/>
<button onClick={this.getCats}>
Click me
</button>
</div>
);
}
I expect to get a different file every time, but instead I get the same .jpg when I do an onClick.

Axios PUT Request in React, Redux Not Working

So I want to make a PUT request to the server, but it doesn't want to work. I know that when making a PUT request you need an identifier(e.g id) for the resource and the payload to update with. So that is my problem.
In my form I have these props:
<div>
<DoorSettingsForm
onSubmit={this.submit.bind(this)}
item={this.props.location.state.item}
id={this.props.location.state.item._id}
/>
</div>
item - All the input fields, radiobuttons etc.
id - The identifier
onSubmit - the function that handles the submitting of all of the new data, here it is:
submit(values, id) {
this.props.updateSettings(values, id)
}
And inside of my really simple action I have this:
export function updateSettings(id, item) {
return dispatch => {
console.log('ID: ', id)
return axios
.put(`${settings.hostname}/locks/${id}`, item)
.then(res => console.log(res))
.catch(err => console.log(err))
}
}
One thing that I really don't understand is when I change the places of id and item on the first line the output of my console.log changes. When having id as the first parameter I get everything I've typed in my inputs (the changes) and when having item as the first parameter I'm getting this:
ID: function (action) {
if (action.payload) {
if (!(0, _isPromise2.default)(action.payload) && !(0, _isPromise2.default)(action.payload.promise)) {
return next(action);
}
Any help with my problem is really appriciated! Thanks for reading.
I forgot to call handleSubmit with my id:
form onSubmit={() => handleSubmit(id, item)}

Categories

Resources