I'm facing one issue with a registration form.
If I log in and browser offers me to save username/password, they are both displayed on the registration form.
I tried to reset the form, I tried to set user details to null, but it didn't work.
As username and password are predefined, repeat password error is present.
here is a snap
Register Controller
...
registerController.$inject = ['$location', 'UsersService', '$timeout'];
function registerController($location, UsersService, $timeout) {
var vm = this;
vm.master = {};
vm.isValid = false;
vm.error = false;
vm.errorMessage = "";
vm.user = {
username : '',
password : '',
email: ''
}
formReset();
// function to submit the form after all validation has occurred
vm.submitForm = function(isValid) {
// check to make sure the form is completely valid
if (isValid) {
console.info('form valid');
vm.isValid = true;
}
if(vm.isValid === true){
signup();
}
else{
vm.error = true;
vm.errorMessage = "All fields are required";
}
};
function signup() {
// initial values
vm.error = false;
vm.success = false;
var username = vm.user.username;
var password = vm.user.password;
// call register from service
UsersService.register(username, password)
// handle success
.then(function () {
vm.success = true;
vm.successMessage = "Registrations successful.You'll get confirmation email soon and you can proceed with login";
$timeout(function() {
$location.path('/login');
}, 5000);
})
// Catch error
.catch(function (fallback) {
vm.error = true;
vm.errorMessage = fallback;
});
};
function formReset(form){
if(form === '' || form === undefined){
form = vm.form;
}
if(form){
form.$setPristine();
form.$setUntouched();
form.$setValidity();
}
vm.contact = angular.copy(vm.master);
}
}
jade template
form.form-horizontal.col-md-12(name="form" role="form", data-ng-submit="ctrl.submitForm(form.$valid)", method="post" novalidate, autocomplete="off")
.form-group(show-errors)
label.control-label.col-xs-3 Username
span.icon-req.glyphicon.glyphicon-asterisk
.col-xs-9
input.form-control(type="text", name="username", placeholder="Enter Username", data-ng-model="ctrl.user.username", data-user-id="{{ctrl.user._id}}", data-ng-minlength="3", required="required" auth-username)
span.help-inline.error(data-ng-show = "form.$dirty && form.username.$error.required") Username required
span.help-inline.error(data-ng-show = "form.$dirty && form.username.$error.minlength") Username too short
span.help-inline.error(data-ng-show = "ctrl.form.username.$touched && ctrl.form.username.$error.usernameExists") Username already taken
.form-group(show-errors)
label.control-label.col-xs-3 Password
span.icon-req.glyphicon.glyphicon-asterisk
.col-xs-9
input.form-control(type="password", name="password", placeholder="Password", data-ng-model="ctrl.user.password", data-ng-minlength="6",ng-maxlength="16", required="required")
span.help-inline.error(data-ng-show = "form.$dirty && form.password.$error.required") Password required
span.help-inline.error(data-ng-show = "form.$dirty && form.password.$error.minlength || form.password.$error.maxlength") Password must be 6-16 character long
.form-group(show-errors)
label.control-label.col-xs-3 Repeat password
span.icon-req.glyphicon.glyphicon-asterisk
.col-xs-9
input.form-control(type="password", name="repeatPassword", placeholder="Repeat Password", data-ng-model="ctrl.user.repeatPassword", data-ng-minlength="4",required="required", equal-to="ctrl.user.password")
span.help-inline.error(data-ng-show = "form.$dirty && form.repeatPassword.$error.equalTo") Password must be equal
....
button.btn.btn-default(type="submit") Submit
a(href='/')
button.btn.btn-primary(type="button") Cancel
I'm pretty much new to mean stack development, and I'm sure I miss something out.I appreciate your help. Thanks
PS: the code posted is a simplified and not optimized one
So first I try with the HTML autocomplete Attribute. But it was not working on chrome. After that I found this post Chrome Browser Ignoring AutoComplete=Off.
One of the solution to disable autocomplete is to set the input readonly and add a bit of js on the onfocus Attribute.
onfocus="this.removeAttribute('readonly')
I test this solution with an angular form and it's working.
See the original fiddle by fizzix
Related
I have the following markup in a form mixed with some asp.net razor:
<div class="account-form__field-container" ng-show="postcodeRequired()" ng-cloak>
#Html.LabelFor(x => x.Postcode)
#Html.TextBoxFor(x => x.Postcode, new { #class = "account-form__field", placeholder = "Postcode here...", ng_required = "postcodeRequired()",ng_validpostcode="", ng_model = "postcode", ng_init = "postcode = '" + Model.Postcode + "'" })
#Html.ValidationMessageFor(x => x.Postcode, null, new { #class = "account-form__error-message" })
<span class="account-form__error-message" ng-show="registrationForm.$submitted && registrationForm.Postcode.$error.required" ng-cloak>
Please enter your postcode
</span>
<span class="account-form__error-message" ng-show="registrationForm.$submitted && !validPostCode()" ng-cloak>
Please enter valid postcode
</span>
</div>
I have a dropdown which will show hide the postcode field, so if uk selected the postcode field will show. The field is required but additionally I am doing a check in whether is a valid postcode via a webservice. The angular controller that deals with form submission looks like:
$scope.submitForm = function () {
$scope.registrationForm.$submitted = true;
if ($scope.enableSubmit()) {
registrationForm.submit();
}
};
$scope.postcodeRequired = function () {
return $scope.country === 'United Kingdom';
};
$scope.validPostCode = function () {
if ($scope.postcodeRequired()) {
if ($scope.postcode !== undefined && $scope.postcode.length > 5) {
postcodeService.ValidatePostCode($scope.postcode).success(function (response) {
return response;
});
} else {
return false;
}
}
return true;
};
$scope.enableSubmit = function () {
return $scope.registrationForm.$valid
&& $scope.passwordsMatch()
&& $scope.acceptTerms
&& $scope.validPostCode();
};
The postCodeService is just doing an http get to validate the post code that returns true or false. The issue i have is on submitting it validates the postcode but then goes into a loop and gives the following error:
angular.min.js:34 Uncaught Error: [$rootScope:infdig] http://errors.angularjs.org/1.4.0/$rootScope/infdig?p0=10&p1=%5B%5D
at angular.min.js:34
at m.$digest (angular.min.js:563)
at m.$apply (angular.min.js:571)
at l (angular.min.js:373)
at O (angular.min.js:388)
at XMLHttpRequest.N.onload (angular.min.js:392)
I have seen other people with this issue when doing an ng-repeat but as you can see I am not doing that.
Any ideas?
Without a plunkr to test against and verify its hard to tell exactly what is causing the infinite digest cycle loop. However I believe it might be cause by the amount of calls made towards your $scope.validPostCode function (which wasn't correctly returning its validity). Basically the change proposed is to only call the validate function when the postcode has been changed (trigged by ng-change on the field). The result of that function sets $scope.validPostCode variable to true or false, which is then what is checked for validity;
HTML (add ng-change to the input)
#Html.TextBoxFor(x => x.Postcode, new { <!-- other attributes -->, ng_change = "validatePostCode()" })
JavaScript
$scope.postcodeRequired = function () {
return $scope.country === 'United Kingdom';
};
// by default its not valid
$scope.validPostCode = false;
// our Validition check
$scope.validatePostCode = function () {
if ($scope.postcodeRequired()) {
if ($scope.postcode !== undefined && $scope.postcode.length > 5) {
postcodeService.ValidatePostCode($scope.postcode).success(function (response) {
$scope.validPostCode = response;
});
} else {
$scope.validPostCode = false;
}
} else {
$scope.validPostCode = true;
}
};
// call our function to properly set the initial validity state.
$scope.validatePostCode();
$scope.enableSubmit = function () {
return $scope.registrationForm.$valid
&& $scope.passwordsMatch()
&& $scope.acceptTerms
&& $scope.validPostCode;
};
I was working with this project, it is linked to mongodb, it was working perfectly, so I could register new users, edit and save them. I format my laptop, then I cloned my project but it doesn't work anymore, when I try to register a new user it gives me the error: "NEXT IS NOT A FUNCTION", I haven't modified anything. I don't know really what happened. I have tried it in a different laptop and it works. So I have to keep working on it but I can't because of it.
I leave some code in case if it is something wrong.
Thanks!
server.js
var express = require("express"); // ExperssJS Framework
var app = express(); // Invoke express to variable for use in application
var port = process.env.PORT || 5555; // Set default port or assign a port in enviornment
var morgan = require("morgan"); // Import Morgan Package
var mongoose = require("mongoose"); // HTTP request logger middleware for Node.js
var bodyParser = require("body-parser"); // Node.js body parsing middleware. Parses incoming request bodies in a middleware before your handlers, available under req.body.
var router = express.Router(); // Invoke the Express Router
var appRoutes = require("./app/routes/api")(router); // Import the application end points/API
var path = require("path"); // Import path module
var passport = require("passport"); // Express-compatible authentication middleware for Node.js.
var social = require("./app/passport/passport")(app, passport); // Import passport.js End Points/API
app.use(morgan("dev")); // Morgan Middleware
app.use(bodyParser.json()); // Body-parser middleware
app.use(bodyParser.urlencoded({ extended: true })); // For parsing application/x-www-form-urlencoded
app.use(express.static(__dirname + "/public")); // Allow front end to access public folder
app.use("/api", appRoutes); // Assign name to end points (e.g., '/api/management/', '/api/users' ,etc. )
//
// <---------- REPLACE WITH YOUR MONGOOSE CONFIGURATION ---------->
//
mongoose.connect(
"mongodb://localhost:27017/databasename",
{ useNewUrlParser: true },
function(err) {
if (err) {
console.log("Not connected to the database: " + err); // Log to console if unable to connect to database
} else {
console.log("Successfully connected to MongoDB"); // Log to console if able to connect to database
}
}
);
// Set Application Static Layout
app.get("*", function(req, res) {
res.sendFile(path.join(__dirname + "/public/app/views/index.html")); // Set index.html as layout
});
// Start Server
app.listen(port, function() {
console.log("Running the server on port " + port); // Listen on configured port
});
-
userCtrl.js
angular
.module("userControllers", ["userServices"])
// Controller: regCtrl is used for users to register an account
.controller("regCtrl", function($http, $location, $timeout, User, $scope) {
var app = this;
// Custom function that registers the user in the database
this.regUser = function(regData, valid, confirmed) {
app.disabled = true; // Disable the form when user submits to prevent multiple requests to server
app.loading = true; // Activate bootstrap loading icon
app.errorMsg = false; // Clear errorMsg each time user submits
// If form is valid and passwords match, attempt to create user
if (valid && confirmed) {
app.regData.name = app.regData.firstName + " " + app.regData.lastName; // Combine first and last name before submitting to database
// Runs custom function that registers the user in the database
User.create(app.regData).then(function(data) {
// Check if user was saved to database successfully
if (data.data.success) {
app.loading = false; // Stop bootstrap loading icon
$scope.alert = "alert alert-success"; // Set class for message
app.successMsg = data.data.message + "...Redirecting"; // If successful, grab message from JSON object and redirect to login page
// Redirect after 2000 milliseconds (2 seconds)
$timeout(function() {
$location.path("/login");
}, 2000);
} else {
app.loading = false; // Stop bootstrap loading icon
app.disabled = false; // If error occurs, remove disable lock from form
$scope.alert = "alert alert-danger"; // Set class for message
app.errorMsg = data.data.message; // If not successful, grab message from JSON object
}
});
} else {
app.disabled = false; // If error occurs, remove disable lock from form
app.loading = false; // Stop bootstrap loading icon
$scope.alert = "alert alert-danger"; // Set class for message
app.errorMsg = "Please ensure form is filled our properly"; // Display error if valid returns false
}
};
// Custom function that checks if username is available for user to use
this.checkUsername = function(regData) {
app.checkingUsername = true; // Start bootstrap loading icon
app.usernameMsg = false; // Clear usernameMsg each time user activates ngBlur
app.usernameInvalid = false; // Clear usernameInvalid each time user activates ngBlur
// Runs custom function that checks if username is available for user to use
User.checkUsername(app.regData).then(function(data) {
// Check if username is available for the user
if (data.data.success) {
app.checkingUsername = false; // Stop bootstrap loading icon
app.usernameMsg = data.data.message; // If successful, grab message from JSON object
} else {
app.checkingUsername = false; // Stop bootstrap loading icon
app.usernameInvalid = true; // User variable to let user know that the chosen username is taken already
app.usernameMsg = data.data.message; // If not successful, grab message from JSON object
}
});
};
// Custom function that checks if e-mail is available for user to use
this.checkEmail = function(regData) {
app.checkingEmail = true; // Start bootstrap loading icon
app.emailMsg = false; // Clear emailMsg each time user activates ngBlur
app.emailInvalid = false; // Clear emailInvalid each time user activates ngBlur
// Runs custom function that checks if e-mail is available for user to use
User.checkEmail(app.regData).then(function(data) {
// Check if e-mail is available for the user
if (data.data.success) {
app.checkingEmail = false; // Stop bootstrap loading icon
app.emailMsg = data.data.message; // If successful, grab message from JSON object
} else {
app.checkingEmail = false; // Stop bootstrap loading icon
app.emailInvalid = true; // User variable to let user know that the chosen e-mail is taken already
app.emailMsg = data.data.message; // If not successful, grab message from JSON object
}
});
};
app.addUser = function() {
if (app.showTheForm) {
app.showTheForm = false;
app.expand = false;
} else {
app.showTheForm = true;
app.expand = true;
}
};
})
// Custom directive to check matching passwords
.directive("match", function() {
return {
restrict: "A", // Restrict to HTML Attribute
controller: function($scope) {
$scope.confirmed = false; // Set matching password to false by default
// Custom function that checks both inputs against each other
$scope.doConfirm = function(values) {
// Run as a loop to continue check for each value each time key is pressed
values.forEach(function(ele) {
// Check if inputs match and set variable in $scope
if ($scope.confirm == ele) {
$scope.confirmed = true; // If inputs match
} else {
$scope.confirmed = false; // If inputs do not match
}
});
};
},
link: function(scope, element, attrs) {
// Grab the attribute and observe it
attrs.$observe("match", function() {
scope.matches = JSON.parse(attrs.match); // Parse to JSON
scope.doConfirm(scope.matches); // Run custom function that checks both inputs against each other
});
// Grab confirm ng-model and watch it
scope.$watch("confirm", function() {
scope.matches = JSON.parse(attrs.match); // Parse to JSON
scope.doConfirm(scope.matches); // Run custom function that checks both inputs against each other
});
}
};
});
Node.js
{ ValidationError: User validation failed: username: next is not a
function, password: next is not a function, email: next is not a function, name: next is not a function
at ValidationError.inspect (D:\Documents\Trabajo\gorotasnewest\node_modules\mongoose\lib\error\validation.js:56:24)
at ValidationError.deprecated (internal/util.js:70:15)
at formatValue (util.js:467:31)
at inspect (util.js:328:10)
at Object.formatWithOptions (util.js:182:12)
at Console.(anonymous function) (console.js:188:15)
at Console.log (console.js:199:31)
at D:\Documents\Trabajo\gorotasnewest\app\routes\api.js:70:17
at D:\Documents\Trabajo\gorotasnewest\node_modules\mongoose\lib\model.js:4423:16
at $__save.error (D:\Documents\Trabajo\gorotasnewest\node_modules\mongoose\lib\model.js:379:16)
at D:\Documents\Trabajo\gorotasnewest\node_modules\kareem\index.js:246:48
at next (D:\Documents\Trabajo\gorotasnewest\node_modules\kareem\index.js:167:27)
at Kareem.execPost (D:\Documents\Trabajo\gorotasnewest\node_modules\kareem\index.js:217:3)
at _handleWrapError (D:\Documents\Trabajo\gorotasnewest\node_modules\kareem\index.js:245:21)
at D:\Documents\Trabajo\gorotasnewest\node_modules\kareem\index.js:272:14
at _next (D:\Documents\Trabajo\gorotasnewest\node_modules\kareem\index.js:94:14)
errors:
{ username:
{ ValidatorError: next is not a function
at new ValidatorError (D:\Documents\Trabajo\gorotasnewest\node_modules\mongoose\lib\error\validator.js:25:11)
at validate (D:\Documents\Trabajo\gorotasnewest\node_modules\mongoose\lib\schematype.js:805:13)
at D:\Documents\Trabajo\gorotasnewest\node_modules\mongoose\lib\schematype.js:854:11
at Array.forEach ()
at SchemaString.SchemaType.doValidate (D:\Documents\Trabajo\gorotasnewest\node_modules\mongoose\lib\schematype.js:814:19)
I am new to Angular and I am trying to add data from forum into the database, to do so i need the id of the current user which i get with no problem, only in my post method I rely entirely on the data that i get from the forum, but in the forum i wouldn't of course ask for the id to be filled so I need to add it automatically to my controller and i don't know how to do so : here is the function that I use in my controller :
app.addFT = function () {
//Get the current user Id
Auth.getUser().then(function (data) {
console.log(data.data.email);
Compte.getComptebymail(data.data.email).then(function(result)
{
console.log(result.data.col.IdCollaborateur);
lecollaborateur.push(result.data.col);
$scope.lecollaborateur = lecollaborateur;
});
});
console.log(app.addData);
//we connect it to the back end of the application
FT.createFT(app.addData).then(function (data) {
if(data.data.success){
//create success message
app.loading = false;
app.successMsg = data.data.message + '...Redirection';
//Redirect to show projet
$timeout(function () {
$location.path('/FeuillesTempsListe');
}, 2000);
}else{
//create an error message
app.loading = false;
app.errorMsg = data.data.message;
}
});
};
app.addData is the data the user fills in the view : I get the name,description,...but I don't know how to pass the Id to app.addData other then using the forum, I tried :
app.addData.Id=lecollaborateur.Id; but it's not working , any suggestions ?
You need call createFT only after the success call of getComptebymail.
So that you will have id in the app.addData.
app.addFT = function() {
//Get the current user Id
Auth.getUser().then(function(data) {
console.log(data.data.email);
Compte.getComptebymail(data.data.email).then(function(
result) {
console.log(result.data.col.IdCollaborateur);
lecollaborateur.push(result.data.col);
$scope.lecollaborateur = lecollaborateur;
app.addData.Id = lecollaborateur.Id;
console.log(app.addData);
//we connect it to the back end of the application
FT.createFT(app.addData).then(function(data) {
if (data.data.success) {
//create success message
app.loading = false;
app.successMsg = data.data.message +
'...Redirection';
//Redirect to show projet
$timeout(function() {
$location.path(
'/FeuillesTempsListe'
);
}, 2000);
} else {
//create an error message
app.loading = false;
app.errorMsg = data.data.message;
}
});
});
});
};
I have scope called $scope.users which returns all the users in my app like so,
[{"id":1,"name":"Peter Boomsma"},
{"id":2,"name":"Jan Jansen"},
{"id":3,"name":"Kees Keesen"},
{"id":4,"name":"Piet Pietersen"}]
Then I have a scope called $scope.current_user which returns the current users, and the id's of the users he's following,
{"id":4,"name":"Piet Pietersen","following":[
{"id":1},{"id":2},{"id":4}]
}
I have a ng-repeat that shows all the users, and a followUser action per user,
%ul{"ng-repeat" => "user in users"}
%li
name: {{ user.name }}
%a{"ng-click" => "followUser(user)"} Follow user.
The problem is that I can't differentiate between a user that's already being followed, and a user that's not being followed. So the action followUser is always there. I would like to give the users the current user is following a different action, such as unfollowUser.
I got the id's of the users that the current user is following, but I don't know how to give those users a other button. Something like unfollowUser.
* update *
I've got it working (somewhat at least), by using Mihail his suggestion,
When I go to my user template I load the userCtrl,
usersService.loadUsers().then(function(response) {
$scope.users = response.data;
angular.forEach(response, function(user){
$scope.user = user
$scope.isFollowed = function(userId) {
var following = $scope.current_user.following;
for (var i=0; i<following.length; i++) {
if (following[i].id == userId) {
return true;
}
}
return false;
}
})
})
And in my template I have,
%ul{"ng-repeat" => "user in users"}
%li
name: {{ user.name }}
%a{"ng-click" => "followUser(user)", "ng-show" => "!isFollowed(user.id)"} follow
%a{"ng-click" => "unfollowUser(user)", "ng-show" => "isFollowed(user.id)"} unfollow
This works fine. When a user is followed then the unfollowUser function is used. The problem is that when I unfollow the user the view doesn't get updated. I have to refresh the page to see the effect of the unfollow action.
I've tried putting a init at the end of the unfollowUser action like so,
$scope.unfollowUser = function(user){
unfollowFriend.unfollowFriend(user).then(function(){
},function(){
}).then(init);
Notification.success(user.name + ' is verwijderd als vriend.');
}
The init,
var init = function(){
console.log ('renew')
usersService.loadUsers().then(function(response) {
$scope.users = response.data;
angular.forEach(response, function(user){
$scope.user = user
$scope.isFollowed = function(userId) {
var following = $scope.current_user.following;
for (var i=0; i<following.length; i++) {
if (following[i].id == userId) {
return true;
}
}
return false;
}
})
})
}
I get the renew message in my browser log, but the view isn't updated.
I am not good at haml, so I will write a simple html example:
<div ng-repeat="user in users">
<div ng-show="isFollowed(user.id)" ng-click="unfollowUser(user)">unfollow</div>
<div ng-show="!isFollowed(user.id)" ng-click="followUser(user)">follow</div>
</div>
$scope.isFollowed = function(userId) {
var following = $scope.current_user.following;
for (var i=0; i<following.length; i++) {
if (following[i].id == userId) {
return true;
}
}
return false;
}
You can make a function that check if a given user is already followed like:
$scope.isFollowed = function (userID) {
//check if the userID is in$scope.current_user.following
//return a boolean
}
then in the HTML code you can check based on this function if to show followUser or unfollowUser.
I know there are a few older questions with related topics, but I have not found a satisfactory answer to this, plus those answers seem to be for older versions of Angularjs.
My issue is a form with angular validation and ng-submit does not fire after it has been submitted once, even after the model data has been reset, and the form has been untouched and set to pristine.
After the first submission, the form resets visually as expected and validates properly if used a second time, including activating the submit button when validation passes. Comparing the form code before any submissions and after reset produces identical HTML. Clicking submit brings up the preloader as designed. However the ng-submit action won't fire...
$scope.resetMediaForm = function() {
$scope.uploadMedia = {};
$scope.uploadMedia.from = ''
$scope.uploadMedia.message = ''
$scope.uploadMedia.file = null;
$scope.uploadMedia.fileType = '';
$scope.uploadMedia.fileName = '';
$scope.uploadMedia.done = false;
$scope.uploadMedia.error = '';
if ($scope.mediaForm) {
$scope.mediaForm.$setUntouched();
$scope.mediaForm.$setPristine();
//$('form[name="'+$scope.mediaForm.$name+'"]')[0].reset();
}
};
$scope.resetMediaForm();
$scope.uploadMedia.submit = function() {
var data = {
from: $scope.uploadMedia.from,
message: $scope.uploadMedia.message,
file: $scope.uploadMedia.file,
fileType: $scope.uploadMedia.fileType,
fileName: $scope.uploadMedia.fileName
};
plotRemoteAPI.postMedia(data, function (data, status) {
if (status >= 200 && status < 300) {
if (data.success === true) {
$scope.resetMediaForm();
} else {
$scope.uploadMedia.error = data.error;
}
} else {
$scope.uploadMedia.error = status;
}
}, function (data, status) {
$scope.uploadMedia.error = data.error;
});
};
Plunkr: http://embed.plnkr.co/zO3lEqa7sfqYDvjHRnqa/preview
You are calling $scope.resetMediaData(); in your submit handler which destroys the $scope.uploadMedia object including your submit function (and it doesn't get redeclared). I just moved $scope.uploadMedia = {}; outside the resetMediaData() function.
http://plnkr.co/edit/OhRwsfnx3rX3gXZ2bilc?p=preview