grab the value of an element in a different template - meteor

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();

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!

Form action called before ajax request

I'm trying to validate some data using javascript, so after created this form:
<form asp-controller="User" asp-action="UpdateUser" asp-antiforgery="true" id="userInformations">
<div class="form-group">
<label class="col-lg-6 control-label">#Localizer["OldPassword"] (*)</label>
<div class="col-lg-12">
<input class="form-control" required id="oldPassword"
asp-for="#Model.ExistingPassword" type="password" />
</div>
<div class="form-group">
<label class="col-lg-6 control-label">#Localizer["NewPassword"] (*)</label>
<div class="col-lg-12">
<input class="form-control" required id="newPassword"
asp-for="#Model.Password" type="password" />
</div>
</div>
<button type="submit" class="btn btn-primary">Store</button>
</form>
I binded a javascript function that intercept the submit:
$('#userInformations').on('submit', function (event) {
event.preventDefault();
//validate some fields
//execute ajax request
$.ajax({
url: $(this).attr('action'),
type: "POST",
data: $(this).serialize(),
success: function (result) {
alert(true);
console.log(result)
},
error: function (data) {
console.log(data);
}
});
});
Now when I press the submit button, the method UpdateUser in the UserController is called first of the javascript function, and I don't understand why happen this because I used preventDefault.
How can I prevent to call the asp net action binded to the form?
The effect you want is to use javascript to validate some data , and implement the action call through ajax when you press the submit button?
I use the code you provided and it works.
Try the following two ways:
1.Add the following piece of code above your javascript
<script src="~/lib/jquery/dist/jquery.js"></script>
2.Or directly write your javascript in #section Scripts { }
If you want JavaScript first than you have to remove asp-Controller and action from form, than you can validate form by JavaScript and send data through Ajax call to Controller/action.

How can I route my messenger and messages in Meteor?

Im creating a an instant messenger app and im having a little trouble routing it. So, once you go into the app. There is a list of available users. You can click on a user and start chatting. The issue I have is once I click send, the console show an Uncaught TypeError: Cannot read property 'value' of undefined. Im not sure what im doing wrong here. Also I need help show the chat messages sent above. As if you can see the recent and previous messages. Here are my codes. Any examples and helps would be great.
HTML
minstant
<body>
</body>
<!-- this is the main template used by iron:router to build the page -->
<template name="ApplicationLayout">
{{> yield "header"}}
<div class="container">
{{> yield "main"}}
</div>
</template>
<!-- top level template for the nav bar -->
<template name="navbar">
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="/">
Minstant!
</a>
</div>
<div class="nav navbar-nav">
{{> loginButtons}}
</div>
</div>
</nav>
</template>
<!-- Top level template for the lobby page -->
<template name="lobby_page">
{{> available_user_list}}
</template>
<!-- display a list of users -->
<template name="available_user_list">
<h2>Choose someone to chat with:</h2>
<div class="row">
{{#each users}}
{{> available_user}}
{{/each}}
</div>
</template>
<!-- display an individual user -->
<template name="available_user">
<div class="col-md-2">
<div class="user_avatar">
{{#if isMyUser _id}}
<div class="user_avatar">{{getUsername _id}} (YOU)
<br/>
<img src="/{{profile.avatar}}" class="avatar_img">
</div>
{{else}}
<a href="/chat/{{_id}}">
{{getUsername _id}}
<br/>
<img src="/{{profile.avatar}}" class="avatar_img">
</a>
{{/if}}
</div>
</div>
</template>
<!-- Top level template for the chat page -->
<template name="chat_page">
<h2>Type in the box below to send a message!</h2>
<div class="row">
<div class="col-md-12">
<div class="well well-lg">
{{#each recentMessages}}
{{> message}}
{{/each}}
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<form class="new-message">
<input class="input" type="text" name="chat" placeholder="type a message here...">
<button class="btn btn-default">Send</button>
</form>
</div>
</div>
</template>
<!-- simple template that displays a message -->
<template name="message">
<div class = "container">
<div class = "row">
<div class = "username">{{username}}
<img src="/{{profile.avatar}}" class="avatar_img">
</div>
<div class = "message-text"> said: {{messageText}}</div>
</div>
</div>
</template>
Here is my JS
Messages = new Mongo.Collection("messages");
if (Meteor.isClient) {
Meteor.subscribe("messages");
Meteor.subscribe("userStatus");
// set up the main template the the router will use to build pages
Router.configure({
layoutTemplate: 'ApplicationLayout'
});
// specify the top level route, the page users see when they arrive at the site
Router.route('/', function () {
console.log("rendering root /");
this.render("navbar", {to:"header"});
this.render("lobby_page", {to:"main"});
});
// specify a route that allows the current user to chat to another users
Router.route('/chat/:_id', function () {
this.render("navbar", {to:"header"});
this.render("chat_page", {to:"main"});
});
///
// helper functions
///
Template.available_user_list.helpers({
users:function(){
return Meteor.users.find();
}
})
Template.available_user.helpers({
getUsername:function(userId){
user = Meteor.users.findOne({_id:userId});
return user.profile.username;
},
isMyUser:function(userId){
if (userId == Meteor.userId()){
return true;
}
else {
return false;
}
}
})
Template.chat_page.helpers({
recentMessages: function () {
return Messages.find({}, {sort: {createdAt: 1}});
return Meteor.users.find();
},
});
Template.chat_page.events({
// this event fires when the user sends a message on the chat page
'submit .new-message':function(event){
event.preventDefault();
var text= event.target.text.value;
// stop the form from triggering a page reload
event.target.text.value = "";
// see if we can find a chat object in the database
// to which we'll add the message
Meteor.call("SendMessage", text);
},
});
};
Meteor.methods({
sendMessage: function (messageText) {
if (! Meteor.userId()) {
throw new Meteor.Error("not-authorized");
}
Messages.insert({
messageText: messageText,
createdAt: new Date(),
username: Meteor.user().username
});
}
});
// start up script that creates some users for testing
// users have the username 'user1#test.com' .. 'user8#test.com'
// and the password test123
if (Meteor.isServer) {
Meteor.startup(function () {
if (!Meteor.users.findOne()){
for (var i=1;i<9;i++){
var email = "user"+i+"#test.com";
var username = "user"+i;
var avatar = "ava"+i+".png"
console.log("creating a user with password 'test123' and username/ email: "+email);
Meteor.users.insert({profile:{username:username, avatar:avatar}, emails: [{address:email}],services:{ password:{"bcrypt" : "$2a$10$I3erQ084OiyILTv8ybtQ4ON6wusgPbMZ6.P33zzSDei.BbDL.Q4EO"}}});
}
}
},
),
Meteor.publish("messages", function () {
return Messages.find();
});
Meteor.publish("userStatus", function() {
return Meteor.users.find({ "status.online": true });
});
};
The error is with your form submit code. In the console you can see the error is in Template.chat_page.events.submit .new-message on line 73. That will take you right to the error code:
'submit .new-message':function(event){
event.preventDefault();
var text = event.target.text.value;
// stop the form from triggering a page reload
event.target.text.value = "";
}
event.target.text.value doesn't exist. event.target does, but there is no field for text. There is textContent, and you can access the children of the target (which in this case is the form). Put in a console.log(event); and figure out what you are trying to access within the javascript console and then use that to determine what your code should look like. This might work for you:
'submit .new-message':function(event){
event.preventDefault();
var text = event.target.elements.chat.value;
// stop the form from triggering a page reload
event.target.text.value = "";
}
event.target.elements.chat.value comes from the name field of the <input>.

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

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');
}
});

Adding an user field to a Meteor record?

Right now, my Posts model has a title and a content field:
client/client.js:
Meteor.subscribe('all-posts');
Template.posts.posts = function () {
return Posts.find({});
};
Template.posts.events({
'click input[type="button"]' : function () {
var title = document.getElementById('title');
var content = document.getElementById('content');
if (title.value === '') {
alert("Title can't be blank");
} else if (title.value.length < 5 ) {
alert("Title is too short!");
} else {
Posts.insert({
title: title.value,
content: content.value,
author: userId #this show displays the id of the current user
});
title.value = '';
content.value = '';
}
}
});
app.html:
<!--headder and body-->
<div class="span4">
{{#if currentUser}}
<h1>Posts</h1>
<label for="title">Title</label>
<input id="title" type="text" />
<label for="content">Content</label>
<textarea id="content" name="" rows="10" cols="30"></textarea>
<div class="form-actions">
<input type="button" value="Click" class="btn" />
</div>
{{/if}}
</div>
<div class="span6">
{{#each posts}}
<h3>{{title}}</h3>
<p>{{content}}</p>
<p>{{author}}</p>
{{/each}}
</div>
</div>
</div>
</template>
I tried adding an author field (already did meteor add accounts-password and accounts-login):
author: userId
But it just shows the id of the current user who is logged in.
I would like it to show the email of the author of the post instead.
How to accomplish that?
I think you can get the email with
Meteor.users.findOne(userId).emails[0];
#danielsvane is correct, but since your Post document's author field stores the _id of the author and not the email address, you'll need a template helper in order for the template to know how to get the email address. Try the following:
// html
...
<div class='span6'>
{{#each posts}}
{{> postDetail}}
{{/each}}
</div>
...
<template name="postDetail">
<h3>{{title}}</h3>
<p>{{content}}</p>
<p>{{authorEmail}}</p>
</template>
// javascript
Template.postDetail.helpers({
// assuming the `author` field is the one storing the userId of the author
authorEmail: function() { return Meteor.users.findOne(this.author).emails[0]; }
});
If it's always showing the current user and not the user who is the author of the post, then the problem lies in how you're setting the value of the userId variable in your event handler, which isn't code that you showed in your question.

Resources