I have some trouble combining client side validation and server side validation in AngularJS. Here's the HTML:
<form class="form-login" name="loginForm" novalidate ng-submit="login()">
<fieldset>
<h2>Login</h2>
<input type="text" required class="input-block-level" placeholder="Username" ng-model="username" name="username">
<div ng-show="loginForm.username.$dirty && loginForm.username.$invalid">
<span ng-show="loginForm.username.$error.required">Username required.</span>
</div>
<input type="password" required class="input-block-level" placeholder="Password" ng-model="password" name="password">
<div ng-show="loginForm.password.$dirty && loginForm.password.$invalid">
<span ng-show="loginForm.password.$error.required">Password required.</span>
</div>
<div ng-show="loginForm.username.$dirty && loginForm.password.$dirty && loginForm.$invalid">
<span>Invalid username or password</span>
</div>
<p>Forgot password?</p>
<p><button class="btn btn-primary btn-large" ng-disabled="loginForm.$invalid" type="submit">Login</button></p>
</fieldset>
</form>
...and here's the login function:
$scope.login = function() {
$http.post('url', {
"password": $scope.password
}).success(function(data, status, headers, config) {
console.log(status);
console.log(data);
}).error(function(data, status, headers, config) {
if (404 === status) {
$scope.loginForm.$invalid = true;
}
});
return false;
}
The client side validation works fine until I submit the form and get back a 404 status. When the 404 status is returned the loginForm.$invalid error shows up but the client side validation doesn't change the form state back to valid when I change the username and password inputs again.
Is there a standard way to do this kind of client side + server side validation in the same form?
I don't think you're supposed to modify form $invalid or $valid directly. You should be doing it via $setValidity(validationErrorKey, isValid).
Why not just store "invalid username/password" status in a separate scope property?
$scope.login = function() {
$http.post('url', {
"password": $scope.password
}).success(function(data, status, headers, config) {
console.log(status);
console.log(data);
}).error(function(data, status, headers, config) {
if (404 === status) {
$scope.invalidUsernamePassword = true; // <--------------
}
});
return false;
}
And the template will be simpler:
<div ng-show="invalidUsernamePassword">
<span>Invalid username or password</span>
</div>
Here is a nice server side validation directive that might be usefull https://groups.google.com/forum/#!msg/angular/6v-AillQboI/D0OaZzV7Me0J
Related
SITUATION:
I used to check my recaptcha with a simple form submit with POST to "/login".
I need to change my implementation for security reasons and would like to do something like:
1) Jquery form submit.
2) Make call to server to call verify recaptcha on the server.
3) Receive response without reloading page.
4) Accept login request or not based on response.
QUESTION:
It looks like I could make an AJAX request ? But I don't know how.
CLIENT CODE:
<div class ="containerMargins">
<h1 class = "authTitle">Login</h1>
<form id="loginForm">
<div class="form-group">
<label>Email</label>
<input type="email" class="form-control" name="email" id="loginEmail" placeholder="You can't forget it :)" required>
</div>
<div class="form-group">
<label>Password</label>
<input type="password" class="form-control" name="password" id="loginPassword" placeholder="We hope you didn't forget it ^^" required minlength="12">
</div>
<div class="g-recaptcha" data-sitekey="6LcRrxMUAAAAANx-AXSdRLAo4Pyqfqg-1vuPSJ5c"></div>
<button class="btn btn-default" id="loginButton">Submit</button> <span class="userLinks">
<a class="logLinks" href="/users/register">Register</a>Password?</span>
</form>
</div>
</div>
<% include ../partials/indexScripts %>
<script>
$("#loginForm").submit(function(e) {
e.preventDefault();
var email = $("#loginEmail").val();
var password = $("#loginPassword").val();
// WOULD LIKE TO MAKE SERVER CALL HERE TO CHECK RECAPTCHA BUT I DONT KNOW HOW
$this = $(this);
$.ajax({
type: "POST",
url: "users/register",
data: $this.serialize()
}).done(function(data) {
if (successfulRecaptcha) {
firebase.auth().signInWithEmailAndPassword(email, password ).then( authData => {
}
else {
console.log("You are a robot!");
}
SERVER CODE:
router.post('/login', function(req, res, next) {
verifyRecaptcha(req.body["g-recaptcha-response"], function(success) {
if (success) {
} else {
}
});
});
I found the solution :
FRONT END:
$this = $(this);
$.ajax({
type: "POST",
url: "login",
data: $this.serialize()
}).done(function(data) {
if (data == true) {
BACKEND:
router.post('/login', function(req, res, next) {
verifyRecaptcha(req.body["g-recaptcha-response"], function(success) {
if (success) {
res.send(true);
} else {
res.send(false);
}
});
});
I am new to AngularJs. I am using a partial view for Create and Edit operation but facing some issue wile retrieving the data.
The data is being retrieved successfully from my MVC controller but is unable to populate the view.
Here is the JS I am using
(function (angular) {
'use strict';
angular.module('Sub_Ledger_Category_Create_app', [])
.controller('Sub_Ledger_Category_Create_ctrl', function ($scope, $http, $location) {
$scope.SubLedgerCategoryModel = {};
GetRequestType();
function GetRequestType() {
$http.get('/Common/Get_Action_Request')
.success(function (result) {
//debugger;
// $scope.SubLedgerCategoryModel = data;
if (result == "Create") {
$("#txt_Master_Subledger_Category").html("<h3 class='box-title'> Create Sub Ledger Category </h3>");
// $("#txt_Master_Accounting_Group_Group_id").val(0);
}
else {
$("#txt_Master_Subledger_Category").html("<h3 class='box-title'> Edit Sub Ledger Category</h3>");
//GetEditData();
$scope.GetEditData();
}
$("#Master_Subledger_Category").val(result)
NProgress.done();
})
.error(function (data, status, headers, config) {
NProgress.done();
$("div.failure").text("Unable to retrieve Request Type");
$("div.failure").fadeIn(300).delay(1500).fadeOut(400);
});
};
$scope.GetEditData = function () {
$http.get('/Master_Subledger_Category/GetEditData')
.success(function (data, status, headers, config) {
debugger;
$scope.SubLedgerCategoryModel = data;
console.log(data);
})
.error(function (data, status, headers, config) {
NProgress.done();
$("div.failure").text("Retrive Failure");
$("div.failure").fadeIn(300).delay(1500).fadeOut(400);
});
};
$scope.InsertSubledgerCategory = function () {
NProgress.start();
var Request_Type = $("#Master_Subledger_Category").val();
var Url_Master_Subledger;
if (Request_Type == "Create") {
Url_Master_Subledger = "/Master_Subledger_Category/Create_Master_Subledger_Category_Ajax";
}
else {
Url_Master_Subledger = "/Master_Subledger_Category/Test";
}
$http({
method: 'POST',
url: Url_Master_Subledger,
data: $scope.SubLedgerCategoryModel
}).success(function (data, status, headers, config) {
if (data.success === true) {
NProgress.done();
$("div.success").text("Successfully Created");
$("div.success").fadeIn(300).delay(1500).fadeOut(800);
$scope.SubLedgerCategoryModel = {};
console.log(data);
}
else {
NProgress.done();
$("div.failure").text("Saveing Failure");
$("div.failure").fadeIn(300).delay(1500).fadeOut(400);
}
}).error(function (data, status, headers, config) {
NProgress.done();
$("div.failure").text("Saveing Failure");
$("div.failure").fadeIn(300).delay(1500).fadeOut(400);
console.log($scope.message);
});
};
})
.config(function ($locationProvider, $sceProvider) {
$locationProvider.html5Mode({
enabled: true,
requireBase: false
});
$sceProvider.enabled(false);
});
})(angular);
Here is the HTML:
<div class="form-horizontal" ng-app="Sub_Ledger_Category_Create_app">
<div class="box-body" ng-controller="Sub_Ledger_Category_Create_ctrl">
<div class="form-group">
<label for="txt_Master_Subledger_Category_Name" class="col-sm-2 control-label">Sub Ledger Category</label>
<div class="col-sm-10">
<input class="form-control" ng-model="SubLedgerCategoryModel.Sub_Ledger_Cat_Name" id="txt_Master_Subledger_Category_Name" name="txt_Master_Subledger_Category_Name" autofocus placeholder="Sub Ledger Category">
<input ng-model="SubLedgerCategoryModel.Sub_Ledger_Cat_ID" name="txt_Master_Subledger_Category_ID" id="txt_Master_Subledger_Category_ID" hidden />
</div>
</div>
<!-- /.box-body -->
<div class="box-footer">
<button type="submit" value="Save" ng-click="InsertSubledgerCategory()" class="btn btn-info pull-right">Save</button>
<div class="text-red alert-box failure pull-right margin-r-5"></div>
<div class="text-green alert-box success pull-right margin-r-5"></div>
</div>
<!-- /.box-footer -->
</div>
</div>
Unfortunately I am unable to populate the view but in Console log I am able to view the data, helpful if anybody and help me.
AngularJs prevents loading HTML in this way by default. You might be getting an error on browser console: attempting to use an unsafe value in a safe context.
This is due to Angular's Strict Contextual Escaping (SCE) mode (enabled by default). Have a look to this for more information.
To resolve this issue you have 2 solutions:
$sce
$scope.thisCanBeusedInsideNgBindHtml = $sce.trustAsHtml(someHtmlVar);
ngSanitize: include the angular-sanitize.min.js resource and add the dependency in module.
hope this will help.
I have only changed the following
scope.SubLedgerCategoryModel = data;
to
scope.SubLedgerCategoryModel = data[0]:
and its resolved my issue.
Along with the form values, I need additional data to be passed to the PHP script- I have a javascript function "cart.items()" which returns the stringified items that have been selected in the cart. How do I pass this value to the PHP function?
form.html
<div ng-controller="formCtrl">
<input type="text" ng-model="name" class="input-medium search-query" placeholder="Name" required >
<input type="email" ng-model="email" class="input-medium search-query" placeholder="Email" required >
<input type="text" ng-model="message" class="input-medium search-query" placeholder="Message" required >
<button type="submit" class="btn" ng-click="formsubmit(userForm.$valid)" ng-disabled="userForm.$invalid">Submit </button>
</form>
App.js
controller("formCtrl", ['$scope', '$http', function ($scope, $http) {
$scope.url = 'http://localhost/ShoppingCart/ShoppingCart/email.php';
$scope.formsubmit = function (isValid) {
if (isValid) {
$http.post($scope.url, { 'name': $scope.name, "email": $scope.email, "message": $scope.message, "items": $scope.items }).
success(function (data, status) {
// console.log(data);
$scope.items = "this is scope";
$scope.status = status;
$scope.data = data;
$scope.result = data;
//window.location.assign("email.php");
//alert($scope.items);
})
} else {
alert('Form is not valid');
}
index.php
<?php
$post_date = file_get_contents("php://input");
$echo("I want the result of the cart.items() function here");
?>
To make http call use like this. Change according to your ajax call
var requestSignin = {
method: 'POST',
url: your url,
headers: {
"Content-Type" : "text/plain"
},
data: {
field 1: $scope.signinData.email,
field 2: $scope.signinData.password,
.
.
field n .
},
timeout: 30000
};
$http(requestSignin)
.success(function(data) { console.log(data);
}).errror(){
}
Send your fields in data object.
And your php code should be like this.
$post_date = json_decode(file_get_contents("php://input"));
To get the input from request.
while returning from php use json_encode()
Ex:
echo json_encode($cities);
I have a standard login page. When the database validates the credentials entered by the user I want to make changes to the page, example: create element saying "Login Successful", using a static javascript file. How do I communicate to a static javascript file that the login was successful thus triggering the changes? I'm using Parse right now for my database.
html:
<form class="form" method="post">
<div>
<label>Username:</label>
<input class="form-control" id="username" type="text" name="username">
</div>
<div>
<label>Password:</label>
<input class="form-control" id="password" type="password" name="password">
</div>
<input class="btn btn-custom" type="submit" id="loginSubmit" name="loginSubmit" value="Submit">
</form>
Node with Express and Parse:
login.post('/login', function (req, res) {
Parse.User.logIn(req.body.username, req.body.password, {
success: function(user) {
console.log("Login Successful!");
res.redirect('/');
},
error: function(user, error) {
res.redirect('/login');
console.log("Login Unsuccessful! " + error.message);
}
});
});
The solution was using jQuery's Ajax method.
$('#loginSubmit').on('click', function () {
$.ajax({
//...
success: function(data, textStatus, xhr) {
console.log(xhr.status);
if (xhr.status === 200) {
console.log("fun time?");
$('body').css("background-color", "yellow");
}
},
complete: function(xhr, textStatus) {
console.log(xhr.status);
}
});
});
I am newbie to Angular.js so i am facing a problem while calling the function in directives from index.html.
When the user enter his phone number i have to call function in Directives.js which is to validate is the number is already exist or not. But i am not getting how to call the function.
my html page
<div class="form-group" ng-class="{ 'has-error' : userForm.contactno.$invalid && (userForm.contactno.$dirty || submitted) }">
<label>ContactNo</label>
<input type="text" name="contactno" class="form-control" ng-model="user.phone" placeholder="Your Contact No" ng-pattern="/^[789]\d{9}$/" maxlength="10">
<p ng-show="userForm.contactno.$error.pattern && (userForm.contactno.$dirty || submitted)" class="help-block">Enter a valid contactno.</p>
</div>
my Directive.js file:
myAppDirectives.
directive('phone', function() {
return {
restrice: 'A',
require: 'ngModel',
link: function(scope, element, attrs, ctrl) {
console.log("test1");
angular.element(element).bind('blur', function() {
var phnNum = this.value;
$.ajax({
url: 'http://localhost:8989/users/'+phnNum,
dataType: 'application/json',
type: 'GET',
success: function( data, status, headers, cfg ){
console.log("test2");
console.log("data" +data);
console.log(jqXHR.responseText);
},
error: function( jqXHR, textStatus, errorThrown ){
console.log("on success");
var result=jqXHR;
//console.log("check" +result.responseText);
console.log(jqXHR);
console.log(result.responseText.length);
if(result.responseText.length===0){
console.log("you can register now");
}
else{
console.log("User with this number is already registered");
}
}
});
});
}
}
});
Can anyone please help me how to call phone() function in directives from my html page.
Thanks in advance
Add the phone directive to your <input> element
<input phone type="text" name="contactno" class="form-control" ng-model="user.phone" placeholder="Your Contact No" ng-pattern="/^[789]\d{9}$/" maxlength="10">
You can put your directive phone as a attribute in input box:-)
<input phone type="text" name="contactno" class="form-control" ng-model="user.phone" placeholder="Your Contact No" ng-pattern="/^[789]\d{9}$/" maxlength="10">
But here is the thing don't use $.ajax it is not a angular function if you want asyn calls use $http that is native service in angular js.
$http.get('/someUrl').
success(function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
}).
error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
Doc