Hi all i have this issue i had to return of axios, that I am not positioning in the right place i show my basic code:
pictures(city) {
axios
.get(
`https://pixabay.com/api/?key=***********&q=${city}&image_type=photo&pretty=true`
)
.then((resp) => {
if(resp.data.hits.length)
// console.log(resp.data.hits[0].largeImageURL)
return resp.data.hits[0].largeImageURL
else
// console.log('ELSE')
return 'https://cdn2.civitatis.com/reino-unido/londres/guia/aeropuerto-gatwick.jpg'
});
},
And what i want to do, is call this method in my HTML like that
<img :src="pictures(item.city)" />
And i wait the return that would be a link from the api, but i must be wrong somewhere.
Sorry if it's basic, and if i forgot to do something basic.
Thank you very much for the time taken to my question
Related
I have tried to figure out why this happens but I have no idea why. I am going to post the code and then explain what happens. The issue is I do not know WHY this happens and it's annoying me like crazy!
Button:
<a
href="#"
v-for="(userStories, userStoriesIndex) in storiesData"
:key="userStoriesIndex"
#click="openUserStories(userStoriesIndex)"
>
Which loads:
<Stories v-for="(userStories, userStoriesIndex) in storiesData"
:key="userStoriesIndex"
>
<Story v-for="(story, storyIndex) in userStories.stories"
:key="storyIndex"
user-link="#"
:name="userStories.model.name"
:date="story.created_at"
close-button
#closeButtonClick="onCloseButtonClick"
>
<template #avatar>
<img :src="userStories.model.profile_photo_path" />
</template>
<img :src="story.media.preview_url" />
</Story>
</Stories>
And storiesData is loaded from this method:
getStories() {
axios
.get("/stories")
.then((response) => (this.storiesData = response.data));
}
which is loaded during mounted()
its loaded into:
data() {
return {
storiesData: [],
Now, when I click the button, the model loads incomplete, it is not loading the data... but... and this is where I lose it...
If I take the data from the Axios request, convert it to a JS object, and add it to the Vue file, everything works as intended.
I am not sure what's going on. I am completely at a loss why local would work and Axios would not. The data is IDENTICAL including but not limited to looking at Vue DevTools.
This sound to me like a bad async handling, Axios (and any other AJAX library), send the request asynchronously. It look like you thought that the rendering would wait for the ajax request to finish, but it is not. Try convert the axios call into Async/Await:
async function getStories() {
const data = await axios.get("/stories");
return data;
}
or for short:
async function getStories() {
return await axios.get("/stories");
}
then in your hydration function:
this.storiesData = await getStories();
I have a js file located in assets folder (not View). can i pass a varible from a controller?
In view file:
The Js is called like this
<canvas id="chart1" class="chart-canvas"></canvas>
</div>
It is not possible (in my point of view) to put a variable to external JS file. You can use data-... attributes and get values from html elements.
For example you can pass your PHP variable as a json encoded string variable in your controller.
$data['chart_info'] = json_encode($chart_info);
return view('your_view', $data);
Then put it in data-info like this.
<canvas id="chart1" class="chart-canvas" data-info="{{ $chart_info }}"></canvas>
And finally in JS, you can get the variable and decode (parse) it as following.
let canvas = document.getElementById('chart1');
let info = JSON.parse(canvas.dataset.id);
console.log(info);
You can put that part of the Javascript in the view and send the variable to the same view. For example, add a section in view:
#section('footer')
<script type="text/javascript">
</script>
#endsection
Do not forget that you should add #yield('footer') to the end of your layout view.
I don't like to mix javascript and PHP/Blade, it might be hard to read the code in the future... You could use a different approach, loading the chart with a async ajax request.
You will have to create a end-point that returns the data you need for your chart:
Your router:
Route::get('/chart/get-data', [ ControllerName::class, 'getChartData' ]);
Your controller method:
public function getChartData() {
$chartData = [];
// Your logic goes here
return $chardData;
}
In your javascript (using jquery) file there will be something like that:
function loadChartData() {
$.ajax({
'url': '/chart/get-data',
'method': 'GET'
})
.done((data) => {
// Load your chart here!!!
})
.fail(() => {
console.log("Could not load chart data");
});
}
Hope I helped ;)
I'm a frustrated Vue.js noobie coming from jQuery.
I'm trying to do something very basic for a simple project: Delete an article but only after ajax response. While waiting, for the response there's a spinner. (I don't want components or vue files. It's a simple, single file app)
I've been hacking away at it for a few days now and I can't grasp some basic concepts it seems. (Or I want it to behave like jquery)
Fiddle
window.app = new Vue({
el: '#app',
data: {
name: '',
posts: [],
loadingItems: [],
},
created() {
this.fetchData();
},
methods:{
fetchData() {
axios.get('https://jsonplaceholder.typicode.com/posts').then(response => {
this.posts = response.data.slice(0,20);
});
},
removeItem(item) {
var index = this.posts.indexOf(item);
//var loadingIndex = this.loadingItems.push(item) - 1;
//console.log(loadingIndex);
item.isLoading = true;
//Update vue array on the fly hack - https://vuejs.org/2016/02/06/common-gotchas/
this.posts.splice(index, 1,item);
axios.post('//jsfiddle.net/echo/json/', "json='{status:success}'&delay=2")
.then(response => {
this.posts.splice(index, 1);
//this.loadingItems.splice(loadingIndex, 1);
//this.loadingItems.pop(item);
//item.isLoading = false;
//this.posts.splice(index, 1,item);
});
}
},
computed: {
showAlert() {
return this.name.length > 4 ? true : false
}
}
})
<div id="app">
<div v-for="(post,index) in posts" :key="post.id">
<b-card class="mb-2">
<b-card-title>{{post.title}}</b-card-title>
<b-card-text>{{post.body}}</b-card-text>
<a href="#" #click.prevent="removeItem(post)" class="card-link">
Remove
<span v-show="post.isLoading" class="spinner"></span>
</a>
</b-card>
</div>
</div>
Works fine for deleting them 1 by 1 one but not when you click on multiple at the same time, since the index is different by the time the request comes back and it splices the wrong item.
What I've tried so far:
First, it took me a day to figure out that item.isLoading = true; won't work if it wasn't present when the data was first observed (or fetched). However, I don't want to add the property to the database just for a loading animation. So the workaround was to do this.posts.splice(index, 1,item); to "force" Vue to notice my change. Already feels hacky.
Also tried using an array LoadingItems and pushing them while waiting. Didn't work due to the same problem: don't know which one to remove based on index alone.
Studying the TODO app didn't help since it's not quite addressing handling async ajax responses or adding properties at runtime.
Is the best way to do it by using post.id and then trying to pass it and find it back in the array? Really confused and thinking jQuery would have been easier.
Any help will be appreciated. Thanks!
Works fine for deleting them 1 by 1 one but not when you click on multiple at the same time, since the index is different by the time the request comes back and it splices the wrong item.
Don't save the index in a variable. Calculate it every time you need it:
removeItem(item) {
item.isLoading = true;
this.posts.splice(this.posts.indexOf(item), 1, item);
axios.post('/echo/json/', "json='{status:success}'&delay=2")
.then(response => {
this.posts.splice(this.posts.indexOf(item), 1);
});
}
So I have this JS code:
myClass = new Class({
initialize: function() {
this.btnSubmit = document.id('btnSubmit');
this.sendData = new Request({
"url":"/",
"method":"post",
"data": {"option":"com_my4quiz", "controller":"conduit", "task":"save", "hrdata":"foo"},
"onSuccess": this.handleResult.bind(this)
});
this.btnSubmitObserver = function() { this.sendData.send(); }.bind(this);
this.btnSubmit.addEvent("click", this.btnSubmitObserver);
},
handleResult: function(stuff) {
//do stuff
}
});
If I'm posting this to my Joomla 3.2.0 component it returns the home page. As soon as I switch to get, it sends the data to the correct place and I get what I expect.
I think its due to your controller page loads the entire view.
This may happen due to inside your controller save(). function not rendering any specific view .
So the solution is after the Ajax result just render the proper layout or just put an exit();
At the end of your save()
exit();
or
$view->setLayout($layoutName);
$view->display();
Hope its helps..
Sorry if can sound strange, but in the routes, on the post of my view I need to do two operations:
Route::post('booking', 'HomeController#booking');
Route::post('booking', function()
{
return Queue::marshal();
});
But of course doing this I get an error: Invalid data.
Yet for the post of the view 'booking' I need to call the method of the controller, and at the same time return Queue::marshal()
There is perhaps I can do this?
Thank you very much!
EDIT:
Here is the HomeController#booking method:
http://paste.laravel.com/19ej
If you define two routes with the same verb and url, the second one is never going to be fired.
Route::post('booking', 'HomeController#booking'); // Laravel will find this route first
Route::post('booking', function() // so this function will never be executed
{
return Queue::marshal();
});
I see that your HomeController#booking() is handling a form. Why can you just use another route for this?
Route::post('booking/create', 'HomeController#booking');
And then change your form action method to point to this route:
// this will render <form method="POST" action="http://yourdomain.com/booking/create"
{{ Form::open(array('action' => 'HomeController#booking')) }}
This way you don't have one route overlapping the other.
Some advice unrelated to the question. Taking a look at your controller, I have noticed that you do this when checking for errors:
if ( ! $errorCondition) {
// do stuff
} else {
// show errors
}
Your code will be a lot easier to read if you write it like this:
if ($errorCondition) {
// return error
}
// do stuff