Clean way of posting form data with Angular? - javascript

I was wondering, what's the clean way of posting form data with angular?
I have this form setup
<div id="contact-form" class="row">
<div class="col-sm-4 col-sm-offset-4 text-center">
<form>
<div class="form-group">
<input type="text" class="form-control input-lg text-center" placeholder="Firstname" name="firstname" ng-model="firstname">
</div>
<div class="form-group">
<input type="text" class="form-control input-lg text-center" placeholder="Lastname" name="lastname" ng-model="lastname">
</div>
<div class="form-group">
<input type="email" class="form-control input-lg text-center" placeholder="Email" name="email"ng-model="email">
</div>
<!-- Submit Contact -->
<button type="submit" class="btn btn-primary btn-lg" ng-click="createContact()">Add</button>
</form>
</div>
</div>
and I'm posting this to a node.js backend "api".
How do I do this correctly? Do I write every api request in 1 core file? Do I make separate files for each page?
And then how I do I write a clean request?
$scope.createContact = function() {
$http.post('/contacts', ...)
.success(function(data) {
})
.error(function(data) {
});
};
I want to process 'lastname', 'firstname' and 'email' to add a new contact, but online I can't find a good, clean way to write this.
Here's my model in case it helps:
var mongoose = require('mongoose');
var ContactSchema = new mongoose.Schema({
firstname: { type: String, require: true },
lastname: { type: String, require: true },
email: { type: String, require: true }
});
module.exports = mongoose.model('Contact', ContactSchema);
Here's the code I used in the end.
$scope.createContact = function(contact) {
$scope.contact = { firstname: $scope.firstname, lastname: $scope.lastname, email: $scope.email };
$http.post('/contacts', $scope.contact)
.success(function(data) {
$scope.contact = {firstname:'',lastname: '', email:''}; // clear the form so our user is ready to enter another
$scope.contacts = data;
console.log(data);
})
.error(function(data) {
console.log('Error: ' + data);
});
};

How you structure your project is up to you. You could do it all in one file (but that's not very scalable), You could do one in each file (I wouldn't recommend it), or you could group them into semantic files like user_routes.js, social_media_routes.js, etc.
You are on the right track using $http.post() You'll want to create a JSON using your bound variables. You haven't included your entire controller so it's hard to tell you what to do. But a better way of doing this would probably just to create a JSON with empty values like this:
$scope.contact = {
firstname: '',
lastname: '',
email: '',
}
and then use something like ng-model="contact.firstname" for your data-binding. This will let you simply send $scope.contact to the back-end route.
The back-end route in Express would look something like:
var express = require('express');
var app = express();
app.post('/contacts', function (req, res) {
res.status(200).send(req)
}
This will send back what it receives - That should be enough to get you started - Handling POST requests in Express will depend on what version of Express you are using.

In the form tag add the attribute ng-submit to trigger directly in angular the post function.
<div id="contact-form" class="row">
<div class="col-sm-4 col-sm-offset-4 text-center">
<form ng-submit="createContact(user)">
<div class="form-group">
<input type="text" class="form-control input-lg text-center" placeholder="Firstname" name="firstname" ng-model="user.firstname">
</div>
<div class="form-group">
<input type="text" class="form-control input-lg text-center" placeholder="Lastname" name="lastname" ng-model="user.lastname">
</div>
<div class="form-group">
<input type="email" class="form-control input-lg text-center" placeholder="Email" name="email"ng-model="user.email">
</div>
<!-- Submit Contact -->
<button type="submit" class="btn btn-primary btn-lg">Add</button>
</form>
</div>
Add an empty user object in the controller:
$scope.user = {firstname:'',lastname: '', email:''};
Let the $http service handle the call:
$scope.createContact = function(user) {
$http.post('/contacts', user)
.then(function(data) {
//in data.data is the result of the call
},function(error) {
//here is the error if your call dont succeed
});};

Related

Server unable to find view for POSTbut can find it in GET

I have some code that is supposed to validate a user logging into my server, however it doesn't want to post it. My get request has no problem loading the very same "/login" as my post but for some reason it doesn't want to load it during the POST. Sorry if my code is a little inefficient and hard to read, still trying to get the hang of javascript.
app.post("/login", (req, res) => {
req.body.userAgent = req.get('User-Agent');
dataServiceAuth.checkUser(req.body).then((user) => {
req.session.user = {
userName: user.username,
email: user.email,
loginHistory: user.loginHistory
}
res.redirect('/employees');
}).catch((err) => {
res.render("login", {errorMessage: err, userName: req.body.userName});
});
});
and the function in the POST
module.exports.checkUser = function (userData) {
return new Promise(function (resolve, reject) {
User.find({ user: userData.userName }).exec().then((user) => {
if (user == undefined || user.length == 0) {
reject("Unable to find user: " + userData.userName);
}
else if (user[0].password != userData.password) {
reject("Incorrect Password for user: " + userData.userName);
}
else if (user[0].password == userData.password) {
users[0].loginHistory.push({dateTime: (new Date()).toString(), userAgent: userData.userAgent});
user[0].update({userName: userData.userName}, {$set: {loginHistory: user[0].loginHistory}}.exec().then((user) => {
resolve(user[0]);
}).catch((err) => {
reject("There was an error verifying the user: ${err}");
}))
}
}).catch((err) => {
reject("Unable to find user: " + userData.user);
});
});
};
My Tree looks like this
and my Handlebars file looks like this
<!DOCTYPE html>
<html lang="en">
<body>
<div class="container">
<div class="row">
<div class="col-md-12">
<h2>Log In</h2>
<hr />
{{#if errorMessage}}
<div class="alert alertdanger">
<strong>Error:</strong> {{errorMessage}}</div>
{{/if}}
<form method="post" action="/login">
<div class="row">
<div class="col-md-12">
<div class="form-group">
<input class="form-control" id="userName" name="userName" type="text" placeholder="User Name" required value=""
/>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-group">
<input class="form-control" id="password" name="password" type="password" placeholder="Password" required />
</div>
</div>
</div>
<input type="submit" class="btn btn-success pull-right" value="Login" />
</form>
</div>
</div>
</div>
</body>
</html>
Express version 4 and above requires extra middle-ware layer to handle POST request. This middle-ware is called as ‘bodyParser’. This used to be internal part of Express framework but here I think you need to install it separately like this npm install --save body-parser
Firstly, You should realize that requesting the same route through GET and POST methods does different things.
When you use the GET method, the reason that it has no problem loading the page is because (from what I assume) you would have specified a specific file (probably this login form) to be rendered when a request is received.
In case of the POST request though, you are carrying out operations on the form data sent with the request, and hence there could be a number of reasons you're facing issues with it. Maybe you haven't configured bodyParser to parse nested objects, as Yaswant's answer stated. Or maybe there's some other issue in your code.
It would be helpful if you could give a little more detail on what error you're facing, and if you could post your complete app.js file.

AngularJS + PHP. Login panel

I have very big problem with login panel. I am still learning AngularJS.
Can you help me with login panel? Here is my code guys. I don't know what I should do now:
api.php:
public function getLogin()
{
$sql = "SELECT login FROM users WHERE login='$username' AND password='$password'";
return $this->db->fetchAll();
}
$app->get('/login', function () use ($app, $DataProvider) {
$login = $DataProvider->getLogin();
return $app->json($login);
});
login.html:
<div class="row">
<div class="col-lg-10 col-sm-10 col-xs-12">
<div class="flat-panel">
<div class="flat-panel-header">
<h3 class="flat-panel-heading">Panel logowania</h3>
</div>
<div class="flat-panel-body">
<div class="form-group">
<input type="text" class="form-control" ng-model="loginInfo.username" placeholder="Podaj login">
</div>
<div class="form-group">
<input type="password" class="form-control" ng-model="loginInfo.password" placeholder="Podaj hasło">
</div>
<div class="form-group">
<button ng-click="loginUser()" class="btn btn-primary">Zaloguj</button>
</div>
</div>
</div>
</div>
</div>
services.js:
app.factory('login', ['$http', function($http){
var _getLogin = function (callback) {
callback = callback||function(){};
$http.get('/api.php/login')
.success(function (data) {
callback(data);
});
};
return {
getLogin: _getLogin
};
app.js:
app.controller("LoginController", function($scope, $http){
$scope.loginInfo = {
username: undefined,
password: undefined
}
$scope.loginUser = function(){
var data = {
username: $scope.loginInfo.username,
password: $scope.loginInfo.password
}
};
})
For angular you need token based authentication.
What is token based authentication?
I never use silex but I found this
https://gonzalo123.com/2014/05/05/token-based-authentication-with-silex-applications/
Another method is normal login form and when user login in see angular app, but this is bad when you try create mobile app.
Take a look at for example this:
https://scotch.io/tutorials/token-based-authentication-for-angularjs-and-laravel-apps
I recommend jwt auth it's very nice!

AngularJS reset form completely

I have a pretty big form that's being validated on the client side by Angular. I am trying to figure out how to reset the state of the form and its inputs just clicking on a Reset button.
I have tried $setPristine() on the form but it didn't really work, meaning that it doesn't clear the ng-* classes to reset the form to its original state with no validation performed.
Here's a short version of my form:
<form id="create" name="create" ng-submit="submitCreateForm()" class="form-horizontal" novalidate>
<div class="form-group">
<label for="name" class="col-md-3 control-label">Name</label>
<div class="col-md-9">
<input required type="text" ng-model="project.name" name="name" class="form-control">
<div ng-show="create.$submitted || create.name.$touched">
<span class="help-block" ng-show="create.name.$error.required">Name is required</span>
</div>
</div>
</div>
<div class="form-group">
<label for="lastName" class="col-md-3 control-label">Last name</label>
<div class="col-md-9">
<input required type="text" ng-model="project.lastName" name="lastName" class="form-control">
<div ng-show="create.$submitted || create.lastName.$touched">
<span class="help-block" ng-show="create.lastName.$error.required">Last name is required</span>
</div>
</div>
</div>
<button type="button" class="btn btn-default" ng-click="resetProject()">Reset</button>
</form>
And my reset function:
$scope.resetProject = function() {
$scope.project = {
state: "finished",
topic: "Home automation"
};
$("#create input[type='email']").val('');
$("#create input[type='date']").val('');
$scope.selectedState = $scope.project.state;
// $scope.create.$setPristine(); // doesn't work
}
Also if you could help me clear the input values of the email and date fields without using jQuery would be great. Because setting the $scope.project to what's defined above doesn't reset the fields for some reason.
Try to clear via ng-model
$scope.resetProject = function() {
$scope.project = {
state: "finished",
topic: "Home automation"
};
$("#create input[type='email']").val('');
$("#create input[type='date']").val('');
$scope.selectedState = $scope.project.state;
$scope.project = {
name: "",
lastName: ""
};
}
As mentioned in the comments, you can use $setUntouched();
https://docs.angularjs.org/api/ng/type/form.FormController#$setUntouched
This should set the form back to it's new state.
So in this case $scope.create.$setUntouched(); should do the trick
Ref all that jquery. You should never interact with the DOM via controllers. That's what the directives are for
If you want to reset a given property then do something like:
$scope.resetProject = function() {
$scope.project = {
state: "finished",
topic: "Home automation"
};
$scope.project.lastName = '';
$scope.project.date= '';
}

angularjs JavaScript inheritance, fail to bind data from view to a controller

what am trying to do is to get data from the form use it in my controller in HTTP post call but it's not working
I know i might have problem with inheritance of scopes but icant solve it.
here is my controller code:
.controller('SignUpCtrl', function($scope, $http, $state) {
$scope.submit = function() {
var url = 'http://localhost:3000/register';
var user = {
email: $scope.email,
password: $scope.password,
};
console.log($scope.user);
$http.post(url, user)
.success(function(res){
console.log('You are now Registered');
//$state.go('app.items');
})
.error(function(err){
console.log('Could not register');
// $state.go('error');
});
};
})
Here is the code of my Template:
<form name="register">
<div class="list">
<label class="item item-input no-border">
<input name="fullname" type="text" ng-model="fullname" placeholder="Full Name" required="">
</label>
<label class="item item-input">
<input name="email" type="email" ng-model="user.email" placeholder="Email" required="">
</label>
<p class="blue-font" ng-show="register.email.$dirty && register.email.$invalid">Please Write valid Email.</p>
<label class="item item-input">
<input name="password" type="password" ng-model="user.password" placeholder="Password" required="">
</label>
<button ng-click="submit();" ng-disabled="register.$invalid" type="submit" class="button signup-btn sharb-border white-font blue-bg-alt border-blue-alt ">
Sign Up
</button>
</div>
</form>
Note: i tried the ng-submit its not really the problem
Inside the controller.
.controller('SignUpCtrl', function($scope, $http, $state) {
$scope.user = {
email: '',
password: ''
};
$scope.submit = function() {
And this
var user = {
email: $scope.user.email,
password: $scope.user.password
};
Also drop the ; in ng-click
<button ng-click="submit()" ...>
Try to use rootScope (docs.angularjs.org/$rootScope").

AngularJs + php authentication

Hi i started learning AngularJs and now im trying to do my Login module using angular and php, but i have some issues. I have watched alot tutorials but none of them was helpful in my case, so here is what i have: controllers.js:
var controllers = angular.module('controllers', []);
controllers.controller('loginController', ['$scope', '$http', 'UserService', function(scope, $http, User) {
scope.main = [
{username: '', password: ''}
]
scope.login = function(){
var config = {
url: '../auth/login.php',
method: 'POST',
data: {
username: scope.main.username,
password: scope.main.password
},
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
}
$http(config)
.success(function(data,status,headers,config){
if(data.status){
//succefull login
User.isLogged = true;
User.username = data.username;
}
else{
User.isLogged = false;
User.username = '';
}
})
.error(function(data,status,headers,config){
User.isLogged = false;
User.username = '';
});
}
}])
auth.js:
var services = angular.module('services', []);
services.factory('UserService', [function(){
var sdo = {
isLogged: false,
username: ''
};
return sdo;
}]);
login.php:
$username = $_POST['username'];
if($username){
return "Logged";
}else{
return false;
}
and the html:
<div class="col-xs-12" id="loginCol" ng-controller="loginController">
<form ng-submit='login()' name="form" novalidate>
<div class="form-group">
<label for="username" class="sr-only">Username</label>
<input type="text" ng-model="scope.main.username" class="form-control" id="username" placeholder="Име..." />
<label for="password" class="sr-only">Password</label>
<input type="password" ng-model="scope.main.password" class="form-control" id="password" placeholder="Парола..." />
</div>
<div class="form-group pull-right">
<button type="button" class="btn btn-primary">Login</button>
<button type="button" class="btn btn-default">Register</button>
</div>
</form>
</div>
In this case i want just if user type something in the username input and hit the login button and on successful call of login.php to return some message. The problem is that code written like that got error "'loginController' is not a function, got undefined" how to fix it?
(Disclosure: I'm one of the developers of UserApp)
You could try the third-party service UserApp, together with the AngularJS module.
Check out the getting started guide, or take the course on Codecademy. Here's some examples of how it works:
Login form with error handling:
<form ua-login ua-error="error-msg">
<input name="login" placeholder="Username"><br>
<input name="password" placeholder="Password" type="password"><br>
<button type="submit">Log in</button>
<p id="error-msg"></p>
</form>
Signup form with error handling:
<form ua-signup ua-error="error-msg">
<input name="first_name" placeholder="Your name"><br>
<input name="login" ua-is-email placeholder="Email"><br>
<input name="password" placeholder="Password" type="password"><br>
<button type="submit">Create account</button>
<p id="error-msg"></p>
</form>
ua-is-email means that the username is the same as the email.
How to specify which routes that should be public, and which route that is the login form:
$routeProvider.when('/login', {templateUrl: 'partials/login.html', public: true, login: true});
$routeProvider.when('/signup', {templateUrl: 'partials/signup.html', public: true});
The .otherwise() route should be set to where you want your users to be redirected after login. Example:
$routeProvider.otherwise({redirectTo: '/home'});
Log out link:
<a href="#" ua-logout>Log Out</a>
Access user properties:
User info is accessed using the user service, e.g: user.current.email
Or in the template: <span>{{ user.email }}</span>
Hide elements that should only be visible when logged in:
<div ng-show="user.authorized">Welcome {{ user.first_name }}!</div>
Show an element based on permissions:
<div ua-has-permission="admin">You are an admin</div>
And to authenticate to your back-end services, just use user.token() to get the session token and send it with the AJAX request. At the back-end, use the UserApp API with the PHP library to check if the token is valid or not.
If you need any help, just let me know :)
You have created the application
var controllers = angular.module('controllers', []);
but didn't use it in the html code, add ng-app attribute to the wrapper div
<div class="col-xs-12" ng-app="controllers" id="loginCol" ng-controller="loginController">
the second issue, that you try to catch submit event, but don't submit the form, use submit type instead button
<button type="submit" class="btn btn-primary">Login</button>
or add ng-click="login()" attribute to the button and remove ng-submit='login()' from the form

Categories