Angular form submitting - javascript

I'm new in programming and need a little advice.
I create two tables in my database - Employee (with foreign key "emp_depId") and Department with values (HR, Tech, Finance). In order to create an employee I need emp_depId, but from select in my form I get depName. What can I do? I must send a request to the server and get all departments from DB and than in data binding call method with "depName" argument, which return me necessary Id. Than I'll assign it to employee.emp_DepId and save.
Here is my form:
<form novalidate #form="ngForm" (ngSubmit)="submitForm(form)" (reset)="resetForm()" >
<div class="form-group">
<label>First Name</label>
<input class="form-control" name="firstName" [(ngModel)]="employee.firstName" required />
</div>
<div class="form-group">
<label>Last Name</label>
<input class="form-control" name="lastName" [(ngModel)]="employee.lastName" required />
</div>
<div class="form-group">
<label>Department</label>
<select class="form-control" name="depName" [(ngModel)]="getDepId(department.depName)">
<option *ngFor="let depName of getDepartments(); let i = index" [value] = "depName[i]">
{{depName}}
</option>
</select>
</div>
<button type="submit" class="btn btn-primary"
[class.btn-warning]="editing" [disabled]="form.invalid">
{{editing ? "Save" : "Create"}}
</button>
<button type="reset" class="btn btn-secondary" routerLink="/">Cancel</button>
</form>
Am I right? Thank you.

As per your code you can do it like :
<select class="form-control" name="emp_DepId" [(ngModel)]="employee.emp_DepId">
<option *ngFor="let depName of getDepartments(); let i = index" [value] = "getDepId(depName)">
{{depName}}
</option>
</select>
But ideally it should be like this :
// output of getDepartments() should look like this
[
{ id : 1 , name : 'department 1'},
{ id : 2 , name : 'department 2'}
{ id : 3 , name : 'department 3'}
]
<select class="form-control" name="emp_DepId" [(ngModel)]="employee.emp_DepId">
<option *ngFor="let dep of getDepartments(); let i = index" [value] = "dep.id">
{{dep.name}}
</option>
</select>

Related

select2 sending id instead of text

I am making a erp website for that I am using select2 to auto fill products I am initializing select2 using an array that I create from the data that I receive from the server(products is an array of objects containing all the product details)
let data = products.map(product =>{return {id : product._id , text : product.product_name}});
//data = [{id : 1, text : 'al00'},{id : 2, text : 'al01'},{id : 3, text : 'al03'}]
$('.js-example-basic-single').select2({
data : data
});
The frontend looks perfect I am getting all the product names in the webpage
.js-example-basic-single is a select input in the form
when I submit this form I am getting id of the elements instead of the name of elements
<form
action="/create-barcodes"
id="create-barcodes-form"
method="POST">
<div id="barcode-wrapper">
<div class="form-group">
<label for="size">Product</label>
<div id="barcode-select-container">
<select
class="js-example-basic-single form-control"
id="barcode"
name="barcode">
</select>
</div>
<label for="quantity">quantity</label>
<input
type="number"
class="form-control mt-2"
name="quantity"
id="quantity"/>
</div>
</div>
<input
type="submit"
class="btn btn-primary"
value="Generate"
id="generate-barcode"/>
</form>
response I am receiving
{ barcode: '2', quantity: '52' }
response I am expecting
{ barcode: 'al01', quantity: '52' }

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>

Angular 4 Nested FormArrays Cannot read property 'push' of null

I cannot push to an array.
i have a segment(id, time) that can have one or several people (role, infos). the field are generated dynamically. On load the page shows the fields (see image below).
when try to add a person I get error : ERROR TypeError: Cannot read property 'push' of null
Here is the .ts code:
addPerson(index: number) {
//let personRows3 = <FormArray>this.mySummaryForm.get('personRows3');
let personRows3 = <FormArray>this.mySummaryForm.get(`segmentRows3.${index}.personRows3`)
personRows3.push(this.fb.group({
personR3: '',
personI3: ''
}));
}
segmentRows3: this.fb.array([
this.fb.group({
segmentId3: '',
segmentTime3: '',
personRows3: this.fb.array([
this.fb.group({
personR3: '',
personI3: ''
})
])
})
]),
The .html code
<div formArrayName="segmentRows3">
<div *ngFor=" let segmentRow of mySummaryForm.controls.segmentRows3.controls; let i=index " >
<div class="form-group" [formGroupName]="i" > {{i+1}}
<label for="segmentId3">Segment ID
<select formControlName="segmentId3" formControlName="segmentId3" placeholder="pick" type="text" id="segmentId3" class="form-control" [(ngModel)]="levelNumSegment3" (ngModelChange)="toNumberSegment3()">
<option *ngFor="let level of segmentId" [value]="level.num">{{level.name}}</option>
</select>
</label>
<label for="segmentTime3">Segment time
<input formControlName="segmentTime3" type="text" id="segmentTime3" class="form-control" placeholder="select a time" (ngModelChange)="onChange($event)">
</label>
<div formArrayName="personRows3">
<div *ngFor=" let personRow of segmentRow.controls.personRows3.controls; let j=index " >
<div class="form-group" [formGroupName]="j" > {{j+1}}
<label for="personR3">person Role
<input formControlName="personR3" [typeahead]="personRole" [typeaheadOptionsLimit]="10" [typeaheadMinLength]="0" type="text" id="personR3" class="form-control" placeholder="select a role" (ngModelChange)="onChange($event)" >
</label>
<label for="personI">Person infos
<input formControlName="personI3" [typeahead]="states" [typeaheadOptionsLimit]="10" [typeaheadMinLength]="0" type="text" id="personI3" class="form-control" placeholder="select infos" (ngModelChange)="onChange($event)" >
</label>
<label><span (click)="deletePerson(j)" class="btn btn-danger">Remove</span></label>
</div>
</div>
</div>
<br><button type="button" (click)="addPerson(j)" class="btn btn-info">Add a person</button><br><br><br>
</div>
</div>
</div>
The above error will occur when your personRows3 is null or don't have elements.
Add a check before pushing the elements,
if(personRows3){
personRows3.push(this.fb.group({
personR3: '',
personI3: ''
}));
}

How to set the object value in ng-model, in select tag, from an object array. and is there an easy way to add filters on ng-options,

Here is my html :
<body ng-controller="myCtrl">
{{loadDataSubject('${subjectList}')}}
{{loadDataTopic('${topicList}')}}
<h1 class = "bg-success" style="color: red;text-align: center">Fill in the below details for Question Template : -</h1> <br>
<div class="container">
<form method="get" action="createTemplate">
<div class="form-group">
<label for="sel1">Topics (select one):</label>
<select class="form-control" ng-model="selectedTopic" ng-options="topic.name as topic.name for topic in topics">
</select> <br>
{{selectedTopic}}
<label for="sel1">Subject (select one):</label>
<select name="subject" value= "" class="form-control" ng-model ="selectedSubject" ng-options="sub.name as sub.name for sub in subjects">
</select> <br>
<label for="sel1">Negative marking:</label>
<select class="form-control" name="negativeMarks">
<option>Yes</option>
<option>No</option>
</select> <br>
<label>Reference Book:</label>
<input type="text" class="form-control" name="ref" required>
<label for="sel1">Number of Questions:</label>
<input type="number" class="form-control" name="questionCount" required><br>
<input class ="bg-primary" type="submit" value="submit and download template">
</div>
</form>
</div>
</body>
and here is the script :
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http) {
$scope.subjects = [];
$scope.topics = [];
$scope.selectedSubject = {};
$scope.selectedTopic = {};
$scope.loadDataSubject = function(subjectList) {
$scope.subjects = JSON.parse(subjectList);
};
$scope.loadDataTopic = function(topicList) {
$scope.topics = JSON.parse(topicList);
};
});
I want to add a filter to options to selectonly the subjects of selected Topic,
something like filter : selectedTopic.id
Error is
angular.js:38 Uncaught Error: [$rootScope:infdig] http://errors.angularjs.org/1.4.8/$rootScope/infdig?p0=10&p1=%5B%5B%7B%22ms…turn%20b(f%2Cc%2Ce)%7D%22%2C%22newVal%22%3A74%2C%22oldVal%22%3A68%7D%5D%5D
at angular.js:38
at r.$digest (angular.js:15934)
at r.$apply (angular.js:16160)
at angular.js:1679
at Object.e [as invoke] (angular.js:4523)
at c (angular.js:1677)
at yc (angular.js:1697)
at Zd (angular.js:1591)
at angular.js:29013
at HTMLDocument.b (angular.js:3057)
before that i want to bind the value of object to ng-model, while the objects name gets binded. Please help me, I'm new with this.
subjects:
[{"subjectId":1,"name":"ComputerScience","code":"CS"},{"subjectId":2,"name":"Computer Basics","code":"CS","documentUrl":"None"},{"subjectId":3,"name":"Computer Basics","code":"CS","documentUrl":"None"},{"subjectId":4,"name":"php","code":"PHP01","documentUrl":"None"},{"subjectId":5,"name":"JAVA","code":"JAVA01","childSubjects":[{"subjectId":6,"name":"Core Java","code":"JAVA02","parentSubject":5,"childSubjects":[{"subjectId":8,"name":"Thread","code":"JAVA04","parentSubject":6},{"subjectId":9,"name":"Object Class","code":"JAVA05","parentSubject":6},{"subjectId":10,"name":"Inheritance","code":"JAVA06","parentSubject":6}]},{"subjectId":7,"name":"Advance Java","code":"JAVA03","parentSubject":5,"childSubjects":[{"subjectId":11,"name":"Servlet","code":"JAVA07","parentSubject":7}]}]},{"subjectId":12,"name":"Computer Basics","code":"CS","documentUrl":"None"}]
topics:
[{"topicId":1,"name":"Technical","code":"TECH","isSubjectsRelated":1,"description":"All Technical subjects","isActive":1,"subjects":[{"subjectId":1,"name":"ComputerScience","code":"CS"},{"subjectId":1,"name":"ComputerScience","code":"CS"}]},{"topicId":2,"name":"GATE","code":"GATE","isSubjectsRelated":1,"description":"GATE exam","isActive":1,"subjects":[]},{"topicId":5,"name":"Programming","code":"PROG","isSubjectsRelated":0,"description":"Coding skills","isActive":1,"subjects":[{"subjectId":5,"name":"JAVA","code":"JAVA01"}]}]
Change your Topics select-box to this
<label for="sel1">Topics (select one):</label>
<select class="form-control" ng-model="selectedTopic" ng-options="topic as topic.name for topic in topics">
</select>
And similarly for subject selectbox.Check out this plunker.

Generate dynamic form input fields and collect field data in an array in angularJS

I need to generate form input fields dynamically by clicking 'add sale' button on the form. which is accomplished
Also on change selected drop down, it get the price from the database and use the quantity to calculate the amount of that product.
if I click on 'add sale' button for another form generate the changes affect the previous one.
how to calculate the amount for each form independently and collect the data in it using angularJS?
this is controller
appcat.controller("MainCtrl", ['$scope', '$http', '$location', function ($scope, $http, $location)
{
//var quan = $scope.quantity;
$http.get('/api/pproduct').success(function (data)
{
$scope.pcategoryA = data;
});
// this controll the addition and removal
$scope.choices = [{ id: 'choice1' }];
//any time changes occurr it calculate the Amount
$scope.changedValue = function (item,quan)
{
if (item != null && quan !=null)
{
$http.get('/api/product/'+ item).success(function (data) // this is the price for that product from the Database
{
//this sets amount field
$scope.amount = parseFloat(data.price * quan);
});
}
}
// this generate a form
$scope.addNewChoice = function ()
{
var newItemNo = $scope.choices.length + 1;
$scope.choices.push({ 'id': 'choice' + newItemNo });
};
// this remove the form
$scope.removeChoice = function () {
var lastItem = $scope.choices.length - 1;
if ($scope.choices.length > 1) {
$scope.choices.splice(lastItem);
}
};
}]);
this is the html
<form class="form-inline" role="form" padding-left:10em">
<strong class="error">{{ error }}</strong>
<div class="form-group">
<label for="name">
Invoice No. :
</label>
<input type="text" class="form-control" id="name" ng-model="name" />
</div>
<br /><hr />
<div ng-controller="MainCtrl">
<fieldset data-ng-repeat="choice in choices">
<div class="form-group">
<label for="name">
Quantity :
</label>
<input type="text" class="form-control" id="quantity" ng-model="quantity" />
</div>
<div class="form-group">
<div class="form-group">
<label class="control-label"> Product : </label>
<select class="form-control" id="selected_id" ng-model="selected_id" ng-options="c.Value as c.Text for c in pcategoryA"
ng-change="changedValue(selected_id,quantity)">
<option value="">-- Select Category --</option>
</select>
</div>
</div>
<div class="form-group">
<label for="name">
Amount :
</label>
<input type="text" class="form-control" id="amount" ng-model="amount" ng-readonly="true" />
</div>
<button class="remove" ng-show="$last" ng-click="removeChoice()">-</button>
<br />
<hr />
</fieldset>
<button type="submit" class="col-sm-offset-10 addfields" ng-click="addNewChoice()">
Add Sale
</button>
</div>
</form>
thanks in advanced!!
You have to put 'amount' in choices array.
$scope.choices = [{ id: 'choice1', amount: 0}];
Then in controller:
$scope.changedValue = function (choise,item,quan)
choise.amount = parseFloat(data.price * quan);
And in tempalte:
ng-change="changedValue(choise,selected_id,quantity)">
<input type="text" class="form-control" id="amount" ng-model="choise.amount" ng-readonly="true" />

Categories