Vue.js call method from dynamic html - javascript

I have a block of html that is sent down from the server, and I want to call a method or function from links embedded in that html.
in my .vue file, the html is being displayed like so:
<template>
<div v-html="myhtml"></div>
</template>
<script>
import axios from 'axios'
export default {
data () {
return {
myhtml: null
}
},
created () {
this.refreshHTML()
},
methods: {
refreshHTML () {
axios.get()// get my html
this.myhtml = response.data
},
myFunction () {
//do my function stuff here...
}
}
}
</script>
And what I would like to do in the html that is fetched is attach an onclick event that fires my function like so:
<a href="myurl" onclick='event.preventDefault();myFunction(this.href);'>link</a>
But when I try, I get:
ReferenceError: Can't find variable: myFunction

This screams bad practice all over the place.
If I HAD to do this:
I'd add the function to the global scope (bad practice), and call it from the html event handler (also bad practice):
<template>
<div v-html="myhtml"></div>
</template>
<script>
import axios from 'axios'
export default {
data () {
return {
myhtml: null
}
},
created () {
this.refreshHTML();
window.myFunction = this.myFunction.bind(this);
},
methods: {
refreshHTML () {
axios.get()// get my html
this.myhtml = response.data
},
myFunction () {
//do my function stuff here...
}
}
}
</script>
Consider converting the html into vue components and use them instead.

Related

How to call the function in a separate JS file through a vue instances [duplicate]

This question already has answers here:
"Uncaught SyntaxError: Cannot use import statement outside a module" when importing ECMAScript 6
(31 answers)
Closed 1 year ago.
I have a javascript function in a separate js file toaster-message.js, the file is in wwwroot/js of ASP.net application, which calls the bootstrap toaster.
toaster-message.js.
showCompleteToast: (message) => {
const toastElm = document.getElementById('#complete-toast');
const toast = new bootstrap.Toast(toastElm)
toast.show();
}
I want to call the showCompleteToast() from my vue instances. I am creating the vue instances with Direct script Include.
I don't want to add any Vue dependency to the function outside the Vue instances. So what is the proper way to call the function in the external js file that is outside the Vue instances?
#section scripts {
<script>
const app = new Vue({
el: "#app",
data() {
return {
}
},
methods: {
showToast: function(){
//I want to call the show toast from here
},
submit: async function () {
try {
this.showToast();
} catch (error) {
console.log(error)
}
}
}
});
</script>
}
When i try to import using:
import { showCompleteToast } from "~/lib/js/toater-message.js"
while using:
export default {
showCompleteToast: (message) => {
const toastElm = document.getElementById('#complete-toast');
const toast = new bootstrap.Toast(toastElm)
toast.show();
},
// ... other methods here
};
I get the error as:
“Uncaught SyntaxError: Cannot use import statement outside a module”
I tried to to import using:
<script type="module">
import { showCompleteToast } from "../../wwwroot/js/toaster-message.js"
alert(showCompleteToast)
</script>
This gave the error as:
GET https://localhost:44307/wwwroot/js/toaster-message.js net::ERR_ABORTED 404
I'm not very familiar with php but typically you can import JavaScript files and then work with their contents. The only requirement is that the imported files need to have exporting defined.
// toaster-message.js
export default {
showCompleteToast: (message) => {
const toastElm = document.getElementById('#complete-toast');
const toast = new bootstrap.Toast(toastElm)
toast.show();
},
// ... other methods here
};
Then pull it into your Vue file like this:
#section scripts {
<script>
import { showCompleteToast } from "..path/to/toaster-message.js"
const app = new Vue({
el: "#app",
data() {
return {
}
},
methods: {
showToast: function(){
//I want to call the show toast from here
showCompleteToast();
},
submit: async function () {
try {
this.showToast();
} catch (error) {
console.log(error)
}
}
}
});
</script>
}

Calling VueJS Components after login from an external script

I have a VueJS Program where I want to provide a login. Thus this login is used one multiple platforms, it is loaded via an external server (See: mounted). It is loaded, puts elements into the mainlogin-div creating a login view and when the user clicks Login it performs a http login request to another server. When the login is successful, the external script calls done(result) or error(result) whether the login was a success or not.
But now of course how can I go back to calling Vue-stuff from there? I cant just do like this.$router.push("/coolPath") or call a defined method like loggedIn to make a toast or what not... How is this implemented?
<template>
<div id="main">
<div id="mainlogin"></div>
<script type="application/javascript">
function done(result){
console.log(result);
loggedIn(result, true)
}
function error(result) {
console.log(result)
loggedIn(result, false)
}
</script>
</div>
</template>
<script>
const Toast = require("#/toast/toast")
export default {
name: "Login",
components: {},
data() {
return {
isAuthenticated: false
}
},
beforeMount() {
let loginScript = document.createElement('script')
loginScript .setAttribute('src', 'http://**.***.***.***/index_krass.js')
document.body.appendChild(loginScript )
},
methods: {
loggedIn: function (result, success){
Toast.toast(result.message, success)
}
}
}
</script>
<style>
...
</style>
Error is always "this." is not defined or loggedIn(...) is not defined...
Maybe its some race condition where VueJS needs to be loaded first or the other way around?
Instead of the <script> block in the template, just set the global functions up on window as arrow functions to capture the Vue instance context:
export default {
beforeMount() {
window.done = result => this.loggedIn(result, true)
window.error = result => this.loggedIn(result, false)
let loginScript = document.createElement("script")
loginScript.setAttribute("src", ".../index_krass.js")
document.body.appendChild(loginScript)
},
destroyed() {
window.done = window.error = undefined
},
}
demo

unable to use $off and passing parameters in eventbus in Vue

In main.js i created the eventBus
Vue.prototype.$eventHub = new Vue()
And in component1
this.$eventHub.$emit('logged-in')
In component2, i tried this
beforeMount () {
this.$eventHub.$on('logged-in', function () {
console.log("logged in")
})
},
beforeDestroy() {
this.$eventHub.$off('logged-in')
}
It is not printing any thing in the console. If i remove this.$eventHub.$off('logged-in') it is working fine, but it is executing number of times that$emit is executed. What am i doing wrong here? why $off is not working?
Unable to pass the parameters as well
trying to send message using $emit
this.$eventHub.$emit('logged-in', "some message")
in $on
this.$eventHub.$on('logged-in', this.testEvent)
The test event method looks
testEvent (params) {
console.log(params)
}
The params shows undefined.
But if i do this, it is working fine
this.$eventHub.$on('logged-in', (params) => {
console.log(params)
})
How can i pass parameters to the method?
You should pass a reference to $off
beforeMount () {
this.$eventHub.$on('logged-in', this.onEventHandler)
},
beforeDestroy() {
this.$eventHub.$off('logged-in', this.onEventHandler)
},
methods: {
onEventHandler () {
console.log("logged in")
}
}

ExtJS call funtion of another component

I created a Ext.Mixin component and would like to call a function of it from another component. How do I have to do that? Must be very obvious, but I can't see right now.
EDIT:
Ext.define('ABC.mixin.MyMixin', {
extend: 'Ext.Mixin',
mixinConfig: {
after: {
},
before: {
initComponent: 'init'
}
},
init: function () {
let me = this;
myfunction();
},
myfunction: function () {
//do stuff
}
}
How do I call myfunction() ?
When you include a mixin to a component all of the functions the mixin provides are included to the component itself.
So when you have a reference to your created component you cann call the function on the component itself.
Ext.define('ABC.mixin.MyMixin', {
extend: 'Ext.Mixin',
myfunction: function () {
//do stuff
}
});
Ext.define('ABC.view.MyView', {
mixins: ['ABC.mixin.MyMixin'],
// ...other config stuff
});
let myView = Ext.create('ABC.view.MyView'); // concreate Object of the class ABC.view.MyView
myView.myfunction(); // we can call the function of the mixin on the Object directly.
For more information see the ExtJs documentation
The API Docs seem to provide the information you need. You just include your mixin in the component you need, like so:
Ext.define('ABC.view.MyComponent', {
mixins: ['ABC.mixin.MyMixin'],
initComponent() {
this.myfunction();
this.callParent();
}
});
And from the component's scope, call the mixin's functions you need

Vuejs global function with Google Auth Signin

I am using vuejs 2 and I am having issues with using the Google auth signin.
I successfully setup and got the sign out and user profile functions working using vue:
export default {
data() {
return {
user: null
};
},
methods: {
getUserProfile() {
const profile = gapi.auth2.currentUser.get().getBasicProfile();
console.log(profile.getIdToken());
},
signOut() {
const auth2 = gapi.auth2.getAuthInstance();
auth2.signOut().then(function () {
console.log('user signed out');
});
}
},
};
My main issue here is the onSignIn(googleUser) function from
<div class="g-signin2" data-onsuccess="onSignIn"></div>
The data-onsuccess="onSignIn" is looking for a js function outside the vue instance.
I tried adding the onSignIn(googleUser) function in my HTML file like:
<script>
function onSignIn(googleUser) {
const auth2 = gapi.auth2.init();
if (auth2.isSignedIn.get()) {
const profile = auth2.currentUser.get().getBasicProfile();
console.log(profile.getName());
console.log(googleUser.getAuthResponse().id_token);
console.log(googleUser.getAuthResponse().uid);
console.log(auth2.currentUser.get().getId());
}
}
</script>
This works as expected, but I wanted to know if it would be possible to add this in my vue file instead of a native javascript way, since inside this function, I will be calling other vue methods.
Or is there a way where I could add the onSignIn(googleUser) function in vue and then call it when Google Auth finishes?
The solution here is to use gapi.signin2.render to render the sign-in button inside your component's mounted hook
<template>
<div id="google-signin-btn"></div>
</template>
<script>
export default {
methods: {
onSignIn (user) {
// do stuff, for example
const profile = user.getBasicProfile()
}
},
mounted() {
gapi.signin2.render('google-signin-btn', { // this is the button "id"
onsuccess: this.onSignIn // note, no "()" here
})
}
}
</script>
See https://developers.google.com/identity/sign-in/web/reference#gapisignin2renderid_options

Categories

Resources