load vue-native-websocket in quasar - vue.js

Im trying to load vue-native-websockets in quasar but Im kind of lost.
I tried to run this as a boot file in quasar:
import VueNativeSock from 'vue-native-websocket'
export default async ({ app, router, store, Vue }) => {
Vue.use(VueNativeSock, 'ws://127.0.0.1:5679', {
store: store,
//format: 'json',
reconnection: true,
reconnectionAttempts: 5,
reconnectionDelay: 3000
})
}
and then:
this.$socket.send("my value");
in a function in my component but I guess I missunderstand the concept. Im pretty new to quasar so a working example would be great indeed ...
I can run this by just creating a connection locally in the component I want to use by putting this in the create method:
this.connection = new WebSocket("ws://127.0.0.1:5679/");
and then using that in a method like:
this.connection.send("myValue")
but the goal is to be able to use the connection in whatever component I like without creating it locally in the create function in that component ...
How can I achieve this?
UPDATE
when using:
https://www.npmjs.com/package/vue-native-websocket-vue3
I get this errormessage after implementing it in main.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import routes from './routes'
Vue.use(VueRouter)
import VueNativeSock from "vue-native-websocket-vue3" ;
Vue.use( VueNativeSock , 'ws://127.0.0.1:5679' );
Errormessage:
property '$socket' of undefined
at Object.install (vueNativeWebsocket.common.js?9cca:3701)
at Function.Vue.use (vue.runtime.esm.js?5593:5107)
at eval (index.js?a18c:10)
at Module../src/router/index.js (app.js:1147) 1: https://quasar.dev/

Related

Importing a Vue library in nuxt.js via plugins

Any idea how I'm going to use this plugin? https://github.com/DimanVorosh/vue-json-rpc-websocket/blob/e2199d89dc15f50e57e7c5c70adfd95e5ceb5cda/src/wsMain.js
I see that it is auto registering with vue but I can't use it in nuxt.
I created the plugins/vue-json-rpc-websocket.client.js, registered in nuxt.config.js as
'~/plugins/vue-json-rpc-websocket.client.js'
but I have no idea what to write in the inject method and IF I have to do it to make it work. this.$socket is undefined in component.
import Vue from 'vue'
import JRPCWS from 'vue-json-rpc-websocket'
Vue.use(JRPCWS, 'wss://bsc-ws-node.nariox.org:443', {
reconnectEnabled: true,
reconnectInterval: 5000,
reconnectAttempts: 3
})
// do I need this?
export default ({ app }, inject) => {
// Inject $hello(msg) in Vue, context and store.
// inject('hello', msg => console.log(`Hello ${msg}!`))
}
also, any idea how can I ENV the 'wss://bsc-ws-node.nariox.org:443' string?
Totally working on my side with the package that you're using and your given configuration. No need to inject anything so far!
Here is a fresh repo created for the example: https://github.com/kissu/so-nuxt-json-rpc-websocket
The below screenshot is using a console.log(this.$socket) in a mounted hook in /pages/index.vue but you can also use $vm0 and access the instance directly from the devtools after selecting the root component (in the screenshot too).
For the env variables part, you can create an .env file at the root of your directory like this
WS_URL="wss://echo.websocket.org"
// nuxt.config.js
export default {
publicRuntimeConfig: {
wsUrl: process.env.WS_URL,
},
}
Then, use this variable in your plugin like this
import Vue from 'vue'
import JRPCWS from 'vue-json-rpc-websocket'
export default ({ $config: { wsUrl } }) => {
Vue.use(JRPCWS, wsUrl, {
reconnectEnabled: true,
reconnectInterval: 5000,
reconnectAttempts: 3
})
}

How to use vue-resource in simple project which uses vue js cdn(not Vue Cli)

I'm using Vue.js in my PHP project as a CDN (it's not a vue Cli project).
I want to use vue-resource to connect one of my vue methods to my ApiController but i don't know how to use this package in a js file.
By the way when i import it like this: import vueResource from 'vue-resource'
i get this error : Cannot use import statement outside a module
import vueResource from 'vue-resource'
use(vueResource);
new Vue({
el:'#panel-main-wrapper',
data : {
collapse:false
},
methods:{
loadCities(field){
this.$http.post('/api/getCities',{
'name' : this.$refs[field].value
}).then(function (data){
alert(data)
})
}
}
})

Vue2 how export multiple components as library that use Vuex?

i'm trying to export a Vue.js 2 project as a library containing multiple components.
Using this as example I managed to export a single component.
In my "library" project, I've exported in the main.js:
import TestButton from "#/components/TestButton";
import store from "#/store";
export default {
install(Vue, options) {
if (!options || !options.store) {
throw new Error("Please initialise plugin with a Vuex store.");
}
options.store.registerModule("testLibrary", store);
Vue.component("test-button", TestButton);
}
};
I build it via vue-cli-service build --target lib --name testlib src/main.js
Published on npm via npm publish --access-public
And then imported in another Vue 2 project.
Here in the main.js I've:
[...]
new Vue({
store,
render: (h) => h(App),
}).$mount("#app");
import TestButton from "my-test-library";
Vue.use(TestButton, { store });
And then I can successfully use <test-button></test-button> in whatever component I need, while the Vuex Store has a working "testLibrary" module.
Now the question is how I can export multiple components in the first app and import in the second one.
I've found many example about, such as this one, however I can't get it working.
For example, in the library app I'm trying
import TestButton from "#/components/TestButton";
import AnotherComponent "#/components/AnotherComponent";
import store from "#/store";
export default {
install(Vue, options) {
if (!options || !options.store) {
throw new Error("Please initialise plugin with a Vuex store.");
}
options.store.registerModule("testLibrary", store);
Vue.component("test-button", TestButton);
Vue.component("another-component", AnotherComponent);
}
};
While in the second app I'm trying something like
[...]
import { TestButton, AnotherComponent } from "my-test-library";
But whatever syntax I try it seems like the second app goes in a loop while building and don't work.
Any idea how is this done?

Creating a single instance of a class within a Vue application

I'm new to Vue and I'm struggling to wrap my head around how to implement what seems to me like a good case for a global variable or singleton.
The background is that I'm using Azure AD B2C for authentication with the MSAL library. MSAL requires a single instance of the Msal.UserAgentApplication to be declared and then shared through the application.
What I'm struggling with is how to declare that instance somewhere central and then access it from each component including the router.
At the moment I've got a class which is similar to this example: https://github.com/sunilbandla/vue-msal-sample/blob/master/src/services/auth.service.js and when I want to use the methods I'm doing:
var authService = new AuthService();
authService.Login();
Unfortunately this creates a new instance of MSAL each time the class is instantiated which in turn caused my users to end up stuck in an authentication loop.
Any help would be greatly appreciated.
Many thanks.
Following on from the answer below by Teddy I've amended my main.js as follows:
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import './registerServiceWorker'
import AuthService from './services/AuthService';
Vue.config.productionTip = false
Vue.prototype.$authService = new AuthService();
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app');
And my register.vue component as follows:
<template>
<div class="about">
<h1>This is the register page, it should redirect off to B2C</h1>
</div>
</template>
<script>
import router from '#/router.js'
export default {
created(){
this.$authService.isAuthenticated().then(
function(result){
if(result){
router.push('/');
}
else{
authService.register();
}
});
}
}
</script>
The component is saying that this.$authService is undefined so it's obviously not reading the prototype.
It feels like I'm missing something really fundamental in Vue at this point.
You can just add it as a Vue instance property. It will be there for all Vue components.
Set it up in main.js like this:
Vue.prototype.$authService = new AuthService();
You can later access it in any Vue component. For example:
this.$authService.Login();
Refer:
https://v2.vuejs.org/v2/cookbook/adding-instance-properties.html
Edit:
You have to use this.$router.push and this.$authService.register inside the isAuthenticated callback. If "this" refers to something else in that block, store var self=this; before the callback starts, or use fat arrow syntax.
<script>
//No import as router is available in 'this'
export default {
created(){
var self=this; //For use inside the callback
this.$authService.isAuthenticated().then(
function(result){
if(result){
self.$router.push('/');
}
else{
self.$authService.register();
}
});
}
}
</script>
Edit 2:
Maybe you can create the instance (singleton) itself in a file called AuthServiceInst.js. Then you can import it in both main.js and router.js.
New file AuthServiceInst.js:
import AuthService from './AuthService.js'
export const authService = new AuthService();
main.js:
import {authService} from './AuthServiceInst.js'
Vue.prototype.$authService = authService;
router.js:
import {authService} from './AuthServiceInst.js'
//Now you can use authService
In Vue 3, to declare global instances you need to use app.config.globalProperties. This is a replacement of Vue 2's Vue.prototype which is no longer present in Vue 3. As with anything global, this should be used sparingly.
// main.js
const app = createApp(App)
.use(router)
.use(store)
.use(vuetify)
app.config.globalProperties.msg = 'hello world'
app.mount('#app')
This makes msg available inside any component template in the application, and also on this of any component instance:
export default {
mounted() {
console.log(this.msg) // 'hello world'
}
}
Source: Docs

Vuex module not accessible from rootState

I needed to get route's query parameters inside Vuex in order to preload filter settings and update the state of the application. To make this possible I installed vuex-router-sync.
Next step was to synchronize the Vuex and VueRouter.
Router:
Vue.use(VueRouter);
export default new VueRouter({ mode: 'history' });
Store:
Vue.use(Vuex);
export default new Vuex.Store({
modules: { filters: FiltersModule },
plugins: [ FiltersPlugin ]
});
App's bootstrap:
const unsync = sync(store, router);
new Vue({
el: '#restaurant-admin-app',
components: {
'App': AppComponent,
'filters': FilterComponent,
'orders-table': OrdersTableComponent
},
store,
router
});
My FilterPlugin that should trigger the URL parsing:
export default store => {
store.dispatch('filters/parseURLFilterSettings');
}
And now, the funny part, here's the URL parsing action:
parseURLFilterSettings: ({ state, commit, rootState }) {
console.log('RootState:', rootState);
console.log('Route module (incorrect):', rootState.route);
console.log('Filters module (correct):', rootState.filters);
console.log('Object\'s keys:', Object.keys(rootState));
}
What am I doing wrong? I thought it might be something with syncing, but at the end the console.log shows clearly that the route Object is there (and it's not empty), but somehow when I access it, it's undefined. Thank you in advance.
The problem was very well explained here. What it basically says is that the object's value is evaluated when you open it's body in the console.
The problem was I didn't have the route module loaded yet, because I was trying to dispatch an action from a vuex plugin which seems to load before the vuex-router-sync's syncing was done.
The problem was solved when I moved application's bootstrap logic from vuex plugins into the AppRootComponent's mount lifecycle event.
You should import the router-sync. After that your store and routes wil behave properly. I usually do this in the main.js file.
import router from './router'
import store from './store'
import { sync } from 'vuex-router-sync'
sync(store, router)