I would like to send a mail when I click a button.
I have stored the mail I have to send it to in: localStorage.plMail
My problem is, this ain't worked in my vue.js
So I have to make it server side in a .js file. But I have no idea after researching how I can call a method from a .js file from my vue. I've tried to call the method from my index.js file in the store folder but as I said, no clue.
This is a part of my vue so far:
<template>
...
<td class="d-flex justify-content-around">
<button class="btn btn-danger btn-circle" type="button" #click="cancelMail(row)">
<!-- ❌ -->
<i class="fas fa-trash"></i>
</button>
<button class="btn btn-success btn-circle" type="button" #click="makeMail(row)">
<!-- ✅ -->
<i class="fas fa-check"></i>
</button>
</td>
...
</template>
<script>
export default {
name: "PlantsList",
components: { },
methods {
cancelMail(data) {
},
makeMail(data){
this.$store.dispatch('makeMail', data);
}
}
}
</script>
^That's not the whole code, it's shorten for good reasons.
This is how my folder structure looks like^
and this my mail logic:
const nodemailer = require('nodemailer');
const schedule = require('node-schedule');
var transporter = nodemailer.createTransport({
host: "**", // hostname
secure: false, // use SSL
port: **, // port for secure SMTP
tls: {
rejectUnauthorized: false
}
});
var mailOptions = {
from: 'anything#mail.com', // sender address
to: 'anything2#mail.com', // list of receivers
cc: '', // Comma separated list or an array
subject: 'test', // Subject line
html: '<b>Hello world </b>' // html body
};
const job = schedule.scheduleJob('45 * * * * *', function() {
transporter.sendMail(mailOptions, function(error, info) {
if (error) {
console.log("/sendmail error");
console.log(error);
//res.sendStatus(500);
return;
} else {
console.log("Message sent: " + info.response);line
socketTimeout: 30 * 1000 // 0.5 min: Time of inactivity until the connection is closed
transporter.close(); // shut down the connection pool, no more essages
//res.sendStatus(200);
}
transporter.close(); // shut down the connection pool, no more messages
});
})
Related
i am new to vue.js and neo4j. i tried using the Vue-neo4j connector - https://github.com/adam-cowley/vue-neo4j. But after implementing it according to the read.me file, when i click connect nothing happens nor are there errors in the console. could you help me out. i will paste my code below
Vue-neo4j version : 0.4.0
Neo4j version: 1.2.7
I imported the vue-neo4j in main.js file
Code -
<template>
<!-- ============ Body content start ============= -->
<div class="main-content">
<breadcumb :page="'Version 1'" :folder="'Dashboard'" />
<div>
<input v-model="protocol" />
<input v-model="host" />
<input v-model="port" />
<input v-model="username" />
<input v-model="password" />
<button #click="connect()">Connect</button>
</div>
</div>
<!-- ============ Body content End ============= -->
</template>
<script>
import { echartBar, echartPie } from "#/data/echarts";
import { echart1, echart2, echart3 } from "#/data/dashboard1";
export default {
metaInfo: {
// if no subcomponents specify a metaInfo.title, this title will be used
title: "Dashboard v1"
},
data() {
return {
protocol: "HTTP",
host: "localhost",
port: 7474,
username: "neo4j",
password: "aqt123",
};
},
methods: {
connect() {
return this.$neo4j.connect(
this.protocol,
this.host,
this.port,
this.username,
this.password,
);
},
driver() {
// Get a driver instance
return this.$neo4j.getDriver();
},
testQuery() {
// Get a session from the driver
const session = this.$neo4j.getSession();
this.$neo4j.desktop.connectToActiveGraph().then(driver => {
this.onConnect(driver);
});
session
.run("MATCH (n) RETURN count(n) AS count")
.then(res => {
console.log(res.records[0].get("count"));
})
.then(() => {
session.close();
});
}
}
};
</script>
<style>
.echarts {
width: 100%;
height: 100%;
}
</style>
In this example you are running the connect method but you aren't actually updating the state of your application afterwards. this.$neo4j.connect returns a Promise that you could use to set a property in the component and then change the UI based on that. Or if you are using vue-router, you could redirect the user to a new route when connected.
You could add a driver and error property to the component:
data() {
return {
protocol: "HTTP",
host: "localhost",
port: 7474,
username: "neo4j",
password: "aqt123",
driver: undefined,
error: undefined,
}
}
Then once the driver has connected successfully set the driver:
return this.$neo4j.connect(
this.protocol,
this.host,
this.port,
this.username,
this.password
)
.then(driver => this.driver = driver)
.catch(e => this.error = e)
Then in the template you could do something like this to change the UI based on whether the driver has been set or not:
<div v-if="!driver">
<!-- display any connection error -->
<div v-if="error">{{ error }}</div>
<input v-model="protocol" />
<input v-model="host" />
<input v-model="port" />
<input v-model="username" />
<input v-model="password" />
<button #click="connect()">Connect</button>
</div>
<div v-else>
<!-- show something different after the driver has been set -->
The driver has been set!
</div>
I am very new with vuejs and recently started to try to replace some old jquery code that I have and make it reactive with vuejs. The thing is I have a component that gets information from a nodejs server via socket.io asynchronously.
When I get the data and update my component's data I see the changes when I console log it but it does not change the DOM the way I want it to do.
What is the proper way to grab data asynchronously and use it inside a component? I post some parts of my code so you can see it. I will appreciate any advice you can give me. Thanks in advance!
Vue.component('chat', {
data() {
return {
chat: null,
commands: [],
chatOpened: false,
}
},
props: [
'io',
'messages',
'channels',
'connectChat',
'roomChat',
'user',
'userId',
'soundRoute',
],
methods: {
openChat() {
this.chatOpened = true;
},
closeChat() {
this.chatOpened = false;
},
},
created() {
this.chat = this.$io.connect(this.connectChat);
this.commands.push('clear');
let self = this;
$.each(this.channels, function(index, value) {
self.chat.emit('join', {room: index, user: self.user, userId: self.userId}, function(err, cb) {
if (!err) {
users = cb.users;
messages = cb.messages;
if (messages.length > 0) {
self.channels[index].loaded = true;
}
//some more code
}
});
});
console.log(this.channels);
},
template: `
<div>
<div id="container-chat-open-button" #click="openChat" :class="{hide : chatOpened}">
<div>+90</div>
<i class="fas fa-comment-alt"></i>
</div>
<div id="container-chat" class="chat__container" :class="{open : chatOpened}">
<div id="container-chat-close-button" #click="closeChat">
<span>
<div>
<i class="fas fa-comment-alt"></i>
#{{ messages.chat_lobby_icon_title }}
</div>
<i class="icon-arrowdown"></i>
</span>
</div>
<div id="alert-chat" class="chat__container-notifications animated flash"></div>
<div class="row">
<ul>
<li v-for="channel in channels" v-show="channel.loaded === true">Channel loaded</li>
</ul>
</div>
</div>
</div>
`
});
I would expect to see the list of channels with messsages but instead I don't see the list even thought I see my channels with the loaded attribute set to true (by default they all have this attribute set to false).
My guess is that it's this part that is not working as expected.
if (messages.length > 0) {
self.channels[index].loaded = true;
}
The reactive way of doing this is by setting the full object again.
Vue.set(self.channels, index, {
...self.channels[index],
loaded: true
}
EDIT 1:
this.channels.forEach((channel) => {
this.chat.emit('join', {room: index, user: self.user, userId: self.userId}, (err, cb) => {
if (!err) {
users = cb.users;
messages = cb.messages;
if (messages.length > 0) {
Vue.set(self.channels, index, {
...self.channels[index],
loaded: true
}
}
//some more code
}
});
})
You'll need to add support for the rest-spread-operator using babel.
I try to add a Vue socket cluster connection inside a method rather than at startup. Here is the result of my research. I see several issues. I added the connection directives inside a method called connect(), this method is called by a click from another component. It works, but then, there is an issue with the event listeners. I have tried to add one using Vue.extend to add it to the connection but it blocks any update made on the component. For example, in my code, I added this.msg="this is a test"; but the msg mutation does not work after I added the event listeners.
I have also tried to add the event listeners using this.$options.SeoScanEvents.nameofwebsocketmessage as an alternative to vue.extend but it does work at all.
This code uses the structure of the dummy vue.js application. So if you want to replicate this issue, you just have to install the dummy structure of a VUEJS app, then replace main.js and HelloWorld.vue with the following. Then you need the default server.js and worker.js from socketcluster.io to run on port 8000. It should return a random number.
main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import VueSocketCluster from 'vue-socket-cluster'
Vue.config.productionTip = false
/* eslint-disable no-new */
const vm = new Vue({
el: '#app',
router,
components: { App },
template: '<App/>',
SeoScanEvents:{
connect: function(data){ // I added it here to see in vm object if I could replicate the property. For sure it does not work because it comes before the connection directives.
console.log('socket connected')
console.log(data)
},
// ['error','connect','disconnect','connectAbort','connecting', etc ...] See socket cluster docs
error () {
//An error occurred on the connection name echo
},
connecting () {
},
// ...
// for hyphen separated events such as 'custom-error' use ...
customError () {
},/*
random(data){
console.log(data)
}*/
},
methods:{
connect(){
Vue.use(VueSocketCluster, {
connections: [{
name: 'SeoScan',
hostname: 'localhost',
secure: false,
port: 8000,
rejectUnauthorized: false
}]
})
var Comp = Vue.extend({
SeoScanEvents:{
random: function(data){
console.log(data);
}
}
});
new Comp().$mount('#app'); // this works but it blocks any updates on my vue component for example the this.msg=... below does not work
console.log(this);
/*
this.$options.SeoScanEvents.random = function random(data) { // this does not work
console.log(data) // should show the random numbers generated by the default server config file from Socket Cluster
}
*/
}
}
});
HelloWorld.vue
<template ref="gogo">
<div class="hello">
<h1>{{ msg }}</h1>
<h2 #click="submit1">Essential Links</h2>
<ul>
<li>
<a
href="https://vuejs.org"
target="_blank"
>
Core Docs
</a>
</li>
<li>
<a
href="https://forum.vuejs.org"
target="_blank"
>
Forum
</a>
</li>
<li>
<a
href="https://chat.vuejs.org"
target="_blank"
>
Community Chat
</a>
</li>
<li>
<a
href="https://twitter.com/vuejs"
target="_blank"
>
Twitter
</a>
</li>
<br>
<li>
<a
href="http://vuejs-templates.github.io/webpack/"
target="_blank"
>
Docs for This Template
</a>
</li>
</ul>
<h2>Ecosystem</h2>
<ul>
<li>
<a
href="http://router.vuejs.org/"
target="_blank"
>
vue-router
</a>
</li>
<li>
<a
href="http://vuex.vuejs.org/"
target="_blank"
>
vuex
</a>
</li>
<li>
<a
href="http://vue-loader.vuejs.org/"
target="_blank"
>
vue-loader
</a>
</li>
<li>
<a
href="https://github.com/vuejs/awesome-vue"
target="_blank"
>
awesome-vue
</a>
</li>
</ul>
</div>
</template>
<script>
var message = 'Vue.js is rad';
export default {
name: 'HelloWorld',
data () {
return {
msg: message,
myArray: []
}
},
methods:{
submit1(){
console.log(this);
this.msg="this is a test"; // this does not work when I add the event listeners using Vue.extend
console.log(new Date())
this.$root.connect(); // trigger Vue Socket cluster connection
}
},
mounted(){
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
The right solution would be to
Create a vue.use for the connection with autoConnect: false below import VueSocketCluster from 'vue-socket-cluster'
> Vue.use(VueSocketCluster, {
> connections: [{
> name: 'SeoScan', // Each connection object must have a name and the name must be unique in the array
> hostname: 'localhost',
> secure: false,
> port: 5128,
> rejectUnauthorized: false,
> autoConnect: false
> }]
> });
then, add in your components (here HelloWorld.vue) the event listeners under export default
SeoScanEvents: {
connect: function (data) {
console.log('socket connected')
console.log(data)
},
random (data) {
console.log(data)
}
}
In the method submit1 rather than calling the method connect from the root, call the method that will start the connection: this.$SeoScanClient.connect();
I want to update a placeholder (currentUsername) asynchronously with an actual value after loading/rendering the page.
I tried following a sample project (https://github.com/jackfranklin/vue2-demo-proj), but I can't correlate it with my setup. Using vuejs 2.0.
I can see the event is triggered, the call is made and something's returned, I've got no errors on my Chrome console, but nothing is updated in the UI. Why is that?
1) html file:
<script src="assets/js/data.js"></script>
2) data.js:
"use strict";
import * as DataXXX from './data.vue';
Vue.component("dataxxx", DataXXX);
var vm = new Vue({
el: "#app",
});
3) data.vue
<template>
<div>
<p v-if="currentUsername == null">
Null username
</p>
<p v-else>
Username: {{ currentUsername }}:
</p>
</div>
</template>
<script>
"use strict";
export default
{
created()
{
awr.EventsBus.$on("requestLoadData", this.loadData);
awr.EventsBus.$emit("requestLoadData", this.loadData);
},
destroyed()
{
awr.EventsBus.$off("requestLoadData", this.loadData);
},
methods:
{
loadData(name)
{
alert("got event");
this.currentUsername = name;
this.fetchGithubData(name);
},
fetchGithubData(name)
{
const url = "http://127.0.0.1/getUsername.php";
alert("requesting url: " + url);
fetch(url).then(response => response.text()).then(data => {
this.currentUsername = data;
console.log("got response: " + data);
});
}
},
data() {
return {
currentUsername: null
}
}
}
</script>
The if isn't re-evaluated when you get the response, so the placeholder isn't included in the page.
This line DOES update it, but it's just not shown: this.currentUsername = data;
Change it to something like:
<div>
Username: {{ currentUsername }}
</div
I have got next Vue component.
Login as calling Login function.
checkAuth -- is calling checking Authorization status between page refresh.
But how I can call checkAuth without pushing on button?
var GuestMenu = Vue.extend({
props: ['username', 'password'],
template: `
<div id="auth">
<form class="form-inline pull-right">
<div class="form-group">
<label class="sr-only" for="UserName">User name</label>
<input type="username" v-model="username" class="form-control" id="UserName" placeholder="username">
</div>
<div class="form-group">
<label class="sr-only" for="Password">Password</label>
<input type="password" v-model="password" class="form-control" id="Password" placeholder="Password">
</div>
<button type="submit" class="btn btn-default" v-on:click.prevent="sendLoginInfo()">LOGIN</button>
<button type="submit" class="btn btn-default" v-on:click.prevent="checkAuth()">CheckAuth</button>
</form>
</div>`,
methods: {
//hash key-value
sendLoginInfo: sendLoginInfo, // key (anyname) | value -> calling function name (from separate file)
//calling without brackets because we do need return from function, we need just function
checkAuth: checkAuth // restore authorization after refresh page if user already have session!
}
});
I tried to call it's from App:
App = new Vue({ // App -- is need for overwrite global var. Global var need declarated abobe all function, because some it's function is calling from outside
el: '#app',
data: {
topMenuView: "guestmenu",
contentView: "guestcontent",
username: "",
password: "",
},
ready: function() {
checkAuth(); // Here
}
}
)
But it's look like it's calling when not all components are loaded,
function checkAuth() {
// we should NOT send any data like: loginData because after refreshing page
// all filds are empty and we need to ask server if he have authorize session
console.log("Checking if user already have active session");
this.$http.post('http://127.0.0.1:8080/checkAuthorization').then(function(response) {
console.log("server response: ", response.data)
}
}
// ...
}
Here I am getting error:
authorization.js:69 Uncaught TypeError: Cannot read property 'post' of undefined
I tried to do:
{
// ...
methods: { //hash key-value
sendLoginInfo : sendLoginInfo, // key (anyname) | value -> calling function name (from separate file)
//calling without brackets because we do need return from function, we need just function
},
ready()
{
checkAuth()
}
// ...
}
But again got error:
Uncaught TypeError: Cannot read property 'post' of undefined
What I am doing wrong?
Let see mounted() I think it is help
https://v2.vuejs.org/v2/api/#mounted
// vue js provides us `mounted()`. this means `onload` in javascript.
mounted () {
// we can implement any method here like
sampleFun () {
// this is the sample method you can implement whatever you want
}
}
If you need run code after 100% loaded with image and files, test this in mounted():
document.onreadystatechange = () => {
if (document.readyState == "complete") {
console.log('Page completed with image and files!')
// fetch to next page or some code
}
}
More info: MDN Api onreadystatechange
You can use the mounted() Vue Lifecycle Hook. This will allow you to call a method before the page loads.
This is an implementation example:
HTML:
<div id="app">
<h1>Welcome our site {{ name }}</h1>
</div>
JS:
var app = new Vue ({
el: '#app',
data: {
name: ''
},
mounted: function() {
this.askName() // Calls the method before page loads
},
methods: {
// Declares the method
askName: function(){
this.name = prompt(`What's your name?`)
}
}
})
This will get the prompt method's value, insert it in the variable name and output in the DOM after the page loads. You can check the code sample here.
You can read more about Lifecycle Hooks here.
You import the function from outside the main instance, and don't add it to the methods block. so the context of this is not the vm.
Either do this:
ready() {
checkAuth.call(this)
}
or add the method to your methods first (which will make Vue bind this correctly for you) and call this method:
methods: {
checkAuth: checkAuth
},
ready() {
this.checkAuth()
}
Vue watch() life-cycle hook, can be used
html
<div id="demo">{{ fullName }}</div>
js
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
})
You can call a function on load like this:
methods:{
checkAuth: function() {your logic here}
},
mounted(){
this.checkAuth()
},