Use class object as parameter in function to add to array - javascript

I would like to do a simple base where I can add memebers to array. I change a "Tour of Heroes" from Angular tutorial (link). What I want to do is instead of passing name (string) to function I would like to give a whole class object (User). I use form where user is typing his name and surname (and city if he want). I have no idea how to get from input to function this whole object, instead of list of string parameters. Here is my code:
form.html:
<div class="form-group">
<label for="Name">Name</label>
<input type="text" class="form-control" id="Name" required name="nameField" [(ngModel)]="ngModel" #nameField="ngModel" >
<div [hidden]="nameField.valid || nameField.pristine" class="alert alert-danger">Name is required</div>
</div>
<div class="form-group">
<label for="surname">surname</label>
<input type="text" class="form-control" id="surname" required name="surnameField" ngModel #surnameField="ngModel">
<div [hidden]="surnameField.valid || surnameField.pristine" class="alert alert-danger">Surname is required</div>
</div>
<div class="form-group">
<label for="city">City</label>
<input type="text" class="form-control" id="city" name="city" ngModel #cityField="ngModel" >
</div>
<button type="submit" class="btn btn-success" [disabled]="!userForm.form.valid">Submit</button>
</form>
function on submit:
onSubmit(name: string, surname: string, city: string ): void{
name = name.trim();
surname = surname.trim();
city = city.trim();
this.myservice.create(name, surname, city)
.then(newUser => this.arrayUsers.push(newUser));
}
And function create inside myservice:
private headers = new Headers({'Content-Type': 'application/json'});
private heroesUrl = 'api/mainArray'; // URL to web api
create(name: string, surname: string, city?: string): Promise<User> {
return this.http
.post(this.heroesUrl, JSON.stringify({name: name, surname:surname, city:city}), {headers: this.headers})
.toPromise()
.then(res => res.json().data as User);
}

Declare the ngModel attribute to bind each input to the form :
For example :
<input type="text" class="form-control" id="name" ngModel required name="nameField" >
<input type="text" class="form-control" id="surname" ngModel required name="surnameField" >
<input type="text" class="form-control" id="city" ngModel required name="cityField" ngModel >
And in the form element, give a name to the form to be able to bind it in the component and add the form as parameter in the onSubmit() method :
<form #f="ngForm" (ngSubmit)="onSubmit(f)" >
Now you should be able to retrieve the user with the f.value property :
onSubmit(f: NgForm): void{
this.myservice.create(f.value)
.then(createdUser=> this.arrayUsers.push(createdUser));
}
More information here : https://angular.io/api/forms/NgModel

Related

getElementById return empty values so post empty values

I'm working with DOM and web API to POST some information about the company like name, worker's name.
But when I write something in the input DOM can't reach the value and return empty so I post an empty object.
That looks like :
adress: ""
companyName: ""
contactName: ""
contactTitle: ""
My form block:
<form>
<div class="form-group">
<label for="">Company Name</label>
<input
type="text"
class="form-control"
id="companyName"
placeholder="Company Name!"
/>
</div>
<div class="form-group">
<label for="">Contact Name</label>
<input
type="text"
class="form-control"
id="contactName"
placeholder="Contact Name!"
value=""
/>
</div>
<div class="form-group">
<label for="">Contact Title</label>
<input
type="text"
class="form-control"
id="contactTitle"
placeholder="Contact Title!"
/>
</div>
<div class="form-group">
<label for="">Country</label>
<input
type="text"
class="form-control"
id="inputCountry"
placeholder="Country!"
/>
</div>
</form>
And my JS code:
'use strict';
let inputCompanyName = document.getElementById('companyName');
let inputContactName = document.getElementById('contactName');
let inputContactTitle = document.getElementById('contactTitle');
let country = document.getElementById('inputCountry');
const btnSubmit = document.getElementById('submit');
let newCompany = {
companyName: inputCompanyName.value,
contactName: inputContactName.value,
contactTitle: inputContactTitle.value,
adress: country.value,
};
btnSubmit.addEventListener('click', e => {
e.preventDefault();
axios
.post('https://northwind.vercel.app/api/suppliers', newCompany)
.then(res => {
console.log('Response', res.data);
alert('Success!');
});
});
I tried innerHTML and innerText and form method but I cant solve this problem.
You're reading the values immediately upon loading the page, long before the user has had a chance to enter any values.
Instead, read the values in the click event:
btnSubmit.addEventListener('click', e => {
let newCompany = {
companyName: inputCompanyName.value,
contactName: inputContactName.value,
contactTitle: inputContactTitle.value,
adress: country.value,
};
// the rest of the click handler logic...
});

Select Option in AngularJS returning object not value

I'm still learning AngularJS, so im not quite sure as to the best way to implement this;
I'd be fine with doing this in ordinary HTML, but wasn't able to use the "selected" property, so i switched to an Angular element - which im new to using.
I have a form, with a Drop down box, where the user selects either "User" or "Administrator". A User has the value of "2", where Administrator has the value of "1".
By default, 'User' is the pre-selected item in the list.
My problem is, when the form is being submitted (via AJAX) to PHP, the form is submitting an Object like {value : "2", name : "User"} where i want it to just submit the value, ie: "2".
HTML code:
<div class="form-group col-md-6">
<label for="usrlevel">User Level:</label>
<select class="form-control form-control-sm"
data-ng-init="formData.usrlevel = usrlevels[0]"
data-ng-model="formData.usrlevel"
data-ng-options="x.name for x in usrlevels">
</select>
</div>
Javascript Code:
app.controller("admController", function ($scope, $http, $location) {
$scope.usrlevels = [
{value : "2", name : "User"},
{value : "1", name : "Administrator"}
];
$scope.addForm = function() {
var ans="";
$http({
method : 'POST',
url : 'php/addstaff.php',
data : $.param($scope.formData),
headers : { 'Content-Type': 'application/x-www-form-urlencoded' } //set the headers so angular passing info as form data (not request payload)
}).then(function (response) {
console.log(response.data);
ans = response.data;
if (!ans.success) {
// Add Error handling
} else {
$('#addModal').modal('hide');
$scope.getStaff(); //refreshes table display
}
}).catch(function(response){
console.log(response.data);
});
};
And here's an image of the debugger, showing that for 'usrlevel' the form is submitting an object, when it should just be submitting the value of the selected item.
Thus, in the debugger, it should just be showing usrlevel:"2"
UPDATE:
As people seem to be under the impression that only the userlevel should be submitted by the AJAX call (I thought the debugger window image would make it clear that the userlevel is 1 element in the form) here's the actual HTML form.
<form data-ng-submit="addForm()" name="addform" method="POST">
<div class="form-group">
<label for="name">Full Name:</label>
<input type="text" class="form-control form-control-sm" name="name" data-ng-model="formData.name" id="name" placeholder="">
</div>
<div class="form-group">
<label for="address">Address:</label>
<input type="text" class="form-control form-control-sm" name="address" data-ng-model="formData.address" id="address" placeholder="">
</div>
<div class="form-group">
<label for="suburb">Suburb:</label>
<input type="text" class="form-control form-control-sm" name="suburb" data-ng-model="formData.suburb" id="suburb" placeholder="">
</div>
<div class="form-group">
<label for="phone">Phone:</label>
<input type="tel" class="form-control form-control-sm" name="phone" data-ng-model="formData.phone" id="phone" placeholder="">
</div>
<div class="form-row">
<div class="form-group col-md-6">
<label for="postcode">Post Code:</label>
<input type="text" class="form-control form-control-sm" name="postcode" data-ng-model="formData.postcode" id="postcode" placeholder="">
</div>
<div class="form-group col-md-6">
<label for="usrlevel">User Level:</label>
<select class="form-control form-control-sm" data-ng-init="formData.usrlevel = usrlevels[0]" data-ng-model="formData.usrlevel" data-ng-options="x.name for x in usrlevels"></select>
</div>
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="email" class="form-control form-control-sm" name="email" data-ng-model="formData.email" id="email" placeholder="">
</div>
<div class="form-group">
<label for="suburb">Password:</label>
<input type="password" class="form-control form-control-sm" name="password" data-ng-model="formData.password" id="password" placeholder="">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
<button type="reset" value="Reset" class="btn btn-secondry">Clear</button>
You are asking why u get whole object on select and not only value selected.
This is because you used
data-ng-options="x.name for x in usrlevels"
Which will set X to model on select, if you want only name/any other attr of x to be set to model you need to use
data-ng-options="x.value as x.name for x in usrlevels" data-ng-model="formData.value"
As tell angular select x show it as y.
to make default selection work
now you need to update $score.formData.value with value of selected user object.
so forexample in ur controller
app.controller("admController", function ($scope, $http, $location) {
$scope.usrlevels = [
{value : "2", name : "User"},
{value : "1", name : "Administrator"}
];
$scope.formData = { value: "1"} // prepare formData and set user with value 1 (Admin) to be selected by default
finally send whole formData.
http({
method : 'POST',
url : 'php/addstaff.php',
data : $scope.formData,
headers : { 'Content-Type': 'application/x-www-form-urlencoded' } //set the headers so angular passing info as form data (not request payload)
}).then(function (response) {
...etc
Again pass only wt u need to data of ajax, dont pass whole object!
Problem is with your model. Well, an easy to understand syntax would look like this
angular.module("app",[]).controller('ctrl', function($scope){
$scope.users= [{value : "2", name : "User"},{value : "1", name : "Admin"}]
$scope.user = "2";
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl" >
<select ng-model="user">
<option ng-repeat="i in users" value="{{i.value}}">{{i.name}}</option>
</select>
Value is : {{user}}
</div>
And now you can use $scope.user as selected value to send wherever you want.
To send it as payload to your request, you can use something like
..
data : {"userLevel" :$scope.user },
..
Use the as clause in ng-options:
<div class="form-group col-md-6">
<label for="usrlevel">User Level:</label>
<select class="form-control form-control-sm"
̶d̶a̶t̶a̶-̶n̶g̶-̶i̶n̶i̶t̶=̶"̶f̶o̶r̶m̶D̶a̶t̶a̶.̶u̶s̶r̶l̶e̶v̶e̶l̶ ̶=̶ ̶u̶s̶r̶l̶e̶v̶e̶l̶s̶[̶0̶]̶"̶
data-ng-model="formData.usrlevel"
̶d̶a̶t̶a̶-̶n̶g̶-̶o̶p̶t̶i̶o̶n̶s̶=̶"̶x̶.̶n̶a̶m̶e̶ ̶f̶o̶r̶ ̶x̶ ̶i̶n̶ ̶u̶s̶r̶l̶e̶v̶e̶l̶s̶"̶>̶
data-ng-options="x.value as x.name for x in usrlevels">
</select>
</div>
Also the initial value of the ng-model should be set to a primitive instead of an object:
$scope.formData.usrlevel = $scope.usrlevels[0].value;
It is better to POST data as application/json, but if your backend only supports application/x-www-form-urlencoded, use the AngularJS built-in param serializer:
$scope.addForm = function() {
var ans="";
$http({
method : 'POST',
url : 'php/addstaff.php',
̶d̶a̶t̶a̶ ̶ ̶ ̶ ̶:̶ ̶$̶.̶p̶a̶r̶a̶m̶(̶$̶s̶c̶o̶p̶e̶.̶f̶o̶r̶m̶D̶a̶t̶a̶)̶,̶
data : $scope.formData,
transformRequest: $httpParamSerializerJQLike,
headers : { 'Content-Type': 'application/x-www-form-urlencoded' } //set the headers so angular passing info as form data (not request payload)
})
As others had mentioned, there was a problem with ng-options which is why it returned an object and not just the value.
But then, after changing ng-options it no longer had 'User' as the default selected item in the drop down - and this was then a problem with ng-init.
Old HTML
<select class="form-control form-control-sm"
data-ng-init="formData.usrlevel = usrlevels[0]"
data-ng-model="formData.usrlevel"
data-ng-options="x.name for x in usrlevels">
</select>
New HTML
<select class="form-control form-control-sm"
data-ng-model="formData.usrlevel"
data-ng-init="formData.usrlevel = formData.usrlevel || usrlevels[0].value"
data-ng-options="x.value as x.name for x in usrlevels">
</select>

Very simple ngModel example

I have a simple form
<form role="form" (submit)="login()">
<input type="text" name="username" id="username" required="required" [ngModel]="credentials.username"/>
<input type="password" name="password" id="password" required="required" [ngModel]="credentials.password" />
<button type="submit">Sign in</button>
</div>
</form>
and a component ts.
export class LoginComponent implements OnInit {
credentials = {username: '', password: ''};
constructor(private loginService: LoginService, private http: HttpClient, private router: Router) { }
ngOnInit() { }
login() {
console.log(this.credentials);
this.loginService.authenticate(this.credentials, () => {
this.router.navigateByUrl('/');
});
return false;
}
}
service
authenticate(credentials, callback) {
console.log(credentials);
const headers = new HttpHeaders(credentials ? {
authorization : 'Basic ' + btoa(credentials.username + ':' + credentials.password)
} : {});
}
My problem is that the credentials are always ''. Shouldn't the ngModel update these values automatically?
You should use [(ngModel)] to set values like this -
<input type="text" name="username" id="username" placeholder="Username" required="required" [(ngModel)]="credentials.username"/>
<input type="password" name="password" id="password" placeholder="Password" required="required" [(ngModel)]="credentials.password" />
As of now, you are using [ngmodel] which is just attribute binding to set value into your DOM and display it back.
But if you want to update value from view part you should use two way data binding [(ngModel)]
You have to use [(ngModel)] instead of [ngModel]
<input type="text" name="username" id="username" placeholder="Username" required="required" [(ngModel)]="credentials.username"/>
<input type="password" name="password" id="password" placeholder="Password" required="required" [(ngModel)]="credentials.password" />
because [( in Angular is signalling a two-way data binding. Theoretically you could only bind to an event (ngModel) or to a value [ngModel]. But in this case you need to use two-way data binding : [(ngModel)]

How to compare values in Angularjs?

I'm a newbie to angular, so I need a help.
In html, I wrote the following
<div class="form-group">
<input type="email" name="Email" id="LoginEmail class="form-control" placeholder="Email Address" required>
</div>
<div class="form-group">
<input type="password" name="password" id="LoginPassword" class="form-control" placeholder="Password" required>
</div>
In angular, I write the following code
angular
.module("LoginForm", [])
.controller("processingLoginForm", ["$scope", function ($scope) {
$scope.userinfo = [
{name : "User1",
account : "user1#whatever.com",
city: "XYZ",
password: "Angular#2017"}
];
}]);
I need to compare the value of input box with the value of the script and show a message if it's not correct, so how can I do that?
Firstly you need to assign model to your template scope. Use ng-model for this purpose. Then you need a form to submit and trigger a function to check if user input matches to the desired values.
Add ng-model and wrap your inputs with a form tag:
<form ng-submit="login()">
<div class="form-group">
<input ng-model="email" type="email" name="Email" id="LoginEmail" class="form-control" placeholder="Email Address" required>
</div>
<div class="form-group">
<input ng-model="password" type="password" name="password" id="LoginPassword" class="form-control" placeholder="Password" required>
</div>
<button type="submit">Login</button>
</form>
Check if user input is valid in Controller:
$scope.login = function() {
const isUserValid = $scope.email === $scope.userinfo[0].account && $scope.password === $scope.userinfo[0].password;
if(isUserValid) {
alert("Logged In Successfully");
}else {
alert("Email or password incorrect. Try again.")
}
}
Here's a working example of the above code.
In your input elements you miss the ng-model attribute. It is used to bind the values with your scope variables.
<input type="email" ... ng-model="email" ...>
<input type="password" ... ng-model="password" ...>
And in your controller you can write
if($scope.email == $scope.userinfo[0].account && $scope.password == $scope.userinfo[0].password){
//Login ok
}else{
//Login failed
}
Assuming there is a form element somewhere above
Add ng-submit to it
<form ng-submit="submit()">
Add ng-model to the form elements.
I have added state.email and state.password
<div class="form-group">
<input ng-model="state.email" type="email" name="Email" id="LoginEmail" class="form-control" placeholder="Email Address" required>
</div>
<div class="form-group">
<input ng-model="state.password" type="password" name="password" id="LoginPassword" class="form-control" placeholder="Password" required>
</div>
Compare the binding values to the values in $scope.userinfo
angular
.module("LoginForm", [])
.controller("processingLoginForm", ["$scope", function ($scope) {
$scope.userinfo = [{
name : "User1",
account : "user1#whatever.com",
city: "XYZ",
password: "Angular#2017"
}];
// when you submit the form, this function will be called
$scope.submit = function (e) {
e.preventDefault();
if ($scope.state.email !== $scope.userinfo[0].account || $scope.state.password !== $scope.userinfo[0].password) {
// did not match
} else {
// matched
}
}
}]);

How to use $asyncValidators with angularjs and set a warning message in the HTML

This is my first bigger form with validations and etc.
I've created a Registration form and I'm using ng-messages for validation. The problem is that I need to validate the username, does it already exist in the JSON server that we are using or it's available. Of course, if it's taken the warning pops out in the HTML where the username input is, if it's available the submit button is no more disabled (because the form will be $valid) and the user can register. I want to use angular-sanitize because I found this (I don't know if they are related):
ngModel.$asyncValidators.uniqueUsername = function(modelValue, viewValue) {
var value = modelValue || viewValue;
// Lookup user by username
return $http.get('/api/users/' + value).
then(function resolved() {
//username exists, this means validation fails
return $q.reject('exists');
}, function rejected() {
//username does not exist, therefore this validation passes
return true;
});
};
Here is the code I use now (reg form, controller and service):
// Controller:
export default class registerPageController {
constructor(userService, authenticationService, $location) {
this.register = "Register";
this.userService = userService;
this.$location = $location;
this.authenticationService = authenticationService;
this.hasLoggedIn = false;
}
onSubmit(user) {
let self = this;
let {
name,
age,
email,
username,
password
} = user;
self.userService.register(name, age, email, username, password).then((res) => {
self.userService.login(username, password).then(function (response) {
let data = response.data;
if (data.length) {
let user = data[0];
self.hasLoggedIn = true;
self.authenticationService.setCredentials(username, password);
self.$location.path('/');
}
});
})
.catch(err => {
// WHAT TO PUT HERE AFTER THE USERNAME EXIST VALIDATION ?
})
}
}
// Service:
export class UserService {
constructor($http) {
this.$http = $http;
}
login(username, password) {
return this.$http({
method: 'GET',
url: 'http://localhost:3000/users',
params: {
username: username,
password: password
}
});
}
register(name, age, email, username, password) {
return this.$http({
method: 'POST',
url: 'http://localhost:3000/users',
data: {
name: name,
age: age,
email: email,
username: username,
password: password
}
});
}
// SHOULD I PUT HERE THE USERNAME EXIST VALIDATION LOGIC ?
}
<div class="container main-content">
<form class="registrationForm" name="registerForm" ng-submit="register.onSubmit(register.user)" novalidate="novalidate">
<!-- Enter Name -->
<div class="form-group">
<label for="name" class="control-label"><span id="reqInfo">*</span> Name</label>
<input type="text" name="name" class="form-control" ng-model="register.user.name" ng-pattern="/[a-zA-Zа-яА-Я]+/" id="name"
required="" placeholder="Example: Petar Petrov">
<div ng-messages="registerForm.name.$error" ng-show="registerForm.name.$touched" style="color:maroon" role="alert">
<div ng-message="required">Your name is required</div>
</div>
</div>
<!-- User Age-->
<div class="form-group">
<label for="age" class="control-label"><span id="reqInfo">*</span> Age</label>
<input type="number" name="age" class="form-control" ng-model="register.user.age" ng-min="18" min="18" id="age" required=""
placeholder="Enter your age">
<div ng-messages="registerForm.age.$error" ng-show="registerForm.age.$touched" style="color:maroon" role="alert">
<div ng-message="min">You must be at leats 18 years old</div>
</div>
</div>
<!-- Enter E-mail -->
<div class="form-group">
<label for="email" class="control-label"><span id="reqInfo">*</span> E-mail</label>
<input type="email" name="email" class="form-control" ng-model="register.user.email" ng-pattern="/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=\+\$,\w]+#)?[A-Za-z0-9\.\-]+|(?:www\.|[\-;:&=\+\$,\w]+#)[A-Za-z0-9\.\-]+)((?:\/[\+~%\/\.\w\-_]*)?\??(?:[\-\+=&;%#\.\w_]*)#?(?:[\.\!\/\\\w]*))?)/"
id="email" required="" placeholder="Example: mail#mail.net">
<div ng-messages="registerForm.email.$error" ng-show="registerForm.email.$touched" style="color:maroon" role="alert">
<div ng-message="required">Your valid e-mail is required</div>
</div>
<br>
<!-- Enter Username -->
<div class="form-group">
<label for="username" class="control-label"><span id="reqInfo">*</span> Username</label>
<input type="text" name="username" ng-minlength="5" ng-maxlength="20" class="form-control" ng-model="register.user.username"
ng-pattern="/^[A-Za-z0-9_]{1,32}$/" ng-minlength="7" id="username" required="" placeholder="Enter your username">
<div ng-messages="registerForm.username.$error" style="color:maroon" role="alert">
<div ng-message="minlength">Your Username must be between 7 and 20 characters long</div>
</div>
<br>
<!-- Enter Password -->
<div class="form-group">
<label for="password" class="control-label"><span id="reqInfo">*</span> Password</label>
<input type="password" name="password" class="form-control" ng-model="register.user.password" ng-minlength="7" id="password"
required="" placeholder="Enter your password">
<div ng-messages="registerForm.password.$error" style="color:maroon" role="alert">
<div ng-message="minlength">You Password must be at least 7 symbols long</div>
</div>
</div>
<!-- Register button -->
<div class="form-group">
<button class="btn btn-primary" type="submit" ng-disabled="!registerForm.name.$valid || !registerForm.age.$valid || !registerForm.email.$valid || !registerForm.username.$valid || !registerForm.password.$valid">Register</button>
</div>
<p>Fields with <span id="reqInfo">*</span> must be filled.</p>
</form>
</div>
Important is to know that I have being told explicitly to write it in ES6.
I have problem with the logic so look at my code and please fill it for me so I can use it and most important - learn it :S
Thank you so so much in advance!
I have implemented a directive for different kind of validations (sync Async), and it supports warning as well.
You may check it from
`https://plnkr.co/2WQHOo`
If this is what you needed and need more information, let me know I will try my best to answer.

Categories