VueJS - Can't access assigned this.property declared within mounted() in mounted() - laravel

I'm doing a project where I'm fetching an api data from my backend laravel with axios get and using its property to concatenate a channel within the mounted section of my component.
I'm fetching api/user through axios get which contains
{
"id": 1,
"name": "admin",
"email": "admin#company.com",
"email_verified_at": null,
"created_at": "2019-08-17 10:06:14",
"updated_at": "2019-11-27 02:03:30",
"phone_number": "+12345678911",
"phone_number_verified": 0,
"company_id": 1,
"verification_code": "",
"signature": "",
"signature_image": null,
}
Here's how I'm getting the user data from my laravel backend through axios:
mounted() {
this.$http
.get('/api/user')
.then(response => ( this.user = response.data ))
.catch(error => console.log(error))
},
Which is then declared as an empty array in my data() section as such:
data() {
return {
user: [],
};
},
I can access the properties for example, id, in my template through {{ user.id }} and when I try to access it within the mounted() section, it gives me an object but when I try console.log(this.user.id) within the mounted, it throws undefined instead. The reason I need to access this.user.id within the mounted section is because I'm using it to concatenate the channel I'm using through Laravel Echo given as such:
mounted() {
this.$http
.get('/api/user')
.then(response => ( this.user = response.data ))
.catch(error => console.log(error))
this.$echo
.channel(`new-notification.${this.user.id}`)
.listen('NewNotification', (data) => {
// eslint-disable-next-line no-alert
this.notifications.unshift(data);
});
},
I'm fairly new to Vue and I don't know what I'm doing wrong in this. It would be of great help if someone can point out what I'm doing wrong or if there's a better method of doing it.

The issue is the console will run before the response of api call. You can make the call async and try.
mounted() {
this.fetchApi();
},
methods:{
fetchApi: async function(){
let response = await this.$http
.get('/api/user');
this.user = response.data;
this.$echo
.channel(`new-notification.${response.data.id}`)
.listen('NewNotification', (data) => {
// eslint-disable-next-line no-alert
this.notifications.unshift(data);
});
}
}

Related

How to get cypress to dynamically update a fixture to a graphql call

I need to mutate a graphql call in Cypress to where I can change certain key:value pairs within a fixture depending on the test.
I know I can call a graphql fixture with a format similar to this:
cy.intercept('POST', '/graphql', (req) => {
if (req.body.operationName === 'operationName') {
req.reply({ fixture: 'mockData.json'});
}
}
but pretend mockData has the following shape:
data: {
"user": {
"user": {
"userId": 123,
"inviteId": "123",
"status": "NEEDS_MORE",
"firstName": "Testy",
"lastName": "McTesterson",
"email": "test#testqa.com",
"phone": "3129876767",
"user": null,
"invite": {
"id": "12345",
"sentAt": null,
"sendDate": null,
"status": "NOT_SENT",
"__typename": "Invite"
},
},
}
}
How would I intercept the graphql call with all the info in mockData.json but change "status": "NEEDS_MORE" to "status": "CLAIMED" in my test without changing the rest of the fixture? The idea would be that in each it block of a spec, I re-use the same fixture but change the status, and have different assertions.
My attempts so far either only send the status without the rest of the data or only send the fixture without mutating anything. There is cypress documentation on how to do this in rest, but not in graphql. We're using typescript.
You can read the fixture first, make the modification before the reply
cy.fixture('mockData.json').then(data => {
data.user.user.status = 'CLAIMED'
cy.intercept('POST', '/graphql', (req) => {
// according to one reference, this is needed
const g = JSON.parse(req.body)
if (g.operationName === 'operationName') {
req.reply({
body: {data} // same reference shows reply stubbing in this format
})
}
}
})
Ref: Smart GraphQL Stubbing in Cypress
Consider using a dynamic import to read the fixture.
cy.intercept('POST', '**/graphql', async (req) => {
const data = await import('../fixtures/mockData.json')
data.user.user.status = 'CLAIMED'
if (req.body.operationName === 'operationName') {
req.reply({
body: {data}
})
}
})
Since you have typescript set up, add resolveJsonModule to tsconfig.json
{
"compilerOptions": {
"target": "es5",
"lib": ["es5", "dom"],
"types": ["cypress", "node"],
"resolveJsonModule": true
},
"include": ["**/*.ts"]
}
#Paolo's answer is good. An alternative to avoid using cy.fixture().then()
const mockedData = require('path/to/fixture/mockData.json')
// later in your test block
mockedData.user.user.status = 'CLAIMED'
cy.intercept('POST', '/graphql', (req) => {
if (req.body.operationName === 'operationName') {
req.reply((res) => (res.body.data = mockedData))
}
})

Data not showing on vue.js component using laravel api

I'm trying to get the data from database using an API, but there are no output on my vue controller.
Am I doing this right?
I think I'm assigning the scheduleList the wrong way.
I'm very new to vue.js and API, I want to know what I'm doing wrong here.
Controller
public function schedules(){
return Schedule::all();
}
api.php
Route::get('schedules', 'CalendarController#schedules');
Vue Component
<script>
import axios from 'axios'
export default {
data() {
return {
schedules: [],
scheduleList: [
{
id: schedules.id,
title: schedules.title,
category: schedules.category,
start: schedules.start,
end: schedules.end
},
],
};
},
methods: {
loadSchedules() {
axios.get('/api/schedules')
.then((response) => {
this.schedules = response.data;
})
}
},
mounted() {
this.loadSchedules();
}
};
</script>
<style>
</style>
The issue is in your data option because you're referencing schedules which is undefined, I'm sure that you're meaning this.schedules but doing that will not solve the issue because at first rendering this.schedules is an empty array, another problem that you're referencing at as object in scheduleList items using schedules.id, if the schedules property is an array i recommend the following solution :
<script>
import axios from 'axios'
export default {
data() {
return {
schedules: [],
scheduleList: [],
};
},
methods: {
loadSchedules() {
axios.get('/api/schedules')
.then((response) => {
this.schedules = response.data;
let schedule=this.schedules[0]
this.scheduleList.push({
id: schedule.id,
title: schedule.title,
category: schedule.category,
start: schedule.start,
end: schedule.end
})
})
}
},
mounted() {
this.loadSchedules();
}
};
</script>
always catch errors if you do promises.
loadSchedules() {
axios.get('/api/schedules')
.then((response) => {
this.schedules = response.data;
})
.catch(error => {
console.log(error)
})
inside your error you can better see whats going wrong.
other way is the "network" tab in your browser where you can trace your api request

Split data JSON after data in VueJS

How to split data in JSON if have array after array? This is my JSON format
{
"status": "true",
"error": "",
"data": [
{
"id": 1,
"sections": [
{
"section_id": 1,
"position": []
}
]
}
]
}
So, I'm using AXIOS . This code AXIOS
const url = '/api/v1/form/'
axios
.get(url)
.then(response => {
this.listing = response.data.data;
})
How to call section using this response.data.data.sections ? I'm try but error undefined. Please help me thanks
response.data.data[0].sections
data is an array according to your json so you cannot directly call sections you will have to iterate or select an instance within the array.
the following code should print all section ids //untested code
const url = '/api/v1/form/'
axios
.get(url)
.then(response => {
response.data.data.foreach((listing)=>{
console.log(listing.sections.section_id)
})
})
If you always will have only one entry under data or you want to access only the 1st entry of data you can use response.data.data[0].sections this is a bad way to access it though because if data is empty it will throw you an error . If the case is that you only have one entry under data you should just change your json to be
{
"status": "true",
"error": "",
"data":
{
"id": 1,
"sections": [
{
"section_id": 1,
"position": []
}
]
}
}
and you can then access it directly response.data.data.sections but as long as its an array you will have to treat it as such.
Iterate through sections and positions [as per comments]:
const url = '/api/v1/form/'
axios
.get(url)
.then(response => {
response.data.data.foreach((listing)=>{ //#this will get you each listing(parent object that contains sections array)
listing.sections.foreach((section)=>{//# this will get you each section(parent object that contains position array)
section.position.foreach((el)=>{//# this will get you each elment in the position array as `el`
console.log(el)
})
})
})
})
Try this:
const url = '/api/v1/form/'
axios
.get(url)
.then(response => {
this.listing = response.data;
console.log(this.listing.data) // <-------
})

Why won't VueJS invoke methods from the created() function?

Learning VueJS and trying to do a simple API call on component load to put a list of repos onto my page. When I call and set the this.repos from the created() method, no problem. But if I set it as a method and then call it from this.getRepos nothing happens. No error, nothing. What am I missing about VueJS?
This works:
data: () => ({
msg: 'Github Repos',
ok: 'Im practically giving away these repos',
repos: [],
}),
methods: {
},
async created() {
const repos = await axios.get('https://api.github.com/orgs/octokit/repos');
this.repos = repos.data.map(repo =>
`<div class="box"><a href="${repo.html_url}">
${repo.name}
</div>`,
);
},
This DOES NOT work:
data: () => ({
msg: 'Github Repos',
ok: 'Im practically giving away these repos',
repos: [],
}),
methods: {
getRepos: async () => {
const repos = await axios.get('https://api.github.com/orgs/octokit/repos');
this.repos = repos.data.map(repo =>
`<div class="box"><a href="${repo.html_url}">
${repo.name}
</div>`,
);
},
},
created() {
this.getRepos();
},
Any ideas? Thanks!
It's simply because you used arrow functions here so that this.repos's this is bound to window object. Changing async () => {} to async function() {} will help you overcome it.
See demo
Note that you should not use an arrow function to define a method (e.g. plus: () => this.a++). The reason is arrow functions bind the parent context, so this will not be the Vue instance as you expect and this.a will be undefined.
reference
Another way to do an Axios call with Vue using then() method:
demo
created() {
axios.get('https://api.github.com/orgs/octokit/repos', {
params: {
type: 'all',
},
})
.then((res) => {
console.log('Success Response', res.data);
res.data.forEach((repo) => {
this.repos.push({ name: repo.name, url: repo.html_url, language: repo.language });
});
})
.catch((err) => {
console.log('Error', err);
});
},

Axios + Vue + Vuex manipulating a basic GET with deeply nested data

I am trying to make a basic GET call to an API using JSON API specifications with deeply nested relationship data. I'm experiencing an issue with axios or vue manipulating my data...
Paying attention to pickup and delivery relationships, the raw data looks like the following:
{
"data": {
"type": "parent",
"id": "34",
"attributes": {
// ...
},
"relationships": {
"r1": {
"data": [
{
"type": "nextparent",
"id": "62",
"attributes": {
// ..
},
"relationships": {
"pickup": {
"data": [
{
"type": "package",
"id": 521,
"attributes": {
// ...
}
},
// ...
]
},
"delivery": {
"data": []
}
}
},
// ...
]
}
}
}
}
... where pickup has an array of objects and delivery has an empty array. However, when I try to retrieve the response in the callback, delivery is an exact copy of pickup.
var promise = window.axios({
url: window.baseApi + '/my-object/34',
method: 'get'
})
promise.then(function (response) {
console.log(response)
})
Whenever you run console.log(response) in the callback, Vue's observers are applied to the response object, which makes me wonder if this is a Vue issue considering that only the relationships of the first r1 object experience this.
Screenshot of log from callback (incorrect):
Additionally, I checked the response from the axios transformResponse function and the raw json was correct (without observers). This is only happening in the callback.
Screenshot of log from transformResponse (correct):
Will update with fiddle, as soon as I can.
EDIT:
The axios function is being called in a vuex action. Here is the code:
fetchData ({commit, dispatch}) {
var promise = window.axios({
url: window.baseApi + '/my-object/34',
method: 'get'
})
promise
.then(function (response) {
console.log(response)
commit('toggleProgress', {key: 'fetchingData'})
commit('setActive', response.data.data)
dispatch('otherModule/setActiveShipments', response.data.data, {root: true})
dispatch('history/clear')
})
.catch(function () {
//
})
return promise
},

Resources