I have an API endpoint for https on localhost that's serving raw json data like so:
[{"day":"Monday","hours":43,"date":"2019-12-23T14:38:08.2112312-05:00"},{"day":"Tuesday","hours":36,"date":"2019-12-24T14:38:08.2130238-05:00"},{"day":"Wednesday","hours":39,"date":"2019-12-25T14:38:08.2130318-05:00"},{"day":"Thursday","hours":34,"date":"2019-12-26T14:38:08.2130329-05:00"},{"day":"Friday","hours":42,"date":"2019-12-27T14:38:08.2130338-05:00"}]
What I don't understand is why VUE.js is failing with a "TypeError: "NetworkError when attempting to fetch resource." JSON is being surved for localhost use, and cors has been enabled. Any get request from postman, browser, curl, etc works just fine. It's only failing when VUE.js makes the fetch() call.
The VUE component:
<template>
<div class="container">
<LineChart v-if="loaded" :chartdata="chartdata" :options="options" />
</div>
</template>
<script>
import LineChart from './LineChart.vue';
export default {
name: 'LineChartContainer',
components: { LineChart },
data: () => ({
loaded: false,
chartdata: null,
}),
async mounted() {
this.loaded = false;
try {
const { daysWorked } = await fetch(
'https://localhost:5001/api/timeworked',
);
console.log('days worked data:', daysWorked);
this.chartdata = daysWorked;
this.loaded = true;
} catch (e) {
console.error("Couldn't access data:", e);
}
},
};
</script>
Any thoughts, advice, or tips appreciated!
It's not a problem with Vue. It's a problem with the way you fetch.
Take a look at https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API and https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
try
...
const { daysWorked } = await fetch('https://localhost:5001/api/timeworked')
.then(r=>r.json());
...
this should help.
Related
this.$axios is undefined. As I said in the title I set nuxt.config.js. This is what the error looks like.
This is the HomeView.vue page code where the error is occurring (I removed some methods as they aren't relevant) BTW, notice the line console.log(this.$axios); because this is what printed undefined in the web console:
<template>
<div>
<button
color="primary"
class="btn btn-primary btn-lg btn-block"
large
:disabled="buttonDisabled"
#click="performAction()"
>
<span v-if="isMetaMaskInstalled()">Login with Metamask</span>
<span v-if="!isMetaMaskInstalled()">{{ buttonInstallText }}</span>
</button>
</div>
<span></span>
<button
type="button"
class="btn btn-primary btn-lg btn-block"
#click="register()"
>
Block level button
</button>
</template>
<script>
import Web3 from "web3";
import "bootstrap/dist/css/bootstrap.css";
import "bootstrap-vue/dist/bootstrap-vue.css";
export default {
data() {
return {
buttonDisabled: false,
buttonInstallText: "Click here to install Metamask",
};
},
methods: {
basicLog() {
console.log("it worked");
},
testAxiosCall() {
console.log("test call worked");
},
async register() {
console.log(this.$axios);
const result = await this.$axios.post("/register", {
wallet: "0x00fffff",
});
return result;
},
},
};
</script>
I already installed axios with yarn add #nuxtjs/axios and set up my nuxt config file:
export default {
modules: ["#nuxtjs/axios"],
axios: {
baseURL: "http://localhost:30005",
},
};
Btw, the function localhost:30005/register works perfectly in Postman when I add the parameter wallet: 0x00fffff.
Also here is the code for the register api call. It's in backend/index.js
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const sqlite3 = require("sqlite3");
const path = require("path");
const app = express();
let port = "30005";
let db = new sqlite3.Database(path.resolve(__dirname, "bonus_content.db"));
app.use(bodyParser.json());
app.use(
bodyParser.urlencoded({
extended: true,
})
);
app.use(cors());
const registerUser = (request, response) => {
const { wallet } = request.body;
console.log(wallet);
db.run(
"INSERT INTO bonus_content (wallet) VALUES ($1)",
[wallet],
(error, results) => {
if (error) {
response.status(500).json({ status: "fail", message: error });
}
response
.status(201)
.json({ status: "success", message: "Wallet added." });
}
);
};
app.post("/register", registerUser);
// allow javascript on a different domain (or port) to call this server's routes
// e.g. front-end running on localhost:8080 can call the server on localhost:41205
app.listen(port);
console.log("App is running on port " + port);
So the problem is centered around this.$axios being undefined. What am I doing wrong?
Btw, It's worth noting that I am going off of this tutorial here: https://duartefdias.medium.com/authenticating-users-to-your-web-app-using-metamask-and-nodejs-e920e45e358
Thank you for mentioning my article, glad you found it useful.
First, you need to make sure you have axios installed as mentioned here:
https://axios.nuxtjs.org/setup
My nuxt.config.js axios setup looks like this:
export default {
axios: {
browserBaseURL: process.env.API_URL
}
}
The process.env.API_URL is an environment variable I created, but you can simply hardcode a string such as "http://localhost:3000"
Then I just call this.$axios from anywhere in the code. Example of a basic .vue page:
<template>
<button #click="getData()">
My Button
</button>
</template>
<script>
export default {
components: {},
data () {
return {
items: []
}
},
methods: {
getData() {
this.$axios.get('/items')
.then(response => {
this.items = response.data
})
.catch(error => {
console.log(error)
})
}
}
}
</script>
If I were you I would start by building a dummy backend endpoint which simply returns a string and getting that to work with Vue prior to moving into building the blockchain wallet register/login endpoints.
Vuex is not detected after refresh, but all data is output to the console. Also after refresh, some components behave incorrectly. For example, I use vee-validate and all the rules and fields I get from the back, after refresh the validation rules disappear, but the fields are displayed
Vuex works on all pages but after refresh only on the home page
stroe/index.js
export const state = () => ({});
const map = {
ru: "ru",
uk: "uk-ua"
};
export const getters = {
lang(state) {
return map[state.i18n.locale];
}
};
export const mutations = {};
export const actions = {
async nuxtServerInit({ state, dispatch }) {
try {
await dispatch('category/getCategories', {
});
} catch (err) {
console.log('nuxt server init error', err);
}
}
};
home page (everything works)
<template>
<div>
<main class="home-page">
<banner />
<section class="home_page">
<div class="container">
<phone-pay />
<card-pay />
<categories :categories="categories" :services="services" />
<main-banner />
</div>
</section>
</main>
</div>
</template>
<script>
import Banner from "#/components/Index/Banner";
import PhonePay from "#/components/Index/PhonePay";
import CardPay from "#/components/Index/CardPay";
import Categories from "#/components/Index/Categories";
import MainBanner from "#/components/Index/MainBanner";
export default {
components: {
Banner,
PhonePay,
CardPay,
Categories,
MainBanner
},
async asyncData({ store, app: { $api }, error, req }) {
try {
const {
data: { data: categories, included: services }
} = await $api.CategoryProvider.getPopularCategories({
params: {
include: "services"
}
});
return {
lang: store.getters.lang,
categories,
services
};
} catch (e) {
console.log("error index", e);
error({ statusCode: 404, message: "Page not found" });
}
}
};
</script>
category (does not work)
<template>
<services-viewer :initial-services="initialServices" :category="category" :init-meta="initMeta" />
</template>
<script>
import ServicesViewer from "#/components/UI/ServicesViewer";
export default {
components: {
ServicesViewer
},
async asyncData({ store, route, error, app: { $api } }) {
try {
const {
data: { data: initialServices, meta: initMeta }
} = await $api.ServiceProvider.getServices({
params: {
"filter[category_slug]": route.params.id,
include: "category"
// "page[size]": serviceConfig.SERVICE_PAGINATION_PAGE_SIZE
}
});
await store.dispatch("category/getCategories", {
params: {}
});
const category = store.state.category.categories.find(
({ attributes: { slug } }) => slug === route.params.id
);
return {
initialServices,
category,
initMeta
};
} catch (e) {
const statusCode = e && e.statusCode ? e.statusCode : 404;
error({ statusCode });
}
}
};
</script>
install the below package:
npm install --save vuex-persistedstate
then change your store like below, then your data will be available after refresh the page.
// store/index.js
import Vuex from 'vuex';
import createPersistedState from 'vuex-persistedstate'
const createStore = () =>
new Vuex.Store({
plugins: [createPersistedState()],
state: {
},
mutations: {
},
getters:{
}
});
export default createStore;
for more details you can read from here.
I solved it. It was my mistake. I have a parallax plugin that works on the home page, but if you go to another page and refresh, the plugin starts and cannot find the item and breaks the page.
follow this link for your question
The nuxtServerInit Action
If the action nuxtServerInit is defined in the store and the mode is universal, Nuxt.js will call it with the context (only from the server-side). It's useful when we have some data on the server we want to give directly to the client-side.
For example, let's say we have sessions on the server-side and we can access the connected user through req.session.user. To give the authenticated user to our store, we update our store/index.js to the following:
actions: {
nuxtServerInit ({ commit }, { req }) {
if (req.session.user) {
commit('user', req.session.user)
}
}
}
I'm using Nuxt.js in static site mode, and trying to get an image from an API using a string passed in a prop, however, in the template I am getting [object Promise]. I would've thought that return before the get request would resolve the promise, but I think my grasp of promises and Nuxt.js a little off. Any help would be greatly appreciated.
<template>
<div>
{{ getThumbnailSrc() }}
</div>
</template>
<script>
import axios from 'axios'
export default {
props: {
link: {
type: String,
required: true
}
},
data() {
return {
imageUrl: null
}
},
methods: {
getVimeoId(link) {
return link.split('/').pop()
},
getThumbnailSrc() {
return axios
.get(
`https://vimeo.com/api/v2/video/${this.getVimeoId(
this.link
)}.json`
)
.then(response => {
const vimeoThumbnailUrl = response.data[0].thumbnail_large
console.log(vimeoThumbnailUrl)
return {
vimeoThumbnailUrl
}
})
.catch(error => {
console.log(error)
})
}
}
}
</script>
It sure won't! XHR requests are asynchronous and therefore the template has no idea that it needs to wait.
Solve it by using an additional data property on the component, and using that instead:
data() {
return {
imageUrl: null,
thumbnailSrc: null
}
},
And in your callback:
.then(response => {
const vimeoThumbnailUrl = response.data[0].thumbnail_large
console.log(vimeoThumbnailUrl)
this.thumbnailSrc = vimeoThumbnailUrl
})
Now you can use {{thumbnailSrc}} and it will load appropriately.
I'm trying to build pagination using vuetify pagination component and nuxt.js but it's not work with server side rendering.
I added nuxt.js link using code from https://github.com/vuetifyjs/vuetify/issues/4855. It's work on client side but on server side it return error "render function or template not defined in component: anonymous"
Anyone have idea how to build correct SSR pagination or how to fix my solution?
Don't know if this thread is still valid but this is my solution for vuetify pagination with nuxt.
<script>
import PostList from "#/components/site/PostList";
import axios from "axios";
export default {
components: {
PostList
},
watchQuery: ["page"],
async asyncData({ $axios, query }) {
try {
const page = query.page || 1;
let { data } = await $axios.get("/articles/?page=" + page);
return {
posts: data.data,
page: data.current_page,
totalPages: data.last_page
};
} catch (e) {
// console.log(e); display errors
}
},
methods: {
next() {
this.$router.push({ query: { page: this.page } });
}
}
};
</script>
<template>
<v-pagination v-model="page" :length="totalPages" #input="next"></v-pagination>
</template>
I have this strange case when trying to retrieve data from mongoDB using axios not showing on grid. It should be already successful given the data can already loaded into the view (already tested it), but it's nowhere inside beforeMount, mounted, or ready hook.
I already tried with
this.gridOptions.onGridReady = () => {
this.gridOptions.api.setRowData(this.ticketData)
}
but only yields partial success (unreliable),
here's a code snippet to show what I mean,
<template>
<div class="ticketing">
<ag-grid-vue style="width: 100%; height: 350px;"
class="ag-fresh"
:gridOptions="gridOptions"
>
</ag-grid-vue>
{{testData}} <!--testData can be loaded-->
<input type="button" #click.prevent="showData" value="test"> </div>
</template>
<script>
//import stuff
//header and url stuff
export default {
//component stuff
data () {
return {
gridOptions: null,
ticketData: [],
testData: [] // only for testing purpose
}
},
methods: {
showData () {
console.log('data shown')
this.testData = this.ticketData // this is working
}
},
beforeMount () {
var vm = this
axios.get(ticketingAPIURL, {'headers': {'Authorization': authHeader}})
.then(function (response) {
vm.ticketData = response.data
}) // this is working
.catch(function (error) {
console.log(error)
})
this.gridOptions = {}
this.gridOptions.rowData = this.ticketData // this is not working
this.gridOptions.columnDefs = DummyData.columnDefs
}
// mount, ready also not working
}
</script>
To be more specific, I still can't determine what really triggers onGridReady of ag-grid in conjunction with Vue component lifecycle, or in other words, how can I replace button to show testData above with reliable onGridReady/Vue component lifecycle event?
You define vm.ticketData and after you call it like this.ticketData
You can change it by: this.rowData = vm.ticketData
You are setting this.gridOptions.rowData outside of the axios callback, so this.ticketData is still empty.
Set it inside the callback:
mounted() {
var vm = this
axios.get(ticketingAPIURL, {'headers': {'Authorization': authHeader}})
.then(function (response) {
vm.ticketData = response.data
vm.gridOptions = {}
vm.gridOptions.rowData = vm.ticketData
vm.gridOptions.columnDefs = DummyData.columnDefs
})
.catch(function (error) {
console.log(error)
})
}
it is due to overlapped intialization between axios, ag-grid, and vue.
after much tinkering, I am able to solve it with using Vue's watch function:
watch: {
isAxiosReady(val) {
if (val) {
this.mountGrid() // initiate gridOptions.api functions
}
}
}