How to Use Third Part Libraries like Vue3GoogleMap with Vue3 CDN Only - google-maps

I am trying to implement a google map in a WordPress website through Vue3 Cdn. Following is my code:
<script src="https://unpkg.com/vue#3/dist/vue.global.js"></script>
<script src="https://unpkg.com/vue3-google-map"></script>
<div id="app">
<div>
{{ message }}
<GoogleMap api-key="<API_KEY_HERE>" style="width: 100%; height: 500px" :center="center" :zoom="15">
<Marker :options="{ position: center }" />
</GoogleMap>
</div>
</div>
<script>
const {
createApp
} = Vue
const {
GoogleMap
} = Vue3GoogleMap
const {
Marker
} = Vue3GoogleMap
createApp({
data() {
return {
message: 'Hello Vue!'
}
},
components: {
GoogleMap,
Marker
},
}).mount('#app')
</script>
I am unable to figure out how to use third party packages like vue3-google-map in this case where libraries are imported through CDN in the website. Please guide. Thanks

Related

vue + pure html component?

how to implement vue-cli calling pure html method?
Please check below as sample file. because I have custom pure html code and facing difficulty converting it to vuejs.
product.vue
<template>
<custombutton #childclick="childclick" />
</template>
<script>
export default {
component: { custombutton },
methods: {
childclick(value) {
console.log(value)
}
}
}
</script>
custombutton.html
<html>
<body>
<button #click="childclick" />
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.6/vue.min.js"></script>
<script>
var App = new Vue({
el: '#app',
data() {
return {
vueMessage: 'testing vue message',
}
},
methods: {
childclick() {
this.$emit('childclick', 'success!')
}
},
});
</script>
</html>
Assuming you want to preserve the possibility to call Vue component from both .html file and .vue files, I would recommend moving your Vue logic from custombutton.html file into a separate custombutton.js file, which will export an object representing Vue component previously defined in HTML. You can then import custombutton.js both in custombutton.html and product.vue.
Example:
custombutton.js:
export default {
name: 'CustomButton',
template: '<div>Hello world!</div>'
}
custombutton.html:
<!DOCTYPE html>
<html>
<head>
<title>App</title>
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.14/dist/vue.js"></script>
</head>
<body>
<div id="app"></div>
<script type="module">
import CustomButton from "./custombutton.js"
new Vue({
el: '#app',
components: { CustomButton },
template: '<CustomButton />'
});
</script>
</body>
</html>
product.vue:
<template>
<CustomButton />
</template>
<script>
import CustomButton from "./custombutton.js"
export default {
components: { CustomButton }
}
</script>
Note that:
For custombutton.html to work target browsers should implement ECMAScript modules.
For product.vue to work you should set runtimeCompiler: true in your Vue CLI configuration. (Since the template in custombutton.js is defined as a string runtime compiler needs to be included in the final bundle.)
It is important to find a suitable location for custombutton.js so it can be imported easily using relative paths from both custombutton.html and custombutton.vue files.
Defining the template as a string in custombutton.js can be quite inconvenient, as you have no markup highlighting, however I don't see any workaround for this.
This solution is a bit more cumbersome, but allows template to be written with syntax highlighting into <script> element, which is more convenient than writing template as a string literal into a template property.
custombutton.js:
export default {
name: 'CustomButton',
data: function () {
return { testVar: 125 }
}
}
custombutton.component.html:
The template is now located in #custombutton-template element. "Hello world! 125" should be printed out.
<!DOCTYPE html>
<html>
<head>
<title>App</title>
<script src="https://cdn.jsdelivr.net/npm/vue#2.6.14/dist/vue.js"></script>
</head>
<body>
<script id="custombutton-template" type="x-template">
<div>Hello world! {{ testVar }}</div>
</script>
<div id="app"></div>
<script type="module">
import CustomButton from "./custombutton.js"
CustomButton.template = "#custombutton-template"
new Vue({
el: '#app',
components: { CustomButton },
template: '<CustomButton />'
});
</script>
</body>
</html>
product.vue: Thanks to Webpack config (see below) we are able to import contents of custombutton.component.html file as a string, parse it and get inner HTML of #custombutton-template element, which is the desired template.
<template>
<CustomButton />
</template>
<script>
import CustomButton from "./custombutton.js"
import CustomButtonComponent from "./custombutton.component.html"
var el = document.createElement("html")
el.innerHTML = CustomButtonComponent
var template = el.querySelector("#custombutton-template").innerHTML
CustomButton.template = template
export default {
components: { CustomButton }
}
</script>
Importing custombutton.component.html file as string is done by non-default Webpack raw-loader, therefore it is necessary to adjust Webpack config:
vue.config.js:
module.exports = {
runtimeCompiler: true,
configureWebpack: {
module: {
rules: [
{
test: /\.component\.html$/,
use: ["raw-loader"]
}
]
}
}
}
package.json:
{
"devDependencies": {
"raw-loader": "^4.0.2"
}
}

How to render a FontAwesome icon from a json file into a React Application?

Good evening,
I have the following JSON structure:
"Flow": [
{
"title": "Is your multicloud secure and scalable?",
"icon": "<FontAwesomeIcon className='my-icon' icon={faShieldCheck} />"
}
],
As you can see, it uses the React version of FontAwesome Pro. But I need to render this dynamically into a Component.
So far I've tried with different approaches. For example:
<div dangerouslySetInnerHTML={ { __html: item.icon } }></div>
Also tried this:
<div> { ReactHtmlParser(item.icon) } </div>
But no luck so far.
I would appreciate any new ideas on this matter.
Thanks in advance.
Remove the quotes in your json for icon.
In fact, just provide the name of the icon in the json and use require to import the icon while rendering FontAwesomeIcon.
Working demo
Code snippet
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
const myJson = {
Flow: [
{
title: "Is your multicloud secure and scalable?",
icon: "faHighlighter"
}
]
};
export default function App() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<FontAwesomeIcon
className="my-icon"
icon={require("#fortawesome/free-solid-svg-icons")[myJson.Flow[0].icon]}
/>
</div>
);
}
Note - below is cleaner code but it imports all icons before hand.
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
const icons = require("#fortawesome/free-solid-svg-icons");
const myJson = {
Flow: [
{
title: "Is your multicloud secure and scalable?",
icon: "faHighlighter"
}
]
};
export default function App() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<FontAwesomeIcon className="my-icon" icon={icons[myJson.Flow[0].icon]} />
</div>
);
}

Get the event response of script in WebView to the react native

I am using the html script for showing some module. Everthing was going perfect until I got no any response of the eventHandler. How can I get the response of the eventHandler in Web View.I am not getting any log of the onSuccess, onError or onClose methods. I am using react-native-webview. I tried using window.postMessage('onSuccess'); and geting the value on onMessage
this.khaltiUI = `<html>
<head>
<script src="https://khalti.com/static/khalti-checkout.js"></script>
</head>
<body>
<script>
var config = {
// replace the publicKey with yours
"publicKey": "test_public_key_dc74e0fd57cb46cd93832aee0a390234",
"productIdentity": "1234567890",
"productName": "Dragon",
"productUrl": "http://gameofthrones.wikia.com/wiki/Dragons",
"eventHandler": {
onSuccess (payload) {
window.postMessage('onSuccess');
console.log(payload);
},
onError (error) {
window.postMessage('onError')
console.log(error);
},
onClose () {
window.postMessage('onClosed')
console.log('widget is closing');
}
}
};
var checkout = new KhaltiCheckout(config);
checkout.show({amount: 1000, mobile: 9800000000});
</script>
</body>
</html>`
And in the react-native webView component:
<WebView
source={{html: this.khaltiUI }}
originWhitelist={["*"]}
scalesPageToFit={false}
style={{position: 'absolute', top: 0, bottom: 0, right: 0, left: 0}}
onMessage={this.onMessage}
startInLoadingState ={true}
/>
onMessage(event){
console.log('Hello'); //got no any response
console.log(JSON.parse(event.nativeEvent.data));
console.log(event.nativeEvent.data);
}
this what I use for sending data from webview to react-native:
react:
import React, { Component } from "react";
import { WebView } from "react-native-webview";
export default class App extends Component {
_bridge(event) {
if(event.nativeEvent.data == 'exit') {
BackHandler.exitApp();
}
}
render() {
return (
<WebView
style={{flex: 1}}
source={{ uri: "https://www.kende.com/" }}
onMessage={event => { this._bridge(event); }}
/>
);
}
}
html:
<script>
$( document ).ready(function() {
$('#exit').on('click', function(){
window.ReactNativeWebView.postMessage("exit");
});
});
</script>
<span id="exit">Exit</span>
To post data to a web page, first, you have to get the ref of WebView:
<WebView
ref={(webView) => this.webView = webView}
onMessage={this.onMessage}
...
/>
Then post a message like:
sendPostMessage() {
console.log("Sending post message");
this.webView.postMessage("Post message from react native");
}

Render Component in iframe using vuejs without src attribute

<iframe id="frame" width="100%" height="100%">
</ifrme>
I want to render component in this iframe. Is there any option of creating html element or rendering component in iframe?
new Vue({
el:'#frame',
store:store,
router:router,
render: component
})
The easiest way for me is to use srcdoc attribute. It loads raw html overriding src attribute.
<template>
<iframe :srcdoc="html"></iframe>
</template>
Update: More detail example: Consider a textarea for a user html input and want to display in an iframe.
<template>
<div id="app">
<textarea v-model="html"></textarea>
<iframe :srcdoc="html"></iframe>
</div>
</template>
<script>
export default {
name: "App",
data(){
return {
html:"<h1>Hello I am H1 block</h1>"
}
}
};
</script>
You can refer below link That helped me a lot.
Here is the link and the code snippets.
Vue.component('i-frame', {
render(h) {
return h('iframe', {
on: { load: this.renderChildren }
})
},
beforeUpdate() {
//freezing to prevent unnessessary Reactifiation of vNodes
this.iApp.children = Object.freeze(this.$slots.default)
},
methods: {
renderChildren() {
const children = this.$slots.default
const body = this.$el.contentDocument.body
const el = document.createElement('DIV') // we will mount or nested app to this element
body.appendChild(el)
const iApp = new Vue({
name: 'iApp',
//freezing to prevent unnessessary Reactifiation of vNodes
data: { children: Object.freeze(children) },
render(h) {
return h('div', this.children)
},
})
iApp.$mount(el) // mount into iframe
this.iApp = iApp // cache instance for later updates
}
}
})
Vue.component('test-child', {
template: `<div>
<h3>{{ title }}</h3>
<p>
<slot/>
</p>
</div>`,
props: ['title'],
methods: {
log: _.debounce(function() {
console.log('resize!')
}, 200)
},
mounted() {
this.$nextTick(() => {
const doc = this.$el.ownerDocument
const win = doc.defaultView
win.addEventListener('resize', this.log)
})
},
beforeDestroy() {
const doc = this.$el.ownerDocument
const win = doc.defaultView
win.removeEventListener('resize', this.log)
}
})
new Vue({
el: '#app',
data: {
dynamicPart: 'InputContent',
show: false,
}
})
https://jsfiddle.net/Linusborg/ohznser9/
I've tried and haven't found a way to mount vue directly on #iframe.
Yet, you can add div to #iframe and mount to that:
// create iframe element
var iframe = document.createElement('iframe')
iframe.id = 'iframe'
// place iframe inside page html
document.documentElement.insertBefore(iframe, document.querySelector('html').firstChild)
// append div to iframe
var container = document.createElement('div')
container.id = 'container'
iframe.contentWindow.document.body.appendChild(container)
// render vue component inside iframe on #container
new Vue({
el: container,
render: h => h(component)
})
Result:
<html>
<iframe id="iframe">
#document
<html>
<head>
</head>
<body><!-- <-- here was <div id="container"></div> -->
<div class="message" style="color: orange;">Hello from Vue component!</div>
</body>
</html>
</iframe>
<head>
</head>
<body>
</body>
</html>
P.s. I've used this code in chrome extension content scripts (javascript injected into pages). If you're going to use
it elsewhere make sure not to break Same-origin policy.
new Vue({
el:'#frame',
store:store,
router:router,
render: component
})
just try to give a name to your route view.
Hope it works

how do you render GoogleMaps API to a route-specific HTML Div element?

I'm using React Meteor 1.3 and this google maps package.
https://github.com/dburles/meteor-google-maps-react-example.
I can successfully render the map to a single page App, however as soon as I add routing to the mix - things stop working. Specifically when I move the element from an index html template to a JSX component that renders to the page - it breaks. I'm at a bit of a loss here and as the problem is quite vague (in my mind at least) I can't find an answer on google.
What's happening here? Does anyone have an example of this package working with flowrouter?
My current working set up looks like this.
Map.jsx
import React from 'react';
import ReactDOM from 'react-dom';
MyTestMap = React.createClass({
mixins: [ReactMeteorData],
componentDidMount() {
GoogleMaps.load();
},
getMeteorData() {
return {
loaded: GoogleMaps.loaded(),
mapOptions: GoogleMaps.loaded() && this._mapOptions()
};
},
_mapOptions() {
return {
center: new google.maps.LatLng(-37.8136, 144.9631),
zoom: 8
};
},
render() {
if (this.data.loaded)
return <GoogleMap name="mymap" options={this.data.mapOptions} />;
return <div>Loading map...</div>;
}
});
GoogleMap = React.createClass({
propTypes: {
name: React.PropTypes.string.isRequired,
options: React.PropTypes.object.isRequired
},
componentDidMount() {
GoogleMaps.create({
name: this.props.name,
element: ReactDOM.findDOMNode(this),
options: this.props.options
});
GoogleMaps.ready(this.props.name, function(map) {
var marker = new google.maps.Marker({
position: map.options.center,
map: map.instance
});
});
},
componentWillUnmount() {
if (GoogleMaps.maps[this.props.name]) {
google.maps.event.clearInstanceListeners(GoogleMaps.maps[this.props.name].instance);
delete GoogleMaps.maps[this.props.name];
}
},
render() {
return (
<div id="mapId" className="map-container"></div>
)
}
});
if (Meteor.isClient) {
Meteor.startup(function() {
return ReactDOM.render(<MyTestMap />, document.getElementById('root'));
});
}
And then I render this to an Index.html file - however this means that the map is on every page.
<head>
<title>googlemaps-react</title>
</head>
<body>
<div id="root"></div>
</body>
Thanks