Differences between data in vue - laravel

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();

Related

Axios return img Src with Vue JS

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

Is it OK to use AJAX to POST to a Razor page model from another page? (Example)

I try to learn web development, and tested to see if I could use only the POST-side of a Razor page/model for an AJAX-script to upload a file via another razor page and at the same time not treat the "FileUpload"-page as a page.
I will cut down the code, just to show what I mean:
Index.cshtml
#* return false, to prevent rendering of FileUpload.cshtml *#
<form asp-page="./FileUpload" enctype="multipart/form-data"
onsubmit="Uploader(this);return false;" method="post">
...
<script>
async function Uploader(element) {
var result = ...
try {
const response = await fetch(element.action, {
method: 'POST',
body: formData
}).then(response => response.json())
.then(data => ...
FileUpload.cshtml.cs
// Another code checks the file and adds errors to ModelState
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
...
Example response in Index.cshtml after posting:
{"file":["File type is not allowed or the signature don't match the extenstion"]}
This works, but I wonder if it is acceptable to do this, or if there are any consequences regarding security, performance, if it is a bad/wrong way of doing it, etc?
Thanks for your time and help.
The primary purpose behind having Razor Pages as endpoints is to generate HTML. If you don't have a requirement for HTML, you should really put your upload handler in a controller, especially if the upload handler is intended to be called from multiple locations in your application.
As to the security question, you should take the same precautions with handling file upload regardless how you create the endpoint that accepts them. There is unlikely to be any significant difference in performance between a Razor page handler and a controller action.

SSR and GraphQL: how to avoid the loading state if no javascript is present (SEO purposes)?

I'm trying SSR (server side rendering) for the first time today.
I need to use it only for SEO purposes: so NO-Javascript browsers (readers) along with standard ones.
In my Svelte/Sapper app I'm using GraphQL (Apollo, URQL or SVQL).
QUESTION
Whatever the GraphQL client I choose I can't understand how to manage the loading of the call to the GraphQL endpoint.
I mean that since we are not in an environment where I can use the reactivity to an event to rewrite part of the DOM (I am rendering in the nodejs server) every time a user (or a bot: search engine) browses the site (without javascript) will only see the wait state for the GraphQL call: "Loading todos ...".
Am I brutally wrong?
CODE EXAMPLE
<script>
import { initClient, query } from '#urql/svelte';
initClient({ url: "https://0ufyz.sse.codesandbox.io" });
const todos = query({
query: `
query {
todos {
id
text
complete
}
}
`
});
</script>
{#if $todos.fetching} <!-- This is the only state I see in my server rendered response -->
Loading todos...
{:else}
<ul>
{#each $todos.data.todos as todo}
<li>{todo.text}</li>
{/each}
</ul>
{/if}
Even if I manage to wait for the GraphQL response in the express server and to render the data instead of the loading message, the problem is that the times are much longer (if the GraphQL endpoint is slow) and the user experience is depressing, especially for the standard user with the browser and javascript.
Maybe I am missing something in the reasoning.
But what?
Preloading
How to preload is documented on the official site here https://sapper.svelte.dev/docs#Preloading
So you would do sth like this
<script context="module">
import { initClient, query } from '#urql/svelte';
export async function preload() {
initClient({ url: "https://0ufyz.sse.codesandbox.io" });
const todos = query({
// ...
});
return todos.toPromise().then(todos => ({todos}));
}
</script>
<script>
export let todos; // note this is the same name as above in the returned promise
</script>
{#if ....
Note that this has to be a page component.
DOM rendering
SSR means you write a text string which represents the DOM. You do this once and cannot update that afterwards. What SSR puts out is sent to the client, no possibility to update that. So if you want to wait for your API and then send the DOM, you just have to wait as long as the query takes.

Avoid double ajax call

I'm really new to React so I'm trying to manage it by made some examples. I made this component that made an ajax call to render a simple list.
import React from "react";
import axios from 'axios';
import Page from '../components/Page/Page';
import ListJobs from '../components/ListJobs/ListJobs';
let state ;
class Home extends React.Component{
constructor(props){
super(props);
this.state ={jobs:[]};
}
componentDidMount(){
var _this = this;
this.serverRequest = axios.get("http://codepen.io/jobs.json")
.then(function(result){
_this.setState({
jobs:result.data.jobs
});
});
}
componentWillUnmount() {
}
render(){
return(
<div>
<Page title="Home">
<p>Home</p>
<ul>
{this.state.jobs.map(function(job,index) {
return(
<ListJobs key={index} job={job}/>
);
})}
</ul>
</Page>
</div>
);
}
}
export default Home;
It calls another child component to render the li elements.
Everytime I call this component it starts with this ajax call, so I was wondering if there is a way to save the result of this ajax call and re-use it, instead of launching every time the request. I tried to do like this https://jsfiddle.net/corvallo/mkp4w8vp/
But I receive this error in the developer console:
Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of Home
Thank you in advance for your help
If you want the ajax calls only when the app launches, then you can make ajax calls on the parent component (probably App) and then pass it as a props to the Home component
EDIT
if you want to call the ajax only from the component, I think you can implement a cache or some sort e.g using localstorage
example
componentDidMount(){
let cache = JSON.parse(localStorage.getItem('homeCache') || "{}");
if(cache.hasOwnProperty('cached') && cache.hasOwnProperty('jobs')){
this.setState({jobs:cache.jobs});
}else{
(/*YOUR API HERE*/).then(function(result){
_this.setState({jobs:result.data.jobs});
localStorage.setItem('homeCache', JSON.stringify({cached: true, jobs: result.data.jobs}));
});
}
}
and everytime when the user exits the app, clear the cache (or anytime you want the cache to be cleared)
localStorage.setItem('homeCache', JSON.stringify({}));
I think that's one solution which popped out of my head right now..

AJAX call with nodeJS and express successful, but not displaying data

I have recently migrated from a codeigniter framework, to a nodejs with an express framework. Our codeigniter site had a lot of JS as it was, and we made a lot of AJAX calls because it is a single page app. We are messing around with node and express now, and I cannot get a simple AJAX call to function. It could be a lack of understanding of node, it could be something else. We are using openshift to host. We are using hogan-express as a template.
server.js
var express = require('express');
var fs = require('fs');
var http = require('http');
var path = require('path');
var SampleApp = function() {
var self = this;
self.initializeServer = function() {
self.app = module.exports = express();
self.app.configure(function() {
self.app.set('views', __dirname + '/views');
self.app.set('view engine', 'html');
self.app.engine('html', require('hogan-express'));
//self.app.set('layout', 'layout') # use layout.html as the default layout
self.app.use(express.favicon());
self.app.use(express.logger('dev'));
self.app.use(express.bodyParser());
self.app.use(express.methodOverride());
self.app.use(express.session());
self.app.use(self.app.router);
self.app.use(require('stylus').middleware(__dirname + '/public'));
self.app.use(express.static(path.join(__dirname, 'public')));
});
require('./routes');
}
There is more code in this file, I am only including the relevant code (I think).
Ajax.html
<div id="button">
<button id="testbutton">Push Me!</button>
</div>
<div id="populate">{{title}}</div>
<div id="null">{{>part}}</div>
<script type='text/javascript'>
$(function(){
$('#testbutton').click(function (){
$.ajax({
url:'/test',
type: 'POST',
success: function(result){
alert('success!');
},
error: function(){
alert("well this is embarassing... if the problem persists please let us know at facebook.com/stembuds");
}
});
});
});
</script>
index.js
app = require('../server');
app.get('/', function(req, res){
res.render('ajax');
});
app.post('/test', function(req, res){
console.log('get');
res.locals = {title: 'Horray'};
res.render('ajax', {partials:{part:'part'}});
});
part.html
<p> pass me in!!</p>
So basically what I am trying to do is when the button is clicked I want the ajax call to show a partial view. The way we are going to structure the site is to have one single page, and have the ajax calls render different views based on the buttons that the user clicks. So here is the interesting part: I get the success alert from the ajax call, but the {{title}} and the {{>part}} never show up. However, when I go to the console and click 'network', and then click 'test' (the url to my ajax call), the response shows the divs populated with "Horray" and "pass me in!!". Sorry for the length, and thank you for any information you can provide us.
If you are calling your resources with ajax (as you are doing) then you get the response to your ajax function. After successful call you need to render the view in your client side JS code.
What I mean is that your code works as expected, but your backend cannot update your browsers view. You need to do it client side or load the whole page again from the server.
Your success hander could be something like this:
success: function(result){
renderTheResults(result);
},
You can just send the JSON. You need to send the json via send not render. Because render is supposed to deliver the full HTML page. May be .ejs file.
For example:
res.send({partials:{part:'part'}});
res.send should be used to pass json to your page. And on your page you have to use the JSON to populate the HTML dynamically.

Resources