Private channel works with static id but not dynamic vue.js - vue.js

On private channel when i hard coded the ID it works fine and i m receiving messages but when set the value to Dynamic it won't work.
Here is my app.js code
const livechat = new Vue({
el: '#livechat',
data: {
conversation: [],
},
methods: {
addMessage(message) {
// Add to existing messages
// this.conversation.messages.push(message);
// Persist to the database etc
axios.post('/messages', message).then(response => {
this.conversation.messages.push(response.data);
})
}
},
created() {
axios.get('/messages/' + user_id).then(response => {
this.conversation = response.data;
});
Echo.private('chat.' + this.conversation.conversation_id)
.listen('MessageSent', (e) => {
this.conversation.messages.push({
conversation_id: e.message.conversation_id,
message: e.message.message,
name: e.user.firstname
});
});
}
});
On console log i m receving the conversation_id = 22
Echo.private('chat.22') //This works fine
Echo.private('chat.' + this.conversation.conversation_id) //This won't working
Broadcast file
public function broadcastOn()
{
return new PrivateChannel('chat.' . (int)$this->message->conversation_id);
}
Is there any thing wrong in my code. Your help will be appreciated. Thanks

The Echo.private call should be done only when you have all the data - in other words, within axios.get().then(...):
axios.get('/messages/' + user_id).then(response => {
this.conversation = response.data;
Echo.private('chat.' + this.conversation.conversation_id)
.listen('MessageSent', (e) => {
this.conversation.messages.push({
conversation_id: e.message.conversation_id,
message: e.message.message,
name: e.user.firstname
});
});
});

Related

How to use localStorage in Vue?

I am using simple Vue app to get data and then present it in a table. Now I created an OK button, where I can change whether one thing is copmlete or not ( similar to todo app).
But how could I save the changes?
This is my code:
declare var Vue: any;
declare var axios: any;
var vm = new Vue({
el: '#appnew',
data: {
message: '',
status: [],
id: '',
},
created: function () {
this.loadQuote();
},
methods: {
loadQuote: function () {
const id = window.location.pathname.split("/").pop();
this.status = 'Loading...';
axios.get('path' + id)
.then(function (response) {
vm.status = response.data;
})
.catch(function (error) {
vm.status = 'An error occured.' + error;
});
},
toggleDone(statu) {
statu.done = !statu.done
},
},
});
Under the toggleDone method I am changing whether it is done or not, so I guess I should add there to also save the changes? Using localStorage? Any ideas anyone?
Thanks if you can help me.
Yes, you'd have to save the value to localStorage, retrieve it, then do what you want with it:
toggleDone(statu) {
statu.done = !statu.done
localStorage.setItem('statu', statu.done);
}
const statu = localStorage.getItem('statu');

Ionic 4 app - detect if user turns off or on gps

I would like to know how I can do to detect if during any moment of the execution of an Ionic 4 app (not only at the beginning of the app), the user manually turns off or on the GPS.
What Ionic 4 event can I hear from the GPS, to be able to alert at any time of the execution of the app if the user turned off or on the GPS?
Thank you very much and sorry for my bad English
My code on app.component.ts:
initializeApp() {
this.platform.ready().then(() => {
this.screenOrientation.lock(this.screenOrientation.ORIENTATIONS.PORTRAIT_PRIMARY);
this.platform.backButton.subscribeWithPriority(9999, () => {
document.addEventListener('backbutton', function (event) {
event.preventDefault();
event.stopPropagation();
}, false);
this.presentAlertConfirm();
});
this.geolocation.getCurrentPosition().then((resp) => {
this.global.origin = { lat: resp.coords.latitude, lng: resp.coords.longitude };
this.global.latitude = resp.coords.latitude;
this.global.longitude = resp.coords.longitude;
}).catch((error) => {
console.log('Error getting location', error);
});
let watch = this.geolocation.watchPosition();
watch.subscribe((data) => {
this.global.origin = { lat: data.coords.latitude, lng: data.coords.longitude };
this.global.latitude = data.coords.latitude;
this.global.longitude = data.coords.longitude;
}, error => {
console.log('Error getting location in WATCH', error); //error handling //
})
this.statusBar.styleDefault();
this.splashScreen.hide();
});
}
You have to watch for some GPS change. As proposed in the Ionic 4 documentation and as you have done correctly:
this.watch = this.geolocation.watchPosition();
this.watch.subscribe((data) => {
// usable data
}, (error) => {
// some error
}, { timeout: 30000 });
timeout: The maximum length of time (milliseconds) that is allowed to pass without receiving a set of coordinates.
And remeber to unsubscribe on destroy:
public ngOnDestroy(): void {
this.watch.unsubscribe();
}

useMutation not mutating the local state

I'm getting this error while trying to mutate the local state in apollo.
errInvariant Violation: Expecting a parsed GraphQL document. Perhaps you need to wrap the query string in a "gql" tag? http://docs.apollostack.com/apollo-client/core.html#gql
Initial state
registration: {
__typename: 'Registration',
tempMerchantId: '',
authorizeProfile: {
__typename: 'AuthorizePersonProfile',
nid_front: '',
nid_back: '',
authorized_person_photo: ''
}
}
My mutation
export const setAuthorizePersonQuery = gql`
mutation setAuthorizePersonProfileInfo($authorizePerosnData: Object!){
setAuthorizePersonProfileInfo(authorizePersonData: $authorizePerosnData) #client
}
`;
My resolver
export const setAuthorizePersonProfileInfo = (
_, { authorizePersonData }, { cache }
) => {
try {
const prevData = cache.readQuery({ getAuthorizePersonProfileQuery });
cache.writeQuery({
getAuthorizePersonProfileQuery,
data: {
registration: {
__typename: 'Registration',
authorizeProfile: {
__typename: 'AuthorizePersonProfile',
...prevData.registration.authorizeProfile,
...authorizePersonData
}
}
}
});
} catch (e) {
console.log(`err${e}`);
}
return null;
};
I'm trying to mutate the local state on button press, the function is
const handlePressedNext = () => {
Promise.all([
setAuthorizePersonProfileInfo({
variables: { authorizePersonData: generateNidData() }
})
])
.then(() => {
navigation.navigate('Photograph');
});
};
generateNidData function is like bellow
const generateNidData = () => ({
nid_front: nidFrontImage,
nid_back: nidBackImage
});
I'm new to apollo client. I can not understand what I'm doing wrong. Can anyone help me figure out the problem?
getAuthorizePersonProfileQuery is not a valid option for readQuery. Presumably, you meant use query instead.

repetedly call a axios.get to display data from endpoint

I working on backend written in flask that returns REST API for various task, one of which is to request deployment,
Then log gets filled in the database. So I have created another REST API endpoint to return log message for the specific request id. Now what I want is to once the showStatus is true the log_url used by axios.get should be constantly hitting and retrieving data from the backend endpoint retrieving data after 30 seconds. and show it in the show below as statusMessage.
<script>
import Vue from 'vue';
import axios from "axios";
import Multiselect from "vue-multiselect";
Vue.component("multiselect", Multiselect);
export default {
name: 'SelectServices',
data: function() {
return {
selectedService: "",
services: [],
updateExisting: "",
showStatus: false,
statusMessage : ""
}
},
mounted() {
console.log("running script");
},
methods : {
selectServiceToDeploy: function(){
// alert("micro services");
},
deploySelected: function(){
this.showStatus = true ;
// animate open the status window.
$("#status_update").animate({height: '500'})
var url = "http://localwebsite.com:5060/services/request_deploy";
axios.post(url)
.then(response => {
if (typeof response.data.reason != "undefined"){
alert("Recieved Status: " + response.data.status + ",\nReason: " + response.data.reason);
}
var req_id = response.data.result.request_id;
this.statusMessage = "Initiating deployment of Services for Request ID: " + req_id ;
var log_url = "http://localwebsite.com:5060/services/get_logs/" + req_id;
axios.get(log_url)
.then(response => {
if (response.data.status == "success"){
this.statusMessage = this.statusMessage + response.data.logs;
}
})
})
.catch((err) => {
console.log("Error happened: " + err.request.message);
alert(err);
return Promise.reject(err);
})
console.log(url);
console.log(log_url);
}
}
}
based on the above logic I have written in vue it successfully request for deployment but the logs don't get printed in the UI! how can I constantly retrieve data from http://localwebsite.com:5060/services/get_logs/" + req_id after every 30 seconds.
You can do something in the mounted hook:
mounted(){
this.interval = setInterval(() => {
axios.get(this.my_url).then(res => { /* do something */});
}, 30000 );
},
data(){
return {
interval: undefined,
my_url: undefined
}
}
setInterval is a javascript function that allow you to run a function every predefined milliseconds. You can cancel it later with the following command: clearInterval(this.interval). You can also change my_url when you want :)

how to implement reusable api-calling component in vuejs?

I'm developing a simple vuejs app where I have a few identical APIs serving content that is parsed in a similar way. I would like to make the code to fetch the content common across the various API calls, and only have a need to pass the API endpoint to what fetches the content.
Here's my code
var content = new Vue({
el: '#story',
data: {
loaded: [],
current: 0,
hasMore:"",
nextItems:"",
errors: []
},
mounted() {
axios.get("/storyjs")
.then(response => {
this.loaded = this.loaded.concat(response.data.content)
this.hasMore = response.data.hasMore
this.nextItems = response.data.nextItem
}).catch(e => {
this.errors.push(e)
})
},
methods: {
fetchNext: function() {
axios.get(this.nextItems)
.then(response => {
this.loaded = this.loaded.concat(response.data.content)
this.hasMore = response.data.hasMore
this.nextItems = response.data.nextItem
this.current+=1
}).catch(e => {
//TODO CLEAR errors before pushing
this.errors.push(e)
})
},
next: function() {
if (this.current+1 < this.loaded.length) {
this.current+=1
} else {
this.fetchNext()
}
},
prev: function() {
this.current = (this.current-1 >= 0) ? this.current-1 : 0
}
},
delimiters: ['[{', '}]']
})
Right now, I've replicated the above object for stories, poems, and many other things. But I would ideally like to combine them into one. Strategies I tried to search for included having a parent component as this object, but I think I'm probably thinking wrong about some of this.
Really appreciate the help!
I went with mixins. This is the solution I implemented.
apiObject.js (Reusable object)
var apiObject = {
data: function() {
return {
loaded: [],
current: 0,
hasMore: "",
nextItems: "",
errors: []
};
},
methods: {
fetchContent: function(apiEndpoint) {
axios
.get(apiEndpoint)
.then(response => {
this.loaded = this.loaded.concat(response.data.content);
this.hasMore = response.data.hasMore;
this.nextItems = response.data.nextItem;
})
.catch(e => {
this.errors.push(e);
});
},
fetchNext: function() {
axios
.get(this.nextItems)
.then(response => {
this.loaded = this.loaded.concat(response.data.content);
this.hasMore = response.data.hasMore;
this.nextItems = response.data.nextItem;
this.current += 1;
})
.catch(e => {
//TODO CLEAR errors before pushing
this.errors.push(e);
});
},
next: function() {
if (this.current + 1 < this.loaded.length) {
this.current += 1;
} else if (this.hasMore == true) {
this.fetchNext();
}
},
prev: function() {
this.current = this.current - 1 >= 0 ? this.current - 1 : 0;
}
}
};
story.js (Specific usage)
var storyComponent = Vue.extend({
mixins: [apiObject],
created() {
this.fetchContent("/story");
}
});
new Vue({
el: "#story",
components: {
"story-component": storyComponent
},
delimiters: ["[{", "}]"]
});
and then, you could either define the template in the component itself, or use the inline-template way of creating the template in the html file, which is what I did
output.html with all js files included
<div id="story">
<story-component inline-template>
[{loaded[current].title}]
</story-component>
</div>
There are many ways to tackle this, but perhaps once you reach this level of complexity in the model of the components/application state, the most sensible strategy would be to use a central state store.
See the State Management chapter of the vue guide and possibly the excellent vuex.
There you could factor the common logic in suitable local classes/functions and call them from store actions (for async operations you have to use actions, which will commit mutations with respective state changes at completion of the asynchronous operations.