How to add vue3-openlayers plugin to nuxt - javascript

I have the following main.ts file in Vue3:
import { createApp } from "vue"
import App from "./App.vue";
//How to do this in nuxt3?
import OpenLayersMap from "vue3-openlayers";
import "vue3-openlayers/dist/vue3-openlayers.css";
const app = createApp(App);
//How to do this in nuxt3?
app.use(OpenLayersMap);
app.mount("#app");
How can I add the vue3-openlayers plugin to nuxt3?

To auto-install a Vue plugin in Nuxt 3, create a .js/.ts file under <projectDir>/plugins/ (create the directory if needed) with the following boilerplate:
// plugins/my-plugin.js
import { defineNuxtPlugin } from '#app'
export default defineNuxtPlugin(nuxtApp => {
nuxtApp.vueApp.use(/* MyPlugin */)
})
Since vue3-openlayers depends on window, the plugin can only be installed client side, so use the .client.js extension.
To load vue3-openlayers client side, the plugin file would look like this:
// plugins/vue3-openlayers.client.js
import { defineNuxtPlugin } from '#app'
import OpenLayers from 'vue3-openlayers'
export default defineNuxtPlugin(nuxtApp => {
nuxtApp.vueApp.use(OpenLayers)
})
Create <projectDir>/components/MyMap.vue with the following example content from the vue3-openlayers docs:
// components/MyMap.vue
<script setup>
import { ref } from 'vue'
const center = ref([40, 40])
const projection = ref('EPSG:4326')
const zoom = ref(8)
const rotation = ref(0)
</script>
<template>
<ol-map :loadTilesWhileAnimating="true" :loadTilesWhileInteracting="true" style="height:400px">
<ol-view :center="center" :rotation="rotation" :zoom="zoom"
:projection="projection" />
<ol-tile-layer>
<ol-source-osm />
</ol-tile-layer>
</ol-map>
</template>
<style scoped>
#import 'vue3-openlayers/dist/vue3-openlayers.css';
</style>
We only want to render MyMap on the client because the plugin is only client-side, so use the <ClientOnly> component as a wrapper:
// app.vue
<template>
<ClientOnly>
<MyMap />
<template #fallback> Loading map... </template>
</ClientOnly>
</template>
demo

Related

How to add resize event handler to my vue code?

I am new to Vue. I am a react developer trying to update some legacy code from my work.
What I want to do is I want to have a screen resize event handler in my component.
I found some helpful code pen https://codepen.io/sandrarodgers/pen/porZbxW
The thing is I don't know how to add those in my existing component.
To give you the general idea. My component already got two script tags
When I try to copy paste from codeine it give me some error on this keyword
Component
<template>
<div :style="styles">
...
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import MultipleChoiceField from '../fields/MultipleChoiceField.vue';
import NumberField from '../fields/NumberField.vue';
export default defineComponent({
name: 'Questionnaire',
components: {
MultipleChoiceField,
NumberField,
},
});
</script>
<script setup lang="ts">
import {
defineProps,
defineEmits,
computed,
nextTick,
onMounted,
ref,
toRefs,
watch,
unref,
} from 'vue';
import {
handleQuestionLogicCalculator,
} from '../../lib/main';
import { typeformMarkdownToHtml } from '../../lib/processTypeformMarkdown';
import {
PrefilledAdditionalParameters,
QuestionnaireChoice,
} from '../../lib/types';
import localize from '../../lib/localization';
const props = defineProps<{
additions: PrefilledAdditionalParameters;
questionnaireConfig: QuestionnaireConfig;
styles: QuestionnaireStyles;
submitAnswers: ShowThankYouFunction;
showwelcomeScreen: () => void;
goBack: () => void;
}>();
const emit = defineEmits(['latestQuestionnaireIndex']);
//MORE CODE HERE
</script>

Vue 3: How to pass data from component to App.vue when there is a router-view in between?

I have the following structure:
src
components
Footer.vue
views
Page.vue
App.vue
I would like to be able to access the 'message' variable in App.vue, but I can´t figure out how to do it when Footer.vue is not a direct child of App.vue (but child of Page.Vue which - via the router - is child App.vue).
What do I need to add in my files? There are now as follows - and (of course) no message appears in App.vue:
//App.vue
<template>
  <p>Message is: {{ message }}</p>
  <router-view />
</template>
<style lang="scss">
#import "./_scss/main.scss";
</style>
.
//Page.vue
<template>
  <Footer/>
</template>
<script>
import Footer from '#/components/Footer.vue'
export default {
  components: {
    Footer
  }
}
</script>
.
//Footer.vue
<template>
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
</template>
<script>
export default {
    data() {
        return {
            message: ''
        }
    }
}
</script>
Maybe Composition API and ES6 modules?
#/compositions/composition.js
import { ref } from 'vue'
const message = ref('test');
export const useComposition = function() {
// other functions, for example to mutate message ref
return {
message,
// ...
}
}
And now you import your composition in the components that need to access message:
// Footer.vue, App.vue
<script>
import { defineComponent } from 'vue'
import { useComposition } from '#/compositions/composition'
export default defineComponent({
setup() {
const { message } = useComposition();
return { // make it available in <template>
message
}
},
})
</script>
If you want to quickly get started with Composition API, see this.

How to use <component :is=""> in vue 3 script setup

I am using the experimental script setup to create a learn enviroment. I got a selfmade navigation bar with open a single component.
I am having trouble using the <component :is="" /> method. This method is described in the docs under component basics -> dynamic-components
In the Vue 3 Composition API, it works as expected:
<template>
<NavigationBar
#switchTab="changeTab"
:activeTab="tab"
/>
<component :is="tab" />
</template>
<script>
import { ref } from 'vue'
import NavigationBar from './components/NavigationBar.vue'
import TemplateSyntax from './components/TemplateSyntax.vue'
import DataPropsAndMethods from './components/DataPropsAndMethods.vue'
export default {
components: {
NavigationBar,
TemplateSyntax,
DataPropsAndMethods
},
setup () {
const tab = ref('DataPropsAndMethods')
function changeTab (newTab) {
tab.value = newTab
}
return {
changeTab,
tab
}
}
}
</script>
My approach with the script setup fails:
<template>
<NavigationBar
#switchTab="changeTab"
:activeTab="tab"
/>
<component :is="tab" />
</template>
<script setup>
import NavigationBar from './components/NavigationBar.vue'
import TemplateSyntax from './components/TemplateSyntax.vue'
import DataPropsAndMethods from './components/DataPropsAndMethods.vue'
import { ref } from 'vue'
const tab = ref('DataPropsAndMethods')
function changeTab (newTab) {
tab.value = newTab
}
</script>
do you got any idea how to solve this with the script setup method?
It seems with <script setup>, tab needs to reference the component definition itself instead of the component name.
To reference the component definition, which does not need reactivity, use markRaw() before setting tab.value:
<script setup>
import DataPropsAndMethods from './components/DataPropsAndMethods.vue'
import { ref, markRaw } from 'vue'
const tab = ref(null)
changeTab(DataPropsAndMethods)
// newTab: component definition (not a string)
function changeTab (newTab) {
tab.value = markRaw(newTab)
}
</script>
demo 1
If you need to pass the component name to changeTab(), you could use a lookup:
<script setup>
import DataPropsAndMethods from './components/DataPropsAndMethods.vue'
import { ref, markRaw } from 'vue'
const tab = ref(null)
changeTab('DataPropsAndMethods')
// newTab: component name (string)
function changeTab (newTab) {
const lookup = {
DataPropsAndMethods,
/* ...other component definitions */
}
tab.value = markRaw(lookup[newTab])
}
</script>
demo 2
Tested with Vue 3.0.9 setup with Vue CLI 5.0.0-alpha.8

How to optimize bundling custom vue components using 3rd party libraries with vue cli 3?

I'm building my external vue component library and published to npm. My components extends Element UI components.
I followed the steps in this article and so far it works fine. https://medium.com/justfrontendthings/how-to-create-and-publish-your-own-vuejs-component-library-on-npm-using-vue-cli-28e60943eed3
npm package
https://www.npmjs.com/package/#bochen/example-lib
bundle script
"build-bundle": "vue-cli-service build --target lib --name exampleLib ./src/components/index.js",
src/components/index.js
import Vue from 'vue';
import BcButton from './Button.vue';
const Components = {
BcButton,
};
Object.keys(Components).forEach((name) => {
Vue.component(name, Components[name]);
});
export default Components;
src/components/Button.vue
<template>
<el-button v-bind="$props"
:class="{
'button-full': full,
}"
>
<slot/>
</el-button>
</template>
<script>
import { Button } from 'element-ui';
export default {
name: 'BcButton',
extends: Button,
props: {
full: {
type: Boolean,
default: false,
},
},
};
</script>
<style scoped>
.button-full {
width: 100%;
}
</style>
Issue
The problem is after I installed my library at another project, I still need to import Element UI in addition to make it work.
main.js
import Vue from 'vue'
import App from './App.vue'
import Element from 'element-ui';
import ExampleLib from '#bochen/example-lib';
import 'element-ui/lib/theme-chalk/index.css';
import '#bochen/example-lib/dist/exampleLib.css';
Vue.use(Element);
Object.keys(ExampleLib).forEach((name) => {
Vue.component(name, ExampleLib[name]);
});
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
Is there any possible, I could just import my library and work as I expected?

How to correctly globally register and use Vue Rangedate Picker component?

I am trying to use VueRangedatePicker and I can't seem to figure out how to use this on the template of some other vue component. I am using Webpack.
I have registered the component/plugin on my main.js file like this:
import Vue from 'vue'
import App from './App'
import router from './router'
import { store } from './store/store'
import firebase from './firebase-config'
import vuefire from 'vuefire'
//////////////// HERE
import VueRangedatePicker from 'vue-rangedate-picker' // importing the plugin here
Vue.use(VueRangedatePicker) // using it
Vue.component('VueRangedatePicker', { }) // creating the component globally (if I don't add this line the app complains the component is not registered
////////////////
Vue.config.productionTip = false
let app;
Vue.use(vuefire)
firebase.auth().onAuthStateChanged(function(user){
if (!app) {
/* eslint-disable no-new */
app = new Vue({
el: '#app',
template: '<App/>',
components: { App, VueRangedatePicker },
router,
store,
VueRangedatePicker
})
}
})
Then on my component component_A.vue I am again importing the VueRangedatePicker plugin in the following manner:
<template>
<div>
<vue-rangedate-picker #selected="onDateSelected" i18n="EN" />
</div>
</template>
<script>
import firebase,{ itemRef } from '../firebase-config';
import VueRangedatePicker from 'vue-rangedate-picker'
export default {
firebase() {
return {
items: itemsRef,
}
},
name: 'component_A',
data () {
return {
}
},
created() {
console.log(VueRangedatePicker);
},
methods: {
onDateSelected: function (daterange) {
this.selectedDate = daterange
},
}
</script>
I know the plugin/component is registered because when I log the Vue Rangedate Picker on the console I can see the object
However I am getting the an error message like this
I have read the complete readme.md file on the project's github but I am still puzzled. What is Vue_Daterange_picker? Is it a plugin? Is it a component? Is it a plugin that allows me to build a component? I am quite confused. Can you clarify this for me a little better? How can I make this work?
This is because you have registered the component with an empty name.
In main.js :
Vue.component('DatePicker', VueRangedatePicker)
Then in your component use the component as :
<date-picker></date-picker>

Categories

Resources