Echo.private and /broadcasting/auth 405 error - vue.js

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

Related

How can I define the pdf url document with axios and not static with vue-pdf

pdf and I see that this example that developer gave it's ok it worked to me but the problem it is that he indicates a static pdf and I wonder how can I fix that if you see the example is like this:
<template>
<div>
<pdf
v-for="i in numPages"
:key="i"
:src="src"
:page="i"
style="display: inline-block; width: 25%"
></pdf>
</div>
import pdf from 'vue-pdf'
var loadingTask = pdf.createLoadingTask('https://cdn.mozilla.net/pdfjs/tracemonkey.pdf');
export default {
components: {
pdf
},
data() {
return {
src: loadingTask,
numPages: undefined,
}
},
mounted() {
this.src.promise.then(pdf => {
this.numPages = pdf.numPages;
});
}
}
If you see this line var loadingTask = pdf.createLoadingTask('https://cdn.mozilla.net/pdfjs/tracemonkey.pdf'); gets the document as static but I wonder if I have this code and I am getting the name from database like this:
export default {
created() {
this.getPost();
},
components: {
pdf
},
methods: {
getPost() {
this.loading = true;
axios.get('/api/content/detail/'+ this.$route.params.id)
.then(response => {
this.post = response.data.data;
this.pdf_url = '/storage/'+this.post.pdf;
})
.catch(function (error) {
console.log(error);
})
.finally(() => {
this.loading = false;
});
}
If you see I have the name into this.pdf_url but I do not know how to add this name to this pdf.createLoadingTask(''); How can I do it? because it is a defined var Thanks

Vue2 create component based on data

I want to create a component based on ajax api response or data which include:
template
data
methods - there may be several methods
Remark: response or data is dynamic and it is not saved in file.
I have tried to generate and return result like :
<script>
Vue.component('test-component14', {
template: '<div><input type="button" v-on:click="changeName" value="Click me 14" /><h1>{{msg}}</h1></div>',
data: function () {
return {
msg: "Test Componet 14 "
}
},
methods: {
changeName: function () {
this.msg = "mouse clicked 14";
},
}
});
</script>
and do compile above code :
axios.get("/api/GetResult")
.then(response => {
comp1 = response.data;
const compiled = Vue.compile(comp1);
Vue.component('result-component', compiled);
})
.catch(error => console.log(error))
I got error on Vue.compile(comp1) -
Templates should only be responsible for mapping the state to the UI. Avoid placing tags with side-effects in your templates, such as
<script>, as they will not be parsed.
Thanks in advance
Your Api should return a JSON with every property required by a Vue component (name, data, template, methods), note that methods needs to be converted into an actual js function (check docs about that)
Vue.config.productionTip = false;
Vue.config.devtools = false;
new Vue({
el: '#app',
data() {
return {
apiComponent: { template: '<div>Loading!</div>' }
};
},
methods: {
loadApiComponent() {
setTimeout(() => {
this.buildApiComponent(JSON.parse('{"name":"test-component14","template":"<div><input type=\\\"button\\\" v-on:click=\\\"changeName\\\" value=\\\"Click me 14\\\" /><h1>{{msg}}</h1></div>","data":{"msg":"Test Componet 14 "},"methods":[{"name":"changeName","body":"{this.msg = \\\"mouse clicked 14\\\";}"}]}'));
}, 2000);
},
buildApiComponent(compObject) {
const {
name,
template,
data,
methods
} = compObject;
const compiledTemplate = Vue.compile(template);
this.apiComponent = {
...compiledTemplate,
name,
data() {
return { ...data
}
},
methods: methods.reduce((c, n) => {
c[n.name] = new Function(n.body);
return c;
}, {})
};
}
},
mounted() {
this.loadApiComponent();
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<component :is="apiComponent" />
</div>

Calling API in method and getting [object Promise]

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.

Printing data variable

I am trying to print data() variable. I am not getting output in HTML template.
<template>
<h3>{{app_skills}}</h3> <!-- I am not getting value here -->
</template>
<script>
export default {
name: "leftbar",
data() {
return {
app_skills: '',
}
},
methods : {
fetchskills (url) {
url = '/skills';
axios.get(url)
.then(response => {
this.app_skills = response.data.skills;
console.log(this.app_skills) // I am getting value here
})
.catch(error => {
console.log(error);
});
}
},
mounted() {
this.fetchskills();
}
}
</script>
Your code worked exactly as expected when I tried it (with a few environment-related changes):
<template>
<h3>{{app_skills}}</h3> <!-- I am not getting value here -->
</template>
<script>
import axios from 'axios';
export default {
name: "leftbar",
data() {
return {
app_skills: '',
}
},
methods : {
fetchskills (url) {
url = 'https://dns.google.com/resolve?name=example.com';
axios.get(url)
.then(response => {
this.app_skills = response.data;
console.log(this.app_skills) // I am getting value here
})
.catch(error => {
console.log(error);
});
}
},
mounted() {
this.fetchskills();
}
}
</script>
All I changed was including the axios library, changing the URL to pull from, and changing the response.data key to pull. It all works as expected. Perhaps you have an issue somewhere else in your surrounding code?

VueJS: Setting data initially based on http response

So I have a template .vue file:
<template>
<div id="app">
<textarea v-model="input" :value="input" #input="update"></textarea>
<div v-html="compiledMarkdown"></div>
</div>
</template>
<script>
var markdown = require('markdown').markdown;
export default {
name: 'app',
data() {
return {
input: '# Some default data'
}
},
mounted: function () {
this.$nextTick(function () {
this.$http.get(window.location.pathname + '/data').then((response) => {
this.input = response.body.markdown;
}) })
},
computed: {
compiledMarkdown: function() {
this.$http.post(window.location.pathname, {
"html": markdown.toHTML(this.input)}).then(function() {
},function() {
});
return markdown.toHTML(this.input);
}
},
methods: {
update: function(e) {
this.input = e.target.value
}
}
}
</script>
In the mounted function I am trying to set input equal to the response of an HTTP request, but when you view this file this.input is still the same as it was initially declared. How can I change this.input inside the compiledMarkdown function to be this.input in the mounted function. What other approaches might I take?
You can not call a async method from a computed property, you can use method or watcher to run asynchronous code, from docs
This is most useful when you want to perform asynchronous or expensive operations in response to changing data.
You have to ran that relevant code when input changes, like following:
var app = new Vue({
el: '#app',
data: {
input: '# Some default data',
markdown : ''
},
methods: {
fetchSchoolData: function (schoolId) {
var url = this.buildApiUrl('/api/school-detail?schoolId=' + schoolId);
this.$http.get(url).then(response => {
this.schoolsListData = response.data;
}).catch(function (error) {
console.log(error);
});
},
},
mounted: function () {
this.$nextTick(function () {
this.$http.get(window.location.pathname + '/data').then((response) => {
this.input = response.body.markdown;
})
})
},
watch: {
// whenever input changes, this function will run
input: function (newInput) {
this.$http.post(window.location.pathname, {
"html": markdown.toHTML(this.input)}).then(function() {
},function() {
this.markdown = markdown.toHTML(this.input);
});
}
},
Have a look at my similar answer here.