Retrieving records in ember js - javascript

I'm new to ember js. I have a form & when a user hit submit i want to check whether the username & password that user have entered, is already in my model/database.I tried following,But it didn't work. Please help me with this...
Template
<h2>Welcome to my blog</h2>
<form {{action 'exist' on="submit"}}>
<dl>
<dt>User Name:<br> {{textarea value=uName cols="20" rows="1"}}</dt>
<dt>Password:<br> {{textarea value=passw cols="20" rows="1"}}</dt>
</dl>
<button type="submit" class="btn btn-primary">Login</button>
</form>
Model
import DS from 'ember-data';
export default DS.Model.extend({
FirstName: DS.attr('string'),
UserName: DS.attr('string'),
Password: DS.attr('string'),
PermissionList: DS.attr('array')
});
Route
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
return this.store.find('user');
}
});
Controller
import Ember from 'ember';
export default Ember.Controller.extend({
actions: {
ght: function () {
var uName = this.get('uName');
var passw = this.get('passw');
if (this.store.find('user', {
userName: this.get('uName')
})) {
alert('Already exist');
}
}
}
});
// This alert is shown for every input.Even they are not in the model

as store.find() always returns a promise which is an object, if condition always evaluates to true. What you should probably do is you've to wait for the promise to resolve and do the check like
// ...
var uName = this.get('uName');
this.store.find('user', {
userName: uName
}).then(function(user) {
if(user) {
alert('Already exist');
} else {
}
});
// ...

This form looks like a login form. If my assumption is right you don't show this form if user is already logged in ( in this case the session will have user info). In case if user is not logged in you will have to show form. I don't think you will need to search user in store. Just send/save user to server and do the user find logic on server side and send response accordingly. On ember side you can show exist result by handling .then of promises.
If your use case is different you can use query(for multiple records). and queryRecord for single record
Query
Copy pasted from documents
// GET to /persons?filter[name]=Peter
this.store.query('person', { filter: { name: 'Peter' } }).then(function(peters) {
// Do something with `peters`
});
// GET to /persons?filter[email]=tomster#example.com
this.store.queryRecord('person', { filter: { email: 'tomster#example.com' } }).then(function(tomster) {
// do something with `tomster`
});
//on mobile will add code if this doesn't help

Related

Creating user on the server with random username and no password

I am very new to Meteor and trying to develop an online synchronous game experiment. Generally, once participants AGREE to the consent form, I want to create a user and add that user into my Players collection.
My consent_page.js looks like this:
import './consent_page.html';
import { FlowRouter } from 'meteor/kadira:flow-router';
import { Template } from 'meteor/templating';
import { Meteor } from 'meteor/meteor'
import '../../../api/players/methods.js'
Template.consent_page.events({
'submit .consent-form'(event) {
event.preventDefault();
Meteor.call('players.addPlayer');
FlowRouter.go('/instructions')
}
});
and my players.addPlayer method looks like this
import { Meteor } from 'meteor/meteor';
import { Accounts } from 'meteor/accounts-base';
import { Players } from './players.js';
import { Random } from 'meteor/random'
Meteor.methods({
'players.addPlayer'() {
console.log('I am in the method');
username = Random.id();
user = create_user(username);
alert(username);
alert(user);
Players.insert({
_id: this.userId,
enterTime: new Date(),
status: 'instructions',
passedQuiz: false,
quizAttempts: 0,
needRematch: false,
condition: 'control'
});
}
});
/*
* Helper functions for the methods
*/
//create user in the server
create_user = function (username) {
return Accounts.createUser({
username: username,
});
};
The collection Players.js has the definition of the collection.
import { Mongo } from 'meteor/mongo'
export const Players = new Mongo.Collection('players');
However, this doesn't work. I do get redirected to the instructions page, but the user doesn't get created .. I get the following error:
Error invoking Method 'players.addPlayer': Method 'players.addPlayer' not found [404]
Although, I get the I am in the method message printed in the console. The alert with the return of create_user is undefined. Also, I want to create the users without a password (how can I do that?).
Accounts.createUser() method is a part of accounts-base package. You need to import that at first. I'm sharing a snippet from my working project. Hope this helps:
import { Meteor } from 'meteor/meteor';
import { Accounts } from 'meteor/accounts-base';
const bcrypt = require('bcrypt');
Meteor.methods({
'user.create':function(data){
return Accounts.createUser({
name: data.name,
username: data.userId,
password: data.password,
});
}
});

How do you create login and register pages without having to connect to backend (ReactJS + Redux)?

I am attempting to create a login and a register page using ReactJS + Redux. Currently once a user registers, the user's object with the registered info are stored inside an array:
const userDataReducer = function(users = [], action){
switch (action.type){
case 'ADD_USER':
return[{
username: action.username,
email: action.email,
name: action.name,
password: action.password
}, ...users]
and once it is registered, the user enters the username and password in the login form and submits it:
verifyLoginUser(){
event.preventDefault()
if(this.props.actions.verifyUser(this.props.loginUser.username, this.props.loginUser.password)){
console.log('LOGGED IN')
} else {
console.log('NOT LOGGED IN')
}
}
and inside userDataReducer.js verifies with the following:
case 'VERIFY_USER':
let isVerified = false;
users.forEach((user)=> {
if(user.username === action.username && user.password === action.password){
isVerified = true;
return false;
}
});
return isVerified;
The actions are:
addUser: function(username, email, name, password) {
return {
type: 'ADD_USER',
username: username,
email: email,
name: name,
password: password
}
},
verifyUser: function(username, password){
return {
type: 'VERIFY_USER',
username: username,
password: password
}
}
Currently, if a user tries to login and click submit, it just continues to return 'LOGGED IN' in any cases.
In ReactJS + Redux, is this the correct way to go about creating Login and Register pages just via front-end? Any guidance or insight would be greatly appreciated. Thank you in advance.
"Login and register just via front-end" probably goes against everything in the book, so if you are looking for implementing good practices, that might be a good place to start - https://www.quora.com/Is-it-possible-to-do-client-side-only-javascript-authentication
Regarding React and Redux, your code looks good. I would just point out 2 things about your actions:
It is a good practice for actions to contain a payload property - https://github.com/acdlite/flux-standard-action
VERIFY_USER is only reading data, not storing. So you don't actually need an action there, nor does the code need to live in a reducer. That code should probably be a method of your authentication component.

Ember-data: model refresh on DS.Store.createRecord

Embsters!
I am trying to figure out why my model isn't refreshed after I create a new record and save it to the store.
My route computes the model as follows:
model: function (params) {
var postID = params.post_id,
userID = this.get('session.currentUser.id');
var post = this.store.findRecord('post', postID) ;
var followings = this.store.query('post-following', {
filter: { post: postID }
}) ;
var userFollowing = this.store.queryRecord('post-following', {
filter: { post: postID, user: userID }
}) ;
return new Ember.RSVP.hash({
post: post,
followings: followings,
userFollowing: userFollowing
});
}
My template then renders a list and a button:
{{#each model.followings as |following|}}
...
{{/each}}
{{#if model.userFollowing}}
<button {{action 'follow'}}>Follow</button>
{{else}}
<button {{action 'unFollow'}}>Unfollow</button>
{{/if}}
And my controller creates/deletes the relevant post-following record:
actions: {
follow: function () {
var user = this.get('session.currentUser'),
post = this.get('model.post') ;
this.store.createRecord('post-following', {
user: user,
post: post
}).save();
},
unFollow: function () {
this.get('model.userFollowing').destroyRecord() ;
}
}
When I click the [Follow] button:
a successful POST request is sent
the button is not updated
the list is not updated
When I (refresh the page then) click the [Unfollow] button:
a successful DELETE request is sent
the button is not updated
the list is updated
Do you have any idea of what I'm doing wrong?
Could it be a problem with my payload?
EDIT: Solved!
Well, it sounds like I was expecting too much from ember.
The framework won't automatically update my post-followings array on store.createRecord('post-following', {...}) call.
I then adjusted my controller logic to "manually" update my model:
// in follow action…
userFollowing.save().then( function(){
var followings = store.query('post-following', {
filter: { post: postID }
}).then( function (followings) {
_this.set('model.userFollowing', userFollowing);
_this.set('model.followings', followings);
}) ;
});
// in unFollow action…
userFollowing.destroyRecord().then( function () {
_this.set('model.userFollowing', null);
_this.notifyPropertyChange('model.followings') ;
});
Please note that my backend API design has been criticized by #duizendnegen (see comments). More best practices in this article.
Thanks you for all your help !!!
Brou
For these kind of questions, it really helps to have a smaller, replicated problem (e.g. through Ember Twiddle)
Fundamentally, the new post-following record doesn't match the filter: it is filtered for an attribute { post: 123 } and your post-following object contains something in the lines of { post: { id: 123, name: "" } }. Moreover, your post-following object doesn't contain a property called filter or what it could be - i.e. the query it executes to the server are different than those you want to filter by on the client.
My approach here would be to, as a response to the follow and unfollow actions, update the model, both the userFollowing and followings.
Your issue is that you aren't re-setting the property model to point to the newly created object. You are always accessing the same model property, even after creating a new one.
First thing to be aware of is that, after the model hook in your route, the setupController hook is called that executes:
controller.set('model', resolvedModel)
meaning that the model property on your controller is, by default, set every time the route loads (the model hook resolves). However, this doesn't happen after you create a new record so you must do it explicitly:
let newModel = this.store.createRecord('post-following', {
user: user,
post: post
})
// since model.save() returns a promise
// we wait for a successfull save before
// re-setting the `model` property
newModel.save().then(() => {
this.set('model', newModel);
});
For a more clear design, I would also recommend that you create an alias to the model property that more specifically describes your model or override the default behavior of setupController if you are also doing some initial setup on the controller. So either:
export default Ember.Controller.extend({
// ...
blog: Ember.computed.alias('model') // more descriptive model name
// ...
});
Or:
export default Ember.Route.extend({
// ...
setupController(controller, resolvedModel) {
controller.set('blog', resolvedModel); // more descriptive model name
// do other setup
}
// ...
});
Your model is set when you enter the page. When changes are made, your model doesn't change. The only reason why the list is updated when you destroy the record is because it simply doesn't exist anymore. Reload the model after clicking the follow button or unfollow button, or manually change the values for the list/button.

Emberjs: How do I filter users by any property using routes

I have the following route and model setup. All my users display fine using a template and
displays the firstName and email as expected.
However I am unable to filter by firstName or email when routing similar to how :user_id works. (I am using the fixture adapter for now)
Example: #/users/logan
this.resource('users', function(){
this.resource('user', {path: ':user_firstName'}); //#/users/logan
});
The following model
App.User = DS.Model.extend({
firstName: DS.attr('string'),
email: DS.attr('string')
})
So to summarise further, exactly what should happen inside the model function or what other approach can I take?
App.UsersRoute = Em.Route.extend({
model: function(){
var user = App.User.find();;
//FILTER BY firstName how?
return user;
}
});
You can create an event on the route that changes the controller content to be a filter of the model.
Template:
<span {{action filterByName}}>Filter by name</span>
Router:
App.UsersRoute = Ember.Route.extend({
events: {
filterByName: function() {
this.get('controller').set('content', this.get('currentModel').filterProperty('firstName', 'John'));
}
}
});

Meteor.users.update() does not work on logout + login

I have a user profile view where users can edit their profile information. Everything below works great and the update is successful. However, when I logout of the account and login with a different user account, the update fails and returns an Access denied error. It isn't until I refresh the page that I can edit the profile information again with the second account.
I know this case is very rare and a user would not normally be logging out of one account, logging in with another and trying to update their profile but I would like to better understand why this is happening. Is the client token not flushed when a user logs out or is there something else that's being preserved that requires a complete reload of the page?
On client JS:
Template.user_profile_form.events({
'click #submit_profile_btn': function(evt) {
evt.preventDefault();
var first_name = $('#profile_first_name').val()
,last_name = $('#profile_last_name').val()
,email = $('#profile_email').val()
,email_lower_case = email.toLowerCase()
,gravatar_hash = CryptoJS.MD5(email_lower_case)
;
gravatar_hash = gravatar_hash.toString(CryptoJS.enc.Hex);
// TODO need to create user sessions so that when you log out and log back in, you have a fresh session
Meteor.users.update({_id: this.userId }, {
$set: {
profile: {
first_name: first_name,
last_name: last_name,
gravatar_hash: gravatar_hash
}
}
}, function(error) {
if (!error) {
Session.set('profile_edit', 'success');
Meteor.setTimeout(function() {
Session.set('profile_edit', null);
}, 3000);
} else {
Session.set('profile_edit', 'error');
Template.user_profile_form.error_message = function() {
return error.reason;
};
}
});
Meteor.call('changeEmail', email);
}
});
The server JS:
Meteor.publish('list-all-users', function () {
return Meteor.users.find({_id: this.userId }, {
fields: {
profile: 1,
emails: 1
}
});
});
Meteor.methods({
sendEmail: function(to, from, subject, text) {
this.unblock();
Email.send({
to: to,
from: from,
subject: subject,
text: text
});
},
changeEmail: function(newEmail) {
// TODO Need to validate that new e-mail does not already exist
Meteor.users.update(Meteor.userId(), {
$set: {
emails: [{
address: newEmail,
verified: false
}]
}
});
}
});
The template:
<template name="user_profile_form">
<h2>Update Profile</h2>
<div id="profile-form">
{{#if success}}
<div class="alert alert-success">
<strong>Profile updated!</strong> Your profile has been successfully updated.
</div>
{{/if}}
{{#if error}}
<div class="alert alert-error">
<strong>Uh oh!</strong> Something went wrong and your profile was not updated. {{error_message}}.
</div>
{{/if}}
<p>
{{#each profile}}
<input type="text" id="profile_first_name" placeholder="First Name" value="{{first_name}}">
<input type="text" id="profile_last_name" placeholder="Last Name" value="{{last_name}}">
{{/each}}
<input type="email" id="profile_email" placeholder="Email" value="{{email_address}}">
</p>
</div>
<div id="submit-btn">
<input type="submit" id="submit_profile_btn" class="btn btn-primary">
</div>
</template>
The Meteor logout function does almost nothing. It certainly does not tear down Session state or the rest of your app's context. Your code must reset these variables during your app's logout event. A manual refresh of the page causes the client side JavaScript to reload wiping out existing Session data.
If you don't want to mess with the accounts-ui template internals you can use the following pattern (CoffeeScript code) to clear individual variables from the Session:
Deps.autorun (c) ->
user = Meteor.user()
if user
# Setup code on login (if required)
else if not user
# Clear session on logout
Session.set "profile_edit", undefined

Categories

Resources