Change dynamically text up to backendresponse - vue.js

I created vuejs project with npm. This is App.vue:
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'app',
components: {
HelloWorld
}
}
</script>
This is helloworld.vue
<template>
<div class="hello">
<label>File
<input type="file" id="file" ref="file" v-on:change="handleFileUpload()"/>
</label>
<button v-on:click="submitFile()">Submit</button>
<span id="error" style="color: red; display: none;">{{message}}</span>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'HelloWorld',
props: {
msg: String
},
methods: {
submitFile() {
let formData = new FormData();
/*
Add the form data we need to submit
*/
formData.append('file', this.file); //todo get "file" string from external
/*
Make the request to the POST /single-file URL
*/
axios.post('http://localhost:8082/upload/'
+ this.bank
+ '/'
+ this.currency,
formData,
{
headers: {
'Content-Type': 'multipart/form-data'
}
}
).then(function (response) {
console.log('SUCCESS!! + response', response);
this.message= "successfully uploaded"
})
.catch(function (response) {
console.log('FAILURE!!+ response', response);
this.message= "successfully uploaded"
});
}
}
}
</script>
It says when it compiles:
vue.runtime.esm.js?2b0e:619 [Vue warn]: Property or method "message" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.
but i need to show a dynamic messagae according to backend response:
<span id="error" style="color: red; display: none;">{{message}}</span>
This is main.js:
new Vue({
render: h => h(App),
}).$mount('#app')
Also when i add data under props in helloworld.vue, like this:
export default {
name: 'HelloWorld',
props: {
msg: String
},
data: {
},
it says:
error: `data` property in component must be a function (vue/no-shared-component-data) at src\components\HelloWorld.vue:36:9:
I did not change or add any files after npm create. Should i create a new file?
this.message = "successfully uploaded" gives Uncaught (in promise) TypeError: Cannot set property 'message' of undefined

You have props:
props: {
msg: String
},
But you are using {{message}} instead.
data should be like this (if you need message property):
data(){
return {
message: '',
};
},
Add created method like this (if you need to put your msg props to message):
created(){
this.message = this.msg;
}
Upd.
Change your code to this (arrow function instead of function) (Upd.2 As mentioned #AJT82 in his answer right before my updates was made):
<script>
import axios from 'axios';
export default {
name: 'HelloWorld',
props: {
msg: String
},
methods: {
submitFile() {
let formData = new FormData();
/*
Add the form data we need to submit
*/
formData.append('file', this.file); //todo get "file" string from external
/*
Make the request to the POST /single-file URL
*/
axios.post('http://localhost:8082/upload/'
+ this.bank
+ '/'
+ this.currency,
formData,
{
headers: {
'Content-Type': 'multipart/form-data'
}
}
).then((response) => {
console.log('SUCCESS!! + response', response);
this.message= "successfully uploaded"
})
.catch((response) => {
console.log('FAILURE!!+ response', response);
this.message= "successfully uploaded"
});
}
}
}
</script>

Related

Vue3 datatable not updating after Axios request

Im building a datatable and it shows my test-data correctly.
However, after i do my Axios request, it doesnt update the state.tableData variable!
What am I doing wrong here?
I keep seeing a table with the value 'test1', and not 'test2' and 'test3'?
I am using Vue3 with the composition API.
This is the template part:
<template>
<div class="card">
<div class="card-body pt-0">
<Datatable
:table-data="state.tableData"
:table-header="state.tableHeader"
>
<template v-slot:cell-name="{ row: item }">
{{ item.name }}
</template>
</Datatable>
</div>
</div>
</template>
And the JS code:
<script lang="ts">
import { defineComponent, toRefs, reactive, ref, onMounted } from "vue";
import Datatable from "#/components/kt-datatable/KTDatatable.vue";
import axios, { AxiosRequestConfig, AxiosResponse} from 'axios';
export default defineComponent({
name: "listing",
components: {
Datatable,
},
setup() {
interface fieldDefinitions {
name: string;
}
const state = reactive({
tableData: ref<fieldDefinitions[]>([]),
tableHeader: [{
name: "Naam",
key: "name",
sortable: true,
}]
});
function getListings() {
const config: AxiosRequestConfig = {
method: 'get',
url: 'https://myurl',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
};
axios(config)
.then(function (response) {
//state.tableData = response.data.data;
state.tableData = [{'name':'test2'},{'name':'test3'}];
console.log(state.tableData);
})
.catch(function (error) {
console.log(error);
});
}
onMounted(async () => {
getListings()
});
return { state,getListings };
},
});
</script>
Not sure why you have tableData: ref<fieldDefinitions[]>([]), you are assigning state.tableData = [{'name':'test2'},{'name':'test3'}]; not state.tableData = ref([{'name':'test2'},{'name':'test3'}]). But even then, state.tableData.value is not needed since reactive unwraps refs. see docs. So as far as I can tell and reproduce, your code should be working properly to trigger reactivity.
The issue is likely due to your Datatable component is not updating properly.

Airtable data into Vue.js

I am new to vue js and have been trying for hours to get airtable data into my application. I am hoping someone could help me as I feel I am almost there! I am using the Airtable NPM package to retrieve the data - https://www.npmjs.com/package/airtable
<template>
<section id="cards-section" class="cards-section">
<div class="centered-container w-container">
<h1>{{ msg }}</h1>
<div class="cards-grid-container">
<Card />
<ul id="example-1">
<li v-for="item in recordsList" v-bind:key="item">
data here {{ item }}
</li>
</ul>
</div>
</div>
</section>
</template>
<script>
import Card from "../components/Card.vue";
import Airtable from "airtable";
export default {
name: "Main",
components: {
Card,
},
props: {
msg: String,
},
data() {
return {
recordsList: [],
};
},
mounted() {
const base = new Airtable({ apiKey: "******" }).base(
"******"
);
base("Table 1")
.select({
view: "Grid view",
})
.firstPage(function (err, records) {
if (err) {
console.error(err);
return;
}
records.forEach( (record) => {
console.log(record.get("Name"));
return record.get("Name")
});
});
},
};
</script>
<style scoped>
</style>
Looking at your code you are probably at the stage that you have succesfully retrieved the data from airtable and seeing some records in your console.log.
Now how to get them from inside that function to your Vue instance:
I will show you two ways to go about this and explain them later:
Method 1: Using a reference to self.
<script>
import Card from "../components/Card.vue";
import Airtable from "airtable";
export default {
name: "Main",
components: {
Card,
},
props: {
msg: String,
},
data() {
return {
recordsList: [],
};
},
mounted() {
// create a reference to this vue instance here.
var self = this;
const base = new Airtable({ apiKey: "******" }).base(
"******"
);
base("Table 1")
.select({
view: "Grid view",
})
.firstPage(function (err, records) {
if (err) {
console.error(err);
return;
}
// now we can set the recordList of our
// vue instance:
self.recordsList = records;
});
},
};
</script>
Method 2: Using javascript arrow function:
<script>
import Card from "../components/Card.vue";
import Airtable from "airtable";
export default {
name: "Main",
components: {
Card,
},
props: {
msg: String,
},
data() {
return {
recordsList: [],
};
},
mounted() {
// no need to create a reference this time.
const base = new Airtable({ apiKey: "******" }).base(
"******"
);
base("Table 1")
.select({
view: "Grid view",
})
.firstPage( (err, records) => {
if (err) {
console.error(err);
return;
}
this.recordsList = records;
});
},
};
</script>
Now what was the problem? In the first example we use a normal javascript anonymous function. this inside a normal javascript anonymous function is not what you expect it to be. We solve this by defining a reference to this (var self = this) somewhere and instead of trying this.recordsList we do self.recordsList inside our anynomous function.
Nem improvements to the javascript language introduced another type of function, the arrow function. One benefit of this function is that this inside this function is the object that you've defined it in. So, this is our vue instance. Now we don't have a problem and can just set this.recordsList.
Other solutions i've ommitted are:
Using Function.bind
async/await

How to use Axios with Vue-Multiselect?

New to using Vue-Multiselect. I am using axios to do a GET request from a JSON placeholder to test.
How do I get the title and post id to show up in my drop down?
Right now, I just get [Object Object] - [title] shown in my select box.
<!-- Vue component -->
<template>
<div>
<multiselect v-model='value' :options='posts' :custom-label='postWithTitle' placeholder='Select one' label='title' track-by='id'></multiselect>
{{ value }}
</div>
</template>
<script>
import Multiselect from "vue-multiselect";
import axios from "axios";
export default {
// OR register locally
components: { Multiselect },
data() {
return {
value: null,
posts: []
};
},
created() {
this.getPosts();
},
methods: {
getPosts() {
axios
.get("https://jsonplaceholder.typicode.com/posts")
.then(response => {
// eslint-disable-next-line
console.log(response);
this.posts = response.data;
})
.catch(error => {
// eslint-disable-next-line
console.log(error);
});
},
postWithTitle(id, title) {
return `${id} - [${title}]`;
}
}
};
</script>
fix:
postWithTitle(option) {
return `${option.id} - [${option.title}]`;
}
explaination:
i saw that when i simply console.logged inside the postWithTitle function:
the custom custom-label attribute was accepting a callback that only accepts one argument. that argument was the entire option object- a single entry of your posts array.

Echo.private and /broadcasting/auth 405 error

In a Vuejs/Larvel forum, I'm seeing the following error when a question and its replies are displayed:
POST http://127.0.0.1:8000/broadcasting/auth 405 (Method Not Allowed)
If I remove an Echo.private method from the component that lists the comments, the error disappears. However, I can't see how the Echo... method is incorrect and don't know where else to look.
The relevant (I hope) code extracts are:
bootstrap.js
import Echo from 'laravel-echo'
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'myKey',
wsHost: window.location.hostname,
wsPort: 6001,
disableStats: true,
auth:{
headers:{
Authorization: JWTtoken
}
}
});
channels.php
Broadcast::channel('App.User.{id}', function ($user, $id) {
return (int) $user->id === (int) $id;
});
Broadcast::channel('likeChannel', function () {
return true;
});
replies.vue
<template>
<div>
<p v-if="comments>0"><em>{{$t('Comments')}}</em></p>
<reply
v-for="(r,index) in content"
:key="r.id"
:index=index
v-if="question.replies"
:data="r"
></reply>
</div>
</template>
<script>
import Reply from './Reply';
import { eventBus } from '../../app';
export default {
name: "Replies",
props: ['question'],
components: {Reply},
data(){
return {
content:this.question.replies,
comments:this.question.replies.length,
}
},
created(){
this.listen();
},
methods: {
listen(){
console.log('userID='+this.UserID)
Echo.private('App.User.' + this.UserID)
.notification((notification) => {
console.log('Replies 36; Notification type: '+ notification.type);
this.content.unshift(notification.reply)
});
eventBus.$on('replyCreated',(reply)=>{
this.content.unshift(reply) //unshift adds item to top of array
});
eventBus.$on('deleteReply',(index) => {
axios.delete(`api/question/${this.question.slug}/reply/${this.content[index].id}`)
.then(res => {
this.content.splice(index,1);
}
)
});
},
},
computed: {
UserID: function () {
var tk = localStorage.getItem('token');
var payload = tk.split('.')[1];
var pl = JSON.parse(atob(payload));
return pl.sub;
},
}
}
</script>
<style scoped>
</style>
Commenting out all the Echo.private material removes the error; commenting out just the .notification part doesn't have the same effect suggesting it is not the contents of 'notification'.
Obviously I've revealed myself to be new and lost in space here; perhaps what I'm seeing is the consequence of a problem elsewhere - but I'm at a loss where to look elsewhere.
Thanks,
Tom

Cannot read property 'list' of null - VueJS

Im creating a Notification component using Vuex to store data API and called it in components but I have some issues
Component.vue
<template>
<div class="notification_check">
<div class="header">
<span>Notifications </span>
<span>(1)</span>
</div>
</div>
<ul v-for="notification in $store.state.notification.notifications.list" :key="notification.id">
{{notification.id}}
</ul>
</template>
<script>
export default {
data: function () {
return {
config: {
'headers': {
'Authorization': 'JWT ' + this.$store.state.token
}
},
notifications: this.$store.state.notification.notifications.list
}
},
created: function () {
this.getNotification()
},
methods: {
getNotification: function () {
this.$store.dispatch('getNotification', this.config)
}
}
}
</script>
This is Action Commit:
getNotification ({commit}, config) {
api.get(`/notifications/`, config)
.then(response => {
commit('GET_NOTIFICATION', response.data)
})
},
This is my data API which stored in Vuex Store. Please take a look:
Error occurs:
Cannot read property 'list' of null