How to display Meteor.loginWithPassword callbak error message on the same page - meteor

I have created a custom login page and used the Meteor.loginWithPassword(user, password, [callback]) function to login to the app.
Following is the login template:
<template name ="Login">
<form class="login-form form-horizontal">
<div class="control-group">
<input class="email" type="text" placeholder="Email">
</div>
<div class="control-group m-inputwrapper">
<input class="password" type="password" placeholder="Password">
</div>
<div class="control-group">
<button type="submit" class="submit t-btn-login" >Login</button>
</div>
</form>
<div class="alert-container">
<div class="alert-placeholder"></div>
</div>
</template>
Template.Login.events({
'submit .login-form': function(e, t) {
e.preventDefault();
// retrieve the input field values
var email = t.find('.email').value,
password = t.find('.password').value;
Meteor.loginWithPassword(email, password, function(err) {
if (err) {
$(".alert-placeholder").html('<div></div><div class="alert"><span><i class="icon-sign"></i>'+err.message+'</span></div>')
}
});
return false;
}
});
While i debugging i can see the error message displayed and added to the dom. but it will get refresh and message will disappear.
Is meteor re render the page after Meteor.loginWithPassword() ? How can i overcome this?

When using meteor, if you find yourself manually injecting html elements with jQuery, you are probably doing it wrong. I don't know the blaze internals well enough to give you an exact answer to why your elements are not being preserved, but here is a more meteor-like solution:
In your alert container, conditionally render an error message:
<div class="alert-container">
{{#if errorMessage}}
<div class="alert">
<span><i class="icon-sign"></i>{{errorMessage}}</span>
</div>
{{/if}}
</div>
In your login callback, Set the errorMessage session variable if err exists:
Meteor.loginWithPassword(email, password, function(err) {
if (err) {
Session.set('errorMessage', err.message);
}
});
Finally, add a template helper to access the errorMessage session variable:
Template.Login.helpers({
errorMessage: function() {
return Session.get('errorMessage');
}
});

You can use Bert for showing error message in each page. I use it in login page like this :
Meteor.loginWithPassword(emailVar, passwordVar, function(error) {
if (error) {
Bert.alert(error.reason, 'danger', 'growl-top-right');
} else {
Router.go('/dashboard');
}
});

Related

Firebase Auth - ConfirmPasswordReset, how to grab oobcode from URL to pass thorugh function?

I'm trying to implement a reset password Page on my website using firebase auth. I got the send email to reset password page working. Now from what I understand you get an email with a link that you need to click and on this email there will be a code that is needed to reset the password. Now I'm at a loss on how to grab said code from the url and already display it for the user on the field. Is it possible to have the code come in the body of the email and have the user input the code? If not, how do I grab the code from the url and input it for the user so the user can only input the password? My website is using vue and this is what I have so far
<template>
<div class="container">
<h3>reset pw page</h3>
<div class="row">
<form #submit.prevent="ResetPw()" class="col s12">
<div class="row">
<div class="input-field col s12">
<input type="password" id="password" v-model="password" />
<label>Password</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<input type="text" id="code" v-model="code" />
<label>Code</label>
</div>
</div>
<button type="submit" class="btn">Submit</button>
</form>
</div>
</div>
</template>
<script>
import firebase from "firebase/app";
export default {
data() {
return {
password: "",
code: ""
};
},
methods: {
ResetPw() {
firebase
.auth()
.confirmPasswordReset(this.code, this.password)
.then(() => {
console.log(`Password Changed!`);
})
.catch(err => console.log(err));
}
}
};
</script>
I think I got everything done, I just need to understand how to grab the oobcode from the link https://my-project.firebaseapp.com/__/auth/action?mode=&oobCode=
If you are using react-router, it does not parse the query any more, but you can access it via location.search
const params = new URLSearchParams(this.props.location.search);
const code = params.get('oobCode')
const email = await firebase.auth().verifyPasswordResetCode(code)
Alternatively, instead of using this.props.location.search, you can do new URLSearchParams(window.location.pathname)
Not sure how to grab the oobCode from the body of the email but to grab the code from the URL once the page loads, you can refer to this question: how-can-i-get-query-string-values-in-javascript. In your form, create a hidden input for the code with an empty string value. Once window loads, code will be grabbed from URL and then you can pass the code and password into the function
<body>
<form>
<input type="text" id='newPass' name='newPass' placeholder='New password'>
<input type="hidden" id='code' name='code' value="">
<button type='submit'>Submit</button>
</form>
</body>
<script>
$(window).load(function () {
function getParameterByName(name, url) {
if (!url) url = window.location.href;
name = name.replace(/[\[\]]/g, '\\$&');
var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, ' '));
}
var code = getParameterByName('oobCode')
document.getElementById('code').value = code;
</script>
Hope this helps!

$(...).jqBootstrapValidation is not a function at HTMLDocument.<anonymous>

i am trying to implement a contact us page using bootstrap template. I am a really beginner in asp.net and its my first time using a template.
I cant really get it where is the problem that is causing the above error.
I want to when the user click the send Message button to send emails to a current business email.
Can anyone help me?
contact.cshtml
<div class="row">
<div class="col-lg-8 mb-4">
<h3>Send us a Message</h3>
<form name="sentMessage" id="contactForm" novalidate>
<div class="control-group form-group">
<div class="controls">
<label>Full Name:</label>
<input type="text" class="form-control" id="name" required data-validation-required-message="Please enter your name.">
<p class="help-block"></p>
</div>
</div>
<div class="control-group form-group">
<div class="controls">
<label>Phone Number:</label>
<input type="tel" class="form-control" id="phone" required data-validation-required-message="Please enter your phone number.">
</div>
</div>
<div class="control-group form-group">
<div class="controls">
<label>Email Address:</label>
<input type="email" class="form-control" id="email" required data-validation-required-message="Please enter your email address.">
</div>
</div>
<div class="control-group form-group">
<div class="controls">
<label>Message:</label>
<textarea rows="10" cols="100" class="form-control" id="message" required data-validation-required-message="Please enter your message" maxlength="999" style="resize:none"></textarea>
</div>
</div>
<div id="success"></div>
<!-- For success/fail messages -->
<button type="submit" class="btn btn-primary" id="sendMessageButton">Send Message</button>
</form>
</div>
</div>
</div>
<script src="~/Content/vendor/jquery/jquery.min.js"></script>
<script src="~/Scripts/contact_me.js"></script>
<script src="~/Scripts/jqBootstrapValidation.js"></script>
<script src="~/Content/vendor/bootstrap/js/bootstrap.min.js"></script>
contact_me.js
$(function () {
$('#contactForm input,#contactForm textarea').jqBootstrapValidation({
preventSubmit: true,
submitError: function($form, event, errors) {
// additional error messages or events
},
submitSuccess: function($form, event) {
event.preventDefault(); // prevent default submit behaviour
// get values from FORM
var name = $("input#name").val();
var email = $("input#email").val();
var phone = $("input#phone").val();
var message = $("textarea#message").val();
var firstName = name; // For Success/Failure Message
// Check for white space in name for Success/Fail message
if (firstName.indexOf(' ') >= 0) {
firstName = name.split(' ').slice(0, -1).join(' ');
}
$this = $("#sendMessageButton");
$this.prop("disabled", true); // Disable submit button until AJAX call is complete to prevent duplicate messages
$.ajax({
url: "mail/contact_me.php",
type: "POST",
data: {
name: name,
phone: phone,
email: email,
message: message
},
cache: false,
success: function() {
// Success message
$('#success').html("<div class='alert alert-success'>");
$('#success > .alert-success').html("<button type='button' class='close' data-dismiss='alert' aria-hidden='true'>×")
.append("</button>");
$('#success > .alert-success')
.append("<strong>Your message has been sent. </strong>");
$('#success > .alert-success')
.append('</div>');
//clear all fields
$('#contactForm').trigger("reset");
},
error: function() {
// Fail message
$('#success').html("<div class='alert alert-danger'>");
$('#success > .alert-danger').html("<button type='button' class='close' data-dismiss='alert' aria-hidden='true'>×")
.append("</button>");
$('#success > .alert-danger').append($("<strong>").text("Sorry " + firstName + ", it seems that my mail server is not responding. Please try again later!"));
$('#success > .alert-danger').append('</div>');
//clear all fields
$('#contactForm').trigger("reset");
},
complete: function() {
setTimeout(function() {
$this.prop("disabled", false); // Re-enable submit button when AJAX call is complete
}, 1000);
}
});
},
filter: function() {
return $(this).is(":visible");
},
});
$("a[data-toggle=\"tab\"]").click(function(e) {
e.preventDefault();
$(this).tab("show");
});
});
/*When clicking on Full hide fail/success boxes */
$('#name').focus(function() {
$('#success').html('');
});
As my answer morphed through the comments:
the answer was that the OP added Jquery twice making a conflict in
file jqBootstrapValidation.js
Also, to help others based on the OP's post, this next part could be helpful as well:
Javascript files need to be loaded in the order of their dependence. Since your custom javascript file, contact_me.js depends on functions contained in the javascript file, jqBootstrapValidation.js, you need to load jqBootstrapValidation.js before contact_me.js, to fix this switch the order in which these files are loaded:
<script src="~/Content/vendor/bootstrap/js/bootstrap.min.js"></script>
<script src="~/Scripts/jqBootstrapValidation.js"></script>
<script src="~/Content/vendor/jquery/jquery.min.js"></script>
<script src="~/Scripts/contact_me.js"></script>

grab the value of an element in a different template

The code below is trying to grab the username and password from input elements on a template.login and createUser when a button which is in template.footer is clicked.
Being new to javascript and Meteor, my code below probably butchered both.
I thought to make a method call from the footer click event, this call gets the username and password and fires Meteor accounts create and store the returned userId in a local session to be used later. blah..blah..
But how can I get access to input values in one template from another?
so I need your help. Thanks
Template.footer.events({
'click .myClass': function (event, template) {
Meteor.call('loginUser', username,password);
}
});
Meteor.methods({
//store the useId returned from createUser in a local session userId
loginUser: function (username, password) {
Accounts.createUser(username, password, function () {
Session.set(userId, this.value);
});
}
});
<template name="footer">
<footer>
<nav class="navbar navbar-default navbar-fixed-bottom">
<div class="container">
<div class="row">
{{#each footerButtons}}
<h2>
<button class="col-xs-{{footerButtonsScaling}} myClass" type="button">{{text.toUpperCase}}</button>
</h2>
{{/each}}
</div>
</div>
</nav>
</footer>
</template>
<template name="login">
<form action="">
<input type="text" name="username" placeholder="type your ID" value="{{username}}">
<input type="password" name="password" placeholder="type your PIN" value="{{password}}">
</form>
</template>
You can just use jQuery to access field values anywhere in the DOM:
var username = $('[name="username"]').val();
var password = $('[name="password"]').val();

html element innerHtml change with session and server code

This webApp has a header which displays a short message based on user interaction by using session in order to make it reactive. I would like to give the server the priority to display its own message it it has one.
Like if server.message is "" then use client session else use server message.
Should I use global helper? or How can go about it? Thanks.
Template.header.helpers({
headerLabel: function(){
return Session.get('taskSelected');
}
});
<template name="header">
<h1>
<button class="col-xs-2 mainMenu" type="button">☰</button>
</h1>
<h3>
<label class="col-xs-8 text-center">
{{#if headerLabel}}
{{headerLabel}}
{{else}}
Select an item
{{/if}}
</label>
</h3>
<h1>
<button class="col-xs-2" type="button">⋮</button>
</h1>
</template>
Template.mainMenu.events({
'click .menuItem': function (event) {
Session.set('taskSelected', this.menuItem);
});
I think you could do this with reactive variables:
Template.header.onCreated( function() {
this.message = new ReactiveVar( "" );
Meteor.call('serverMessageMethod', function(error, results) {
if( error || !results ) {
Template.instance().message.set(Session.get("yourVariable");
} else {
Template.instance().message.set(results);
}
});
});
Template.header.helpers({
message() {
return Template.instance().message.get();
}
});
You'll have to create the server method to see if there's a message, but other than that this should work.

Iron Router / User details issue in Meteor

I am relatively new to Meteor and have been stuck on an issue for awhile. I have a /users/:_id route that is supposed to display details specific to that user id. However, whenever I hit that route, it displays information for the currently logged in user, NOT of the user whose details I want to view.
Here's my route:
Router.route('/users/:_id', {name: 'Users', controller: 'usersDetailController'});
Here's my usersDetailController:
usersDetailController = RouteController.extend({
waitOn: function () {
Meteor.subscribe('userProfileExtended', this.params._id);
},
onBeforeAction: function () {
var currUserId = Meteor.userId();
var currUser = Meteor.users.findOne({_id: currUserId});
console.log('admin? ' + currUser.isAdmin);
if (!currUser.isAdmin) {
this.render('accessDenied');
} else {
this.next();
}
},
action: function() {
this.render('Users');
}
});
And here's my server/publish:
Meteor.publish('userProfileExtended', function() {
return Meteor.users.find({_id: this.userId});
});
User Details template:
<template name="Users">
<form>
{{#with user}}
<div class="panel panel-default">
<div class="panel-heading">{{profile.companyName}} Details</div>
<div class="row">
<div class="col-md-4">
<div class="panel-body">
<p><label>Company: </label><input id="Company" type="text" value={{profile.companyName}}></p>
<p><label>Email: </label><input id="Email" type="text" value={{emails.address}}></p>
<p><label>Phone: </label><input id="Phone" type="text" value={{profile.phoneNum}}></p>
<p><label>Tire Markup: </label><input id = "tireMarkup" type="text" value={{profile.tireMarkup}}></p>
<p><button class="saveUserDetails">Save</button></p>
<p><button class="deleteUser">Delete User</button></p>
</div>
</div>
</div>
</div>
{{/with}}
Here's my Template Helper:
Template.Users.helpers({
user: function() {
return Meteor.users.findOne();
}
});
Can someone help? I think the issue is the way i reference "this.userId"...
Thank you!!
You need to change your publish function to use the userId parameter you specify when subscribing :
Meteor.publish('userProfileExtended', function(userId) {
return Meteor.users.find(userId,{
fields:{
'username':1,
'profile.firstName':1,
'profile.lastName'
}
});
});
In the publish function, userId will equal whatever value you call Meteor.subscribe with, in this case it will hold this.params._id.
Beware of using the proper syntax for route parameters, if you declare a path of /users/:_id, you need to reference the param using this.params._id.
Also note that it's insecure to publish the whole user document to the client if you only need to show specific fields in the interface, that's why you want to use the fields option of Collection.find to only publish a subset of user documents.
EDIT :
I would recommend using the route data function to specify the data context you want to apply when rendering your template, something like this :
data: function(){
return {
user: Meteor.users.findOne(this.params._id)
};
}

Resources