mount any component in vue 3 and laravel-9 - javascript

i´m trying to mount any component with vue 3, this component it´s a datatables with vue-good-table-next. For fill this tables i´m using axios. but only i can mount one table.
this it´s my app.js
require('./bootstrap');
import { createApp } from "vue";
import VueGoodTablePlugin from 'vue-good-table-next';
import 'vue-good-table-next/dist/vue-good-table-next.css'
import datatablePhysios from "./components/datatablePhysios.vue";
import datatableTreatment from "./components/datatableTreatment.vue";
const app = createApp(datatableTreatment) // here it´s the component
app.use(VueGoodTablePlugin);
app.mount("#app")
i know that in createApp() i have only one component. But also i´m trying this:
require('./bootstrap');
import { createApp } from "vue";
import VueGoodTablePlugin from 'vue-good-table-next';
import 'vue-good-table-next/dist/vue-good-table-next.css'
import datatablePhysios from "./components/datatablePhysios.vue";
import datatableTreatment from "./components/datatableTreatment.vue";
const app = createApp({}) // here it´s the component
app.component('datatable-physios', datatablePhysios)
app.component('datatable-treatment', datatableTreatment);
app.use(VueGoodTablePlugin);
app.mount("#app")
with same result. I don´t know how i can to mount more than one component.
UPDATE (bootstrap.js)
window._ = require('lodash');
try {
require('bootstrap');
} catch (e) {}
/**
* We'll load the axios HTTP library which allows us to easily issue requests
* to our Laravel back-end. This library automatically handles sending the
* CSRF token as a header based on the value of the "XSRF" token cookie.
*/
window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
/**
* Echo exposes an expressive API for subscribing to channels and listening
* for events that are broadcast by Laravel. Echo and event broadcasting
* allows your team to easily build robust real-time web applications.
*/
// import Echo from 'laravel-echo';
// window.Pusher = require('pusher-js');
// window.Echo = new Echo({
// broadcaster: 'pusher',
// key: process.env.MIX_PUSHER_APP_KEY,
// cluster: process.env.MIX_PUSHER_APP_CLUSTER,
// forceTLS: true
// });
Thanks for read me and sorry for my bad english

Related

Django + Vue3 + Vite

I am upgrading my multipage app from Vue2+webpack to Vue3+vite.
I got to a point where I can see and render my vue3 on my django templates and all the setup seems to be working.
Now I need to set some of the component variables on the vue app using the django template, but I can't get a hold of my vue instance to do so.
Before I use to do:
//after window loads
app = document.getElementById('abc_app').__vue__ ;
app.message = "New Message";
And it would display the new message.
Now the same doesn't work anymore for vue3, and changing the code to __vue__app__ doesn't work either.
Entry JS from vue2:
import Vue from 'vue'
import abc_app from './abc_app.vue'
const root_element = document.getElementById('abc_app');
const AppRoot = Vue.extend(abc_app);
new AppRoot({
el: root_element,
propsData: { ...root_element.dataset }
});
new entrypoint for Vue3
import abc_app from './abc_app.vue'
const root_element = document.getElementById('abc_app');
import { createApp } from 'vue'
import { createPinia } from 'pinia'
const app = createApp(abc_app)
app.use(createPinia())
app.mount(root_element)
I was able to access the data elements (not the methods) with:
app = document.getElementById('abc_app'). __vue__app__.instance;

How to use conditional user properties with Firebase Remote Config For Web?

I am using firebase remote config for my website in react alongside my ios and android apps.
https://www.npmjs.com/package/firebase
The problem I have is that the conditional values do not work. Getting the values and default implementation works great. ONLY conditions are not respected.
Example:
I set parameter test to true for conditions where user_id equals 1 but this is not being resspected and I get back always the default value which is false
My simplified code is
LoggedTemplate.tsx
// some react component that uses the hook
useFirebaseRemoteConfig(); // see next file
useFirebaseRemoteConfig.ts
import { initializeApp } from 'firebase/app';
import { fetchAndActivate, getRemoteConfig } from 'firebase/remote-config';
import useDidMountEffect from '#/c/hooks/useDidMountEffect';
import Env from '#/Env';
import firebaseConfig from '../../temp/firebase-config.json';
export default function useFirebaseRemoteConfig(): void {
useDidMountEffect(() => {
const app = initializeApp(firebaseConfig);
const remoteConfig = getRemoteConfig(app);
remoteConfig.settings.minimumFetchIntervalMillis = Env.environment === 'local' ? 0 : 3600000 * 6;
fetchAndActivate(remoteConfig)
.then(() => {
window._firebaseRemoteConfig = remoteConfig;
});
});
}
How can I tell firebase this is my user id ?
I am already setting up the user_id property in google analytics
this.gtag('set', { user_id: p.id });

Vue3: injection "Symbol(pinia)" not found

I am using Vue 3 + Vite plugin for Quasar + Pinia for Store management. I followed all official documentation (Quasar, Pinia). But I am getting this error.
[Vue warn]: injection "Symbol(pinia)" not found.
...
runtime-core.esm-bundler.js:38 [Vue warn]: Unhandled error during execution of setup function
at <ViewLogin onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< undefined > >
...
runtime-core.esm-bundler.js:38 [Vue warn]: Unhandled error during execution of scheduler flush. This is likely a Vue internals bug. Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/core
pinia.esm-browser.js:1638 Uncaught (in promise) Error: [🍍]: getActivePinia was called with no active Pinia. Did you forget to install pinia?
const pinia = createPinia()
app.use(pinia)
This will fail in production.
at useStore (pinia.esm-browser.js:1638:19)
js:185:25)
main.js
import {createApp} from 'vue'
import {Notify, Quasar} from 'quasar'
// Import icon libraries
import '#quasar/extras/roboto-font-latin-ext/roboto-font-latin-ext.css'
import '#quasar/extras/material-icons-round/material-icons-round.css'
// A few examples for animations from Animate.css:
// import #quasar/extras/animate/fadeIn.css
// import #quasar/extras/animate/fadeOut.css
// Import Quasar css
import 'quasar/src/css/index.sass'
// Import icon libraries
import '#quasar/extras/material-icons/material-icons.css'
import '#quasar/extras/material-icons-sharp/material-icons-sharp.css'
// Assumes your root component is App.vue
// and placed in same folder as main.js
import App from './App.vue'
import router from "./router/router";
import i18n from "./i18n/i18n"
import {createPinia} from "pinia/dist/pinia";
import {useLoginStore} from "./stores/login";
const app = createApp(App)
// app.config.globalProperties.loginStore = useLoginStore();
app.use(Quasar, {
plugins: {
Notify,
}, // import Quasar plugins and add here
})
app.use(router)
app.use(i18n)
app.use(createPinia())
// Assumes you have a <div id="app"></div> in your router.html
app.mount('#app')
And I am recieving this error after adding 'const store = useLoginStore()' to the component's code.
<script setup>
import {ref} from 'vue'
import {storeToRefs} from 'pinia'
import {useLoginStore} from '../../stores/login'
import {useQuasar} from 'quasar'
const $q = useQuasar()
const email = ref(null)
const password = ref(null)
const store = useLoginStore()
const {loginEmail} = storeToRefs(store)
</script>
What is the problem and how to fix it?
The problem was related to WebStorm. It automatically creates this import:
import {createPinia} from "pinia/dist/pinia";
instead of this
import {createPinia} from 'pinia'
For me it was :
import { isTemplateNode } from '#vue/compiler-core'
Cut and reload the server works fine

How to use Vue.prototype or global variable in Vue 3?

Like the title, I want to add Axios into Vue prototype. So when I want to use it, I can use it like this.$axios instead of importing it every time.
CODE:
//plugins/axios.ts
import axios from 'axios'
import router from '../router/index'
const errorHandle = (): void => {};
const instance = axios.create({
// baseURL: process.env.NODE_ENV == 'development' ? '' : ''
baseURL: 'http://localhost:3000',
timeout: 1000 * 12
});
instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'
export default instance
import { createApp } from 'vue'
import App from './App.vue'
import installElementPlus from './plugins/element'
import instance from './plugins/axios'
import router from './router'
const app = createApp(App).use(router)
installElementPlus(app)
// app.config.globalProperties.http = instance
app.config.globalProperties.$axios= instance
app.mount('#app')
However, there is a problem when I try to use it like this: this.$axios.
TS2339: Property '$axios' does not exist on type 'ComponentPublicInstance<{}, {}, {}, {}, {}, EmitsOptions, {}, {}, false, ComponentOptionsBase<{}, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, EmitsOptions, string, {}>>'.
How could I fix this problem?
You could use provide/inject or define a global config property, which replaces Vue.prototype in Vue 3:
1. provide/inject (for Composition or Options API)
Provide
import axios from 'axios';
const app = Vue.createApp(App);
app.provide('$axios', axios); // Providing to all components during app creation
Inject
Composition API:
const { inject } = Vue;
...
setup() {
const $axios = inject('$axios'); // injecting in a component that wants it
// $axios.get(...)
}
Options API:
inject: ['$axios'], // injecting in a component that wants it
2. Global config (for Options API)
import axios from 'axios';
const app = Vue.createApp(App);
app.config.globalProperties.$axios = axios;
Options API:
this.$axios
Note: This is only for the Options API. Evan You (Vue creator) says: "config.globalProperties are meant as an escape hatch for replicating the behavior of Vue.prototype. In setup functions, simply import what you need or explicitly use provide/inject to expose properties to app."
There is a way to use globalProperties inside a setup function. Although this might be considered an anti-patter. It would be better to use provide/inject if possible. But if there is a library that uses globalProperties and you really need to access it from setup this is how you could do it.
<script setup>
import { getCurrentInstance } from 'vue'
const app = getCurrentInstance()
const progressBar = app.appContext.config.globalProperties.$Progress
progressBar.start()
</script>

How do I unit test a Vue.js component that relies on a complicated Vuex store and extends another component?

I am wondering how one goes about unit testing a component that uses a complicated Vuex store and extends another component.
Can someone please provide me with an example of how I might go about creating a test that simply asserts that a component that extends another component and relies on Vuex mounts and displays some simple text?
I've tried using vue-test-utils to shallowMount the component under test, but I can't get my test to fail because it has issues even building and mounting the component. As far as I can tell, this is a result of the component leveraging the extended component, and because both components rely on a complicated Vuex store.
Any kind of examples would be appreciated. Thanks.
EDIT:
For further context, our store is broken up into modules. Here is what the store definition file looks like:
/* global phpvars */
import Vue from 'vue'
import Vuex from 'vuex'
import * as actions from './actions'
import * as getters from './getters'
import * as mutations from './mutations'
import acloverrides from '../../modules/acloverrides'
import api from '../../modules/api'
import callback from '../../modules/callback'
import clearlink from '../../modules/clearlink'
import configuration from '../../modules/configuration'
import customer from '../../modules/customer'
import drKeepAlive from '../../modules/drkeepalive'
import interaction from './modules/interaction'
import ivr from './modules/ivr'
import marketing from '../../modules/marketing'
import opportunities from './modules/opportunities'
import order from '../../modules/order'
import orderNotes from './modules/notes'
import products from '../../modules/products'
import sidebar from './modules/sidebar'
import sparks from './modules/sparks'
import training from '../../modules/training'
import transformers from '../../modules/transformers'
import user from '../../modules/user'
let brand = require('../brands/' + phpvars.brand.name + '/modules/brand').default
let forms = require('../brands/' + phpvars.brand.name + '/modules/forms').default
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
acloverrides,
api,
brand,
callback,
clearlink,
configuration,
customer,
drKeepAlive,
forms,
interaction,
ivr,
marketing,
opportunities,
order,
orderNotes,
products,
sidebar,
sparks,
training,
transformers,
user
},
state: {
availability: {
status: false,
results: {}
},
navigation: {
enabled: phpvars.user.access.order.navigate,
restrictTo: []
},
routes: [],
router: {},
editMode: false // Used to determine if the user has clicked the edit button on an existing order.
},
actions,
getters,
mutations
})
And here is my unit test file:
import Vuex from 'vuex'
import { shallowMount, createLocalVue } from '#vue/test-utils'
import SelectedProducts from '../../resources/assets/js/components/formfields/products/SelectedProducts'
import BaseField from '../../resources/assets/js/components/BaseField'
import store from '../../resources/assets/js/orderform/store/index.js'
const Vue = createLocalVue()
Vue.use(Vuex)
describe('SelectedProducts', () => {
fit('sanity check', () => {
window.phpvars = {
brand: {
name: 'foobar'
},
user: {
access: {
order: {
navigate: true
}
}
}
}
const wrapper = shallowMount(SelectedProducts, {
store: new Vuex.Store(store)
})
expect(wrapper.text()).toContain('Selected Products')
})
})
I find Vue documentation on unit testing to be a bit vague. Give this a shot:
import {createLocalVue, shallowMount} from '#vue/test-utils';
import Vuex from 'vuex';
import store from 'path/to/store/index.js';
import Component from 'path/to/Component';
// create a local instance that uses
// the store, should follow a pattern present
// in your src/main.js
const localVue = createLocalVue();
localVue.use(Vuex);
describe(
'Component', () => {
test('renders', () => {
const wrapper = shallowMount(Component, {
store: new Vuex.Store(store)
});
expect(wrapper.isVueInstance()).toStrictEqual(true);
});
}
);
EDIT for your edit
In Jest, window is replaced by global. So you could mock your phpvars with:
global.phpvars = {
brand: {
name: 'foobar'
},
user: {
access: {
order: {
navigate: true
}
}
}
};
You'll want to place that before you import your store.
Components that extend other components shouldn't be tested any differently, they essentially compile down to a single component in terms of variables and requirements. If you could expand on that question, I'd be happy to answer (like, what issues or errors you are encountering unique to your extended components).
I haven't tested anything I've mentioned so if you do continue to have errors I'll throw together a project. Good luck!

Categories

Resources