How to send params form web page to parse cloud function? - javascript

I make a web form to add some string to database and now my add function is running perfectly but my web does not send params to function when i click submit and console log send undefined to me i dont know what to do please help and thank you
Here my function code and run perfectly
Parse.Cloud.define('addSynonym', function (request, response) {
var SYN = Parse.Object.extend("Synonym");
var CommonwordFromUser = request.params.common_word;
var SynonymwordFromUser = request.params.synonym_word;
console.log(CommonwordFromUser);
console.log(SynonymwordFromUser);
if (CommonwordFromUser == null || SynonymwordFromUser == null) {
response.error("request null values");
} else {
var query = new Parse.Query(SYN)
query.find({
success: function (synResponse) {
var synOBJ = new SYN();
synOBJ.set("common_word", CommonwordFromUser);
synOBJ.set("synonym_word", SynonymwordFromUser);
synOBJ.save(null, {
success: function (success) {
response.success({
"common_word": CommonwordFromUser,
"synonym_word": SynonymwordFromUser
});
},
error: function (error) {
response.error("save failed : " + error.code);
}
});
}
})
}
});
Here my web form my problem
<form id="contact" class="registerForm">
<div class="alert alert-success" id="alertbox">
<strong>Success!</strong> Your Synonym has uploaded.
</div>
<div class="text-center">
<img src="img/icon.png" class="text-center" alt="Responsive image" width="90" height="90">
</div>
<h3 class="text-center font-weight-normal">Welcome to synonym Menu</h3>
<label id="label-tags" for="ask-tags">Common Word :</label>
<fieldset class="form-group">
<input id="common_word" name="common_word" placeholder="Please type some word" type="text" tabindex="1" required>
</fieldset>
<label id="label-tags" for="ask-tags">Synonym Word :</label>
<fieldset class="form-group">
<input id="synonym_word" name="synonym_word" placeholder="Please type some word" type="text" tabindex="2"
required>
</fieldset>
<fieldset class="form-group">
<button name="submit" type="submit" onclick="submitfrom()" id="contact-submit">Submit</button>
</fieldset>
</form>
</div>
<!-- jQuery -->
<script src="js/jquery.js"></script>
<!-- Bootstrap Core JavaScript -->
<script src="js/bootstrap.min.js"></script>
<script src="js/standalone/selectize.min.js"></script>
<script src="js/bootstrapValidator.min.js"></script>
<script>
$('.registerForm').bootstrapValidator({
message: 'This value is not valid',
feedbackIcons: {
valid: 'glyphicon glyphicon-ok',
invalid: 'glyphicon glyphicon-remove',
validating: 'glyphicon glyphicon-refresh'
},
fields: {
common_word: {
validators: {
notEmpty: {
message: 'Require !!'
}
}
},
synonym_word: {
validators: {
notEmpty: {
message: 'Require !!'
}
}
},
}
}).on('success.form.bv', function (e) {
submitfrom();
});
$('#alertbox').hide();
function submitfrom() {
var common_word = $('#common_word').val();
var synonym_word = $('#synonym_word').val();
var obj = [{
"common_word": common_word,
"synonym_word": synonym_word,
}];
var data = '{"objects":' + JSON.stringify(obj) + '}';
callParseServerCloudCode("addSynonym", data, function (response) {
if (response) {
console.log(response);
alert("🤖:Ok !");
location.reload();
}
});
$(this).scrollTop(0);
$('.registerForm').data('bootstrapValidator').resetForm();
$('#alertbox').show();
$('#alertbox').fadeTo(2000, 500).slideUp(500, function () {
$('#alertbox').hide();
});
}
function callParseServerCloudCode(methodName, requestMsg, responseMsg) {
var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://xxxxxxxxxxxx.herokuapp.com/parse/functions/' + methodName, true);
xhr.setRequestHeader('Content-type', 'application/json');
xhr.setRequestHeader('X-Parse-Application-Id', 'myAppId');
xhr.setRequestHeader('X-Parse-Master-Key', 'myMasterKey');
xhr.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var myArr = JSON.parse(this.responseText);
responseMsg(myArr.result);
}
};
xhr.send(requestMsg);
}
</script>
</body>
</html>

Option 1:
Just change the lines below and it should work
var obj = {
"common_word": common_word,
"synonym_word": synonym_word,
};
var data = JSON.stringify(obj);
Option 2 (recommended):
Install Parse JS SDK: https://docs.parseplatform.org/js/guide/#getting-started
Call cloud code like this:
Parse.Cloud.run(
"addSynonym",
{
"common_word": common_word,
"synonym_word": synonym_word
}
).then(
function() {
console.log('success');
},
function (error) {
console.error(error);
}
);

Related

Failed to set the 'value' property on 'HTMLInputElement':

If I upload a PDF or a picture to the form, I get the following error message when changing to another form field:
The upload function is done using the following JavaScript:
;(function($,window) {
$.plugin('OnacyUpload', {
defaults: {
fileUpload: '#register_license_upload',
fileText: '.register-upload-file-text',
registerContent: '.register--content.registration-upload-finished',
registerLogin: '.register--login',
sidebar: 'aside.sidebar-main',
breadcrumb: 'nav.content--breadcrumb'
},
init: function() {
var me = this;
me._on(me.opts.fileUpload, 'change', $.proxy(me.onUploadChange, me));
me._on(me.opts.fileText, 'click', $.proxy(me.fileTextClicked, me));
if ( $(me.opts.registerContent).length ) {
$(me.opts.registerLogin).remove();
$(me.opts.sidebar).remove();
$(me.opts.breadcrumb).remove();
}
},
fileTextClicked: function() {
$(me.opts.fileUpload).trigger('click');
},
onUploadChange: function(event) {
var me = this,
$target = $(event.target),
$fileText = $(me.opts.fileText),
value = $target.val();
if ( typeof value !== 'string' || value === '' ) {
$fileText.html($fileText.attr('data-no-file-text'));
}
else {
var list = value.replace(/\\/g, '/').split('/');
$fileText.html(list[list.length-1]);
}
}
});
window.StateManager.addPlugin('body', 'OnacyUpload');
Here is the HTML Part:
<div class="panel--body is--wide"> <input type="file" id="register_license_upload" name="register_license_upload" accept="image/png, image/jpeg, application/pdf"> <label for="register_license_upload" class="btn is--secondary"> Datei aussuchen </label> <span class="register-upload-file-text" data-no-file-text="Datei wählen"> Datei wählen </span> </div>

AWS API gateway unreacheable from S3 webpage

I am trying to add a form contact to a AWS S3 static web page with API Gateway, Lambda and SES
I checked and followed many guides, so far the API gateway and Lambda together can send email properly. I even tested successfully with postman APP in my home computer.
I guess the form webpage script does not called or it is bad created, please help on check it. The form does not received fail response only reset itself.
This is AWS lambda function
var AWS = require('aws-sdk');
var ses = new AWS.SES();
var RECEIVER = 'xxxxx#gmail.com';
var SENDER = 'xxxxx#gmail.com';
var response = {
"isBase64Encoded": false,
"headers": { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*'},
"statusCode": 200,
"body": "{\"result\": \"Success.\"}"
};
exports.handler = function (event, context) {
console.log('Received event:', event);
sendEmail(event, function (err, data) {
context.done(err, null);
});
};
function sendEmail (event, done) {
var params = {
Destination: {
ToAddresses: [
RECEIVER
]
},
Message: {
Body: {
Text: {
Data: 'name: ' + event.name + '\nphone: ' + event.phone + '\nemail: ' + event.email + '\ndesc: ' + event.desc,
Charset: 'UTF-8'
}
},
Subject: {
Data: 'Website Referral Form: ' + event.name,
Charset: 'UTF-8'
}
},
Source: SENDER
};
ses.sendEmail(params, done);
}
the form webpage that it called AWS function is
<html>
<head>
</head>
<body>
<form id="contact-form" method="post">
<h4>Name:</h4>
<input type="text" style="height:35px;" id="name-input" placeholder="Enter name here" class="form-control" style="width:100%;" /><br/>
<h4>Phone:</h4>
<input type="phone" style="height:35px;" id="phone-input" placeholder="Enter phone number" class="form-control" style="width:100%;"/><br/>
<h4>Email:</h4>
<input type="email" style="height:35px;" id="email-input" placeholder="Enter email here..." class="form-control" style="width:100%;"/><br/>
<h4>How can we help you?</h4>
<textarea id="description-input" rows="3" placeholder="Enter your message..." class="form-control" style="width:100%;"></textarea><br/>
<div class="g-recaptcha" data-sitekey="6Lc7cVMUAAAAAM1yxf64wrmO8gvi8A1oQ_ead1ys" class="form-control" style="width:100%;"></div>
<button type="button" onClick="submitToAPI(event)" class="btn btn-lg" style="margin-top:20px;">Submit</button>
</form>
</body>
<script>
function submitToAPI(e) {
e.preventDefault();
var URL = "https://"awsdata".amazonaws.com/probado/sndemail";
var name = document.getElementById("name-input").value;
var phone = document.getElementById("phone-input").value;
var email = document.getElementById("email-input").value;
var desc = document.getElementById("description-input").value;
if (name=="" || phone=="" || email=="" || desc=="")
{
alert("Please Fill All Required Field");
return false;
}
nameRE = /^[A-Z]{1}[a-z]{2,20}[ ]{1}[A-Z]{1}[a-z]{2,20}/;
if(!nameRE.test(name)) {
alert("Name entered, is not valid");
return false;
}
phoneRE = /^([0|\+[0-9]{1,5})?([7-9][0-9]{9})$/;
if(!phoneRE.test(phone)) {
alert("Phone number entered, is not valid");
return false;
}
emailRE = /^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/;
if(!emailRE.test(email)) {
alert("Email Address entered, is not valid");
return false;
}
var data = {
name : name,
phone : phone,
email : email,
desc : desc
};
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", "<URL for API gateway>");
xmlhttp.setRequestHeader("Content-Type", "application/json");
xmlhttp.send(JSON.stringify(data));
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState === 4) {
var response = JSON.parse(xmlhttp.responseText);
if (xmlhttp.status === 200 ) {
console.log('successful');
document.getElementById("contact-form").innerHTML = "<h1>Thank you for your message/feedback<br>our team will get back to you soon!</h1>";
} else {
console.log('failed');
}
}
}
document.getElementById('contact-form').reset();
}
</script>
</html>
API Gateway CORS
The form has to be inside the body and put the script inside the head...
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js">
</script>
<script> your own script like the one above... </script>
</head>
<body>
<form> user form... </form>
</html>

Sending static data using bootstrapValidator locally

how to use a remote back-end to check if a given username is already taken or not.
check and validate locally without using database or web-server
This is latest version of bootstrapValidator, jquery, html5, bootstrap.
<script src="js/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.bootstrapvalidator/0.5.2/js/bootstrapValidator.min.js"></script>
<form id="registrationForm" class="form-horizontal">
<div class="form-group">
<label class="col-lg-3 control-label">Username</label>
<div class="col-lg-5">
<input type="text" class="form-control" name="username" />
</div>
</div>
</form>
and custom js is
$(document).ready(function() {
$('#registrationForm').bootstrapValidator({
fields: {
username: {
message: 'The username is not valid',
validators: {
remote: {
message: 'The username is not available',
url: 'default.php',
data: {
type: 'username'
}
}
}
}
}
});
});
back-end default.php file is
<?php
$isAvailable = true;
switch ($_POST['type']) {
case 'username':
default:
$username = $_POST['username'];
data = 'admin','root';
$isAvailable = true;
break;
}
echo json_encode(array(
'valid' => $isAvailable,
));
username already exists or not from default.php file, error
not showing.
$(document).ready(function() {
$('#registrationForm').bootstrapValidator({
fields: {
username: {
message: 'The username is not valid',
validators: {
callback: {
callback: function(value, validator) {
var data = "user1";
if (value === data) {
return {
valid: false,
message: 'The name is not available'
}
}
return true;
}
}
}
}
}
});
});
Instead of using php function, I have used call back function for this it's working fine.

How can I add multiple images along with other input fields in vue js html?

My html code is
I also need to add sez which is in array format and also i need to add multiple images, need to provide add image and when clicking on it, need to add images as needed by the client
<form method="POST" enctype="multipart/form-data" v-on:submit.prevent="handleSubmit($event);">
<div class="row">
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Name</label>
<input type="text" class="form-control" v-model="name">
</div>
</div>
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Alias</label>
<input type="text" class="form-control" v-model="alias">
</div>
</div>
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Sex</label>
<select class="form-control" v-model="sex" id="level">
<option value="Male">Male</option>
<option value="female">Female</option>
</select>
</div>
</div>
</div>
<div class="row" v-for="(book, index) in sez" :key="index">
<div class="col-md-4">
<div class="form-group label-floating">
<label class="control-label">Date </label>
<input type="date" class="form-control" v-model="book.date">
</div>
</div>
<div class="col-md-8">
<div class="form-group label-floating">
<label class="control-label"> Details</label>
<input type="text" class="form-control" book.details>
</div>
</div>
</div>
<a #click="addNewRow">Add</a>
<div class="card-content">
<div class="row">
<div class="col-md-4">
<div class="button success expand radius">
<span id="save_image_titlebar_logo_live">Signature</span>
<label class="custom-file-upload"><input type="file" name="photo" accept="image/*" />
</label>
</div>
</div>
<div class="col-md-4">
<div class="button success expand radius">
<span id="save_image_titlebar_logo_live">Recent Photograph</span>
<label class="custom-file-upload">
<input type="file" name="sign"/>
</label>
</div>
</div>
</div>
</div>
</form>
My vue js code is
addForm = new Vue({
el: "#addForm",
data: {
name: '',
alias: '',
sex: '',
sez: [{
date: null,
details: null,
}, ],
photo: '',
sign: '',
},
methods: {
addNewRow: function() {
this.seziure.push({
date: null,
details: null,
});
},
handleSubmit: function(e) {
var vm = this;
data = {};
data['sez'] = this.sez;
data['name'] = this.name;
data['alias'] = this.alias;
data['sex'] = this.sex;
//how to add images
$.ajax({
url: 'http://localhost:4000/save/',
data: data,
type: 'POST',
dataType: 'json',
success: function(e) {
if (e.status) {
vm.response = e;
alert("success")
} else {
vm.response = e;
console.log(vm.response);
alert("Registration Failed")
}
}
});
return false;
},
},
});
This is my code. I have no idea about how to add images in this case.
Can anyone please help me pass this data.
How to pass this data along with images to the backend?
I don't want to use base64 encoding. I need to just pass this image in this ajax post request along with other data
Using axios:
Template
...
<input type="file" name="photo" accept="image/*" #change="setPhotoFiles($event.target.name, $event.target.files) />
...
Code
data () {
return {
...
photoFiles: [],
...
}
},
...
methods: {
...
setPhotoFiles (fieldName, fileList) {
this.photoFiles = fileList;
},
...
handleSubmit (e) {
const formData = new FormData();
formData.append('name', this.name);
formData.append('alias', this.alias);
formData.append('sex', this.sex);
...
this.photoFiles.forEach((element, index, array) => {
formData.append('photo-' + index, element);
});
axios.post("http://localhost:4000/save/", formData)
.then(function (result) {
console.log(result);
...
}, function (error) {
console.log(error);
...
});
}
}
I'm not sure where would you like the extra images to appear, but I added them after this column:
<div class="col-md-4">
<div class="button success expand radius">
<span id="save_image_titlebar_logo_live">Recent Photograph</span>
<label class="custom-file-upload">
<input type="file" name="sign"/>
</label>
</div>
</div>
And here's the column I added — "add images": (You can try this feature here, with the updates)
<div class="col-md-4">
<ul class="list-group" :if="images.length">
<li class="list-group-item" v-for="(f, index) in images" :key="index">
<button class="close" #click.prevent="removeImage(index, $event)">×</button>
<div class="button success expand radius">
<label class="custom-file-upload">
<input type="file" class="images[]" accept="image/*" #change="previewImage(index, $event)">
</label>
</div>
<div :class="'images[' + index + ']-preview image-preview'"></div>
</li>
</ul>
<button class="btn btn-link add-image" #click.prevent="addNewImage">Add Image</button>
</div>
And the full Vue JS code (with jQuery.ajax()):
addForm = new Vue({
el: "#addForm",
data: {
name: '',
alias: '',
sex: '',
sez: [{
date: null,
details: null
}],
// I removed `photo` and `sign` because (I think) the're not necessary.
// Add I added `images` so that we could easily add new images via Vue.
images: [],
maxImages: 5,
// Selector for the "Add Image" button. Try using (or you should use) ID
// instead; e.g. `button#add-image`. But it has to be a `button` element.
addImage: 'button.add-image'
},
methods: {
addNewRow: function() {
// I changed to `this.sez.push` because `this.seziure` is `undefined`.
this.sez.push({
date: null,
details: null
});
},
addNewImage: function(e) {
var n = this.maxImages || -1;
if (n && this.images.length < n) {
this.images.push('');
}
this.checkImages();
},
removeImage: function(index) {
this.images.splice(index, 1);
this.checkImages();
},
checkImages: function() {
var n = this.maxImages || -1;
if (n && this.images.length >= n) {
$(this.addImage, this.el).prop('disabled', true); // Disables the button.
} else {
$(this.addImage, this.el).prop('disabled', false); // Enables the button.
}
},
previewImage: function(index, e) {
var r = new FileReader(),
f = e.target.files[0];
r.addEventListener('load', function() {
$('[class~="images[' + index + ']-preview"]', this.el).html(
'<img src="' + r.result + '" class="thumbnail img-responsive">'
);
}, false);
if (f) {
r.readAsDataURL(f);
}
},
handleSubmit: function(e) {
var vm = this;
var data = new FormData(e.target);
data.append('sez', this.sez);
data.append('name', this.name);
data.append('alias', this.alias);
data.append('sex', this.sex);
// The `data` already contain the Signature and Recent Photograph images.
// Here we add the extra images as an array.
$('[class~="images[]"]', this.el).each(function(i) {
if (i > vm.maxImages - 1) {
return; // Max images reached.
}
data.append('images[' + i + ']', this.files[0]);
});
$.ajax({
url: 'http://localhost:4000/save/',
data: data,
type: 'POST',
dataType: 'json',
success: function(e) {
if (e.status) {
vm.response = e;
alert("success");
} else {
vm.response = e;
console.log(vm.response);
alert("Registration Failed");
}
},
cache: false,
contentType: false,
processData: false
});
return false;
},
},
});
Additional Notes
I know you're using Node.js in the back-end; however, I should mention that in PHP, the $_FILES variable would contain all the images (so long as the fields name are properly set); and I suppose Node.js has a similar variable or way of getting the files.
And in the following input, you may have forgotten to wrap book.details in v-model:
<input type="text" class="form-control" book.details>
<input type="text" class="form-control" v-model="book.details"> <!-- Correct -->
UPDATE
Added feature to limit number of images allowed to be selected/uploaded, and added preview for selected image. Plus the "send images as array" fix.
If you're using HTML5, try with a FormData object ; it will encode your file input content :
var myForm = document.getElementById('addForm');
formData = new FormData(myForm);
data: formData
Use below templete to show/upload the image:
<div v-if="!image">
<h2>Select an image</h2>
<input type="file" #change="onImageUpload">
</div>
<div v-else>
<img :src="image" />
<button #click="removeImage">Remove image</button>
</div>
Js code:
data: {
image: '',
imageBuff: ''
},
methods: {
onImageUpload(e) {
var files = e.target.files || e.dataTransfer.files;
if (!files.length)
return;
this.createImage(files[0]);
},
createImage(file) {
var image = new Image();
var reader = new FileReader();
this.imageBuff = file;
reader.onload = (e) => {
this.image = e.target.result;
};
reader.readAsDataURL(file);
},
removeImage: function(e) {
this.image = '';
},
handleSubmit(e) {
const formData = new FormData();
formData.append('name', this.name);
formData.append('alias', this.alias);
formData.append('sex', this.sex);
formData.append('image', this.imageBuff);
...
// Ajax or Axios can be used
$.ajax({
url: 'http://localhost:4000/save/',
data: formData,
processData: false, // prevent jQuery from automatically transforming the data into a query string.
contentType: false,
type: 'POST',
success: function(data) {
console.log(data);
...
}
});
}
}

Finding cause of template being destroyed/recreated

trying to debug something. On our client, we have a Accounts.createUser() call, which include a callback that looks like:
function(err) {
if (err) {
Session.set('entryError', err.reason);
}
else {
return Router.go('/');
}
}
With this setup, a normal signup (i.e. with no errors) works fine. However, if there's an error, the template is destroyed, created, and rendered, twice. I found this question, and went on a hunt for potential reactive variables triggering this. The only thing I can find that changes between the two template destroyed/created/rendered calls is Meteor.loggingIn() (including session variables). That doesn't seem to be causing this, because when I removed all references to it and dependencies on it, the problem continued.
Any pointers?
ETA: per the request below.
signUpPage.html:
<template name='signUpPage'>
<main id="signUpPage">
<h1 class="accountsTitle">Sign Up</h1>
<p id="signInPrompt">If you already have an account sign in.</p>
<form id='signUpForm'>
{{> entryError}}
<div class="form-group">
<label for="usernameInput">Username</label>
<input id="usernameInput" type="string" class="form-control" value=''>
</div>
<div class="form-group">
<label for="emailInput">Email Address</label>
<input id="emailInput" type="email" class="form-control" value=''>
</div>
<div class="form-group">
<label for="passwordInput">Password</label>
<input id="passwordInput" type="password" class="form-control" value=''>
</div>
<div class="form-group">
<label for="confirmPasswordInput">Confirm Password</label>
<input id="confirmPasswordInput" type="password" class="form-control" value=''>
</div>
<div class="form-group">
<label for="signupCodeInput">Signup Code</label>
<input id="signupCodeInput" class="form-control" value=''>
</div>
<button type="submit" class="btn btn-primary btn-block">Sign up</button>
</form>
</main>
</template>
signUpPage.js
Template.signUpPage.events({
'submit #signUpForm': function(event, template) {
event.preventDefault();
// Get the input values from the form
var username = template.find("#usernameInput").value.trim();
var email = template.find("#emailInput").value.trim();
var signupCode = template.find("#signupCodeInput").value;
var password = template.find("#passwordInput").value;
var confirmPassword = template.find("#confirmPasswordInput").value;
// Log the signup attempt
var signupAttempt = {'type':'signup', 'username':username, 'email':email, 'password':password, 'signupCode':signupCode};
Logins.insert(signupAttempt);
// Validate username presence
if (!username.length)
return Session.set('entryError', 'Username is required');
// Validate email presence
if (!email.length)
return Session.set('entryError', 'Email address is required');
// Validate password
var passwordErrors = validatePassword(password, confirmPassword);
if (passwordErrors.length) {
var errorsString = passwordErrors.join("\r\n");
Session.set('entryError', errorsString);
return;
}
// Validate signup code
if (!signupCode.length)
return Session.set('entryError', 'Signup code is required');
Meteor.call('createAccount', username, email, password, signupCode, function(err, data) {
if (err) {
Session.set('entryError', err.reason);
return;
}
else {
Meteor.loginWithPassword(username, password);
return Router.go('/');
}
});
}
});
Template.signUpPage.destroyed = function () {
Session.set("entryError", null);
};
Template.signUpPage.created = function() {
document.title = "Grove OS | Sign Up";
};
The following are js files where entryError is used:
Template.signInPage.events({
'click #signInButton': function(evt, template) {
evt.preventDefault();
// Making lowercase here, check on the server should be case insensitive though
var email = template.find('#emailInput').value.trim().toLowerCase();
var password = template.find('#passwordInput').value;
if (!email.length)
return Session.set('entryError', 'Email is blank');
if (!password.length)
return Session.set('entryError', 'Password is blank');
var loginAttempt = {'type':'login', 'email':email, 'date':new Date()};
return Meteor.loginWithPassword(email, password, function(error) {
if (error) {
loginAttempt.status = 'error';
Logins.insert(loginAttempt);
return Session.set('entryError', error.reason);
} else{
loginAttempt.status = 'success';
Logins.insert(loginAttempt);
return Router.go("/");
}
});
},
'click #signUpButton': function(evt, template) {
evt.preventDefault();
Router.go("signUpRoute");
},
'click #forgotPasswordButton': function(evt, template) {
evt.preventDefault();
Router.go("forgotPasswordRoute");
}
});
Template.signInPage.destroyed = function () {
Session.set("entryError", null);
};
Template.signInPage.created = function() {
document.title = "Grove OS | Sign In";
};
-
Template.resetPasswordPage.helpers({
error: function() {
return Session.get('entryError');
}
});
Template.resetPasswordPage.events({
'submit #resetPasswordForm': function(event, template) {
event.preventDefault();
var password = template.find('#passwordInput').value;
var confirmPassword = template.find('#confirmPasswordInput').value;
// Validate password
var passwordErrors = validatePassword(password, confirmPassword);
if (passwordErrors.length) {
var errorsString = passwordErrors.join("\r\n");
return Session.set('entryError', errorsString);
} else {
return Accounts.resetPassword(Session.get('resetToken'), password, function(error) {
if (error) {
return Session.set('entryError', error.reason || "Unknown error");
} else {
Session.set('resetToken', null);
return Router.go("/");
}
});
}
}
});
Template.resetPasswordPage.created = function () {
document.title = "Grove OS | Reset Password";
};
-
Template.forgotPasswordPage.events({
'submit #forgotPasswordForm': function(event, template) {
event.preventDefault();
var email = template.find("#forgottenEmail").value;
if (!email.length) {
return Session.set('entryError', 'Email is required');
} else {
return Accounts.forgotPassword({
email: email
}, function(error) {
if (error)
return Session.set('entryError', error.reason);
else
return Router.go("/");
});
}
}
});
Template.forgotPasswordPage.created = function () {
document.title = "Grove OS | Forgot Password";
};
-
Router code (combined from 2 files):
//--------------------------------------------------------------
// Global Configuration
Router.configure({
layoutTemplate: 'appBody',
notFoundTemplate: 'notFoundPage',
loadingTemplate: 'loadingPage',
yieldTemplates: {
'appHeader': {to: 'header'},
'appFooter': {to: 'footer'}
}
});
// Have to sign in to access all application pages
Router.onBeforeAction(function() {
console.log("Global router onBeforeAction calle");
// if (!Meteor.loggingIn() && !Meteor.user()) {
if(!Meteor.user()){
this.redirect('/sign-in');
}
this.next();
}, {
// whitelist which routes you don't need to be signed in for
except: [
'signUpRoute',
'signInRoute',
'forgotPasswordRoute',
'signOutRoute',
'resetPasswordRoute',
'pageNotFoundRoute'
]
});
// Subscriptions application-wide
Router.waitOn(function() {
if (Meteor.loggingIn() || Meteor.user())
return Meteor.subscribe("userGroups");
});
//--------------------------------------------------------------
// Root route
Router.route('landingRoute', {
path: '/',
onBeforeAction: function(){
console.log("other global one is being called");
// if (!Meteor.loggingIn() && !Meteor.user()){
if(!Meteor.user()){
this.redirect('/sign-in');
}else{
this.redirect('/grove/dashboard');
}
this.next();
}
});
//--------------------------------------------------------------
// Static Routes
Router.route('/glossary', {
path: '/glossary',
template: 'glossaryPage'
});
Router.route('/eula', {
path: '/eula',
template: 'eulaPage'
});
Router.route('/privacy', {
path: '/privacy',
template: 'privacyPage'
});
Router.route('/about', {
path: '/about',
template: 'aboutPage'
});
Router.route("signUpRoute", {
path: "/sign-up",
template: "signUpPage"
});
Router.route("signInRoute", {
path: "/sign-in",
template: "signInPage"
});
Router.route('signOutRoute', {
path: '/sign-out',
template: "signOutPage",
onBeforeAction: function() {
Meteor.logout();
Router.go('/');
this.next();
}
});
Router.route("forgotPasswordRoute", {
path: "/forgot-password",
template: "forgotPasswordPage",
});
Router.route('resetPasswordRoute', {
path: 'reset-password/:resetToken',
template: "resetPasswordPage",
data: function() {
Session.set('resetToken', this.params.resetToken);
return ;
}
});
Router.route("404Route", {
path: "/page-not-found",
template: "notFoundPage",
});
Router.route("dashboardRoute", {
path: "/dashboard",
template: "dashboardPage"
});
Router.route('createShrub', {
path: '/tools/createShrub',
template: 'upsertShrubPage',
waitOn: function(){
},
data: function () {
},
});
// TODO figure out how to dynamically render templates
// based on if the slug is a group, user, or nothing
// and also conditionally subscribe
Router.route('profileRoute', {
path: '/:ownerSlug',
template: 'myProfilePage'
});
Router.route('groveRoute', {
path: '/:ownerSlug/:groveSlug',
template: 'grovePage',
data: function () {
return Groves.findOne({ slug: this.params.groveSlug });
},
});
Router.route('shrubRoute', {
path: '/:ownerSlug/:groveSlug/:shrubSlug',
template: 'shrubStaticPage',
data: function() {
Session.set("currentShrub", this.params.shrubSlug);
return ShrubTemplates.findOne({ slug: this.params.shrubSlug });
},
action: function() {
if (this.ready())
this.render();
else
this.render('loadingHolder');
}
});
Well, it turned out that as part of the router there was this function:
Router.waitOn(function() {
if (Meteor.loggingIn() || Meteor.user())
return Meteor.subscribe("userGroups");
});
The change in Meteor.loggingIn() caused this function to run, which we saw with our loading page getting displayed briefly. We're changed the if statement so that it no longer contains the Meteor.loggingIn() check. A little embarrassing, really--I swear I looked at that line before. Not sure what happened in my thought process to miss this. At least now I have a better understanding of Iron Router.

Categories