Angular JS Forms submit not sending ID - angularjs

I am trying to send the course id to the controller in a form button, but it does not seem to work. The controller logs the vm.add.year correctly but vm.add.course gets undefined. Why?
index.html:
<form method="post" ng-submit="vm.addCourseToYear()">
<table class="table">
<tr ng-repeat="course in vm.courses | filter:search">
<td>{{course.courseName}}</td>
<td><select id="addCourse" name="addCourse" class="form-control" ng-model="vm.add.year" required>
<option value="year1"> Year1 </option>
</select></td>
<td><input style="display:none" ng-value="course._id" ng-model="vm.add.course">
<button type="submit" class="btn btn-primary" id="{{course._id}}">Add</button>
</td>
</tr>
</table>
</form>
index.controller.js
function addCourseToYear(){
console.log(vm.add.course);
console.log(vm.add.year);
};

I would do the following to fix this:
Add ng-click directive to button:
<button type="submit"
class="btn btn-primary"
ng-click="vm.addCourseToYear(vm.add)"
id="{{course._id}}">Add</button>
Remove the form action leaving just form:
<form>
Change the function to take a parameter:
function addCourseToYear(newItem){
console.log(newItem.course);
console.log(newItem.year);
};
Change this to initialize vm.add.course as course._id:
<td>
<input style="display:none" ng-init="vm.add.course = course._id" ng-model="vm.add.course">
<button type="submit" class="btn btn-primary" id="{{course._id}}">Add</button>
</td>
This follows the patterns found on Angular's site: https://docs.angularjs.org/guide/forms

try changing the code to this:
<form method="post" ng-submit="vm.addCourseToYear(vm.add.course._id)">
hope this solves your issue .. :)

display:none removes the object from the from,
change it to visibility: hidden;position:absolute
<input style="visibility:hidden;position:absolute;" ng-value="course._id" ng-model="vm.add.course">

Related

Object not added to one $scope variable but to all others

Everytime I want to add a form to fill out a new contact person of a customer company I call this function:
$scope.addContact = () => {
$scope.selectedCustomer.contacts.push({});
console.log(JSON.stringify($scope.selectedCustomer));
};
But I noticed there is one customer that magically loses that contact object at somepoint after the method is called and I don't know why, because in the debugger only some standard angularjs methods are executed that shouldn't play a role in this and I don't understand them.
Usually the console looks like this:
1st, 2nd and 3rd click on add contact button results in:
{"id":135,"masterData":{},"name":"Normal Test","contacts":[{}]}
{"id":135,"masterData":{},"name":"Normal Test","contacts":[{"$$hashKey":"object:2205"},{}]}
{"id":135,"masterData":{},"name":"Normal Test","contacts":[{"$$hashKey":"object:2205"},{"$$hashKey":"object:2207"},{}]}
But for one object (so far, but I think there are more) the same situation prints this:
{"id":150,"masterData":{},"name":"Test AG","contacts":[{}]}
{"id":150,"masterData":{},"name":"Test AG","contacts":[{}]}
{"id":150,"masterData":{},"name":"Test AG","contacts":[{}]}
As you see there is an empty object added but not saved, every time I click add contact again, the contacts array is empty at first.
In the mongo db those two customers look exactly the same:
What else can I analyze to find out where the problem is and what to do about it?
EDIT
By debugging I found the place where the workflow traverses a different path when it's not working:
contentscript.js, line 1114 var observerHandler = function(mutations) {... is traversed when it works, but not reached during the failing process - it is called after: return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? jQuery.event.dispatch.apply( elem, arguments ) : undefined; in jquery.js, line 5013.
My HTML:
<div class="form-group">
<label for="contacts" class="col-sm-3 control-label">Ansprechpartner</label>
<div class="col-sm-9">
<table id="contacts" ng-if="selectedCustomer.contacts.length"
class="table-condensed" cellpadding="10">
<tr>
<th>Name</th>
<th>Telefon</th>
<th>E-Mail</th>
</tr>
<tr ng-repeat="contact in selectedCustomer.contacts">
<td>
<a class="delete" ng-hide="readonly" ng-click="deleteContact(contact)">
<i class="fa fa-minus-circle"></i>
</a>
<input type="text" class="form-control"
ng-readonly="readonly" ng-model="contact.name"
placeholder="keine Angabe">
</td>
<td>
<input type="text" class="form-control" ng-readonly="readonly"
ng-model="contact.phone" placeholder="keine Angabe"/>
</td>
<td>
<input type="text" class="form-control" ng-hide="readonly"
ng-model="contact.email" placeholder="keine Angabe"/>
<a href="mailto:{{contact.email}}" ng-show="readonly">
<input type="text" class="form-control"
ng-readonly="readonly" ng-model="contact.email"
placeholder="keine Angabe"/>
</a>
</td>
</tr>
</table>
<div class="addContact" ng-hide="readonly">
<button class="btn btn-default btn-block btn-sm" ng-click="addContact()"
type="button">+ Ansprechpartner hinzufügen...
</button>
</div>
</div>
</div>

Angular post call with scala,play

I want to call angular controller through scala.html file.and angular controller should redirect to scala controller to insert data.
I am getting the list from database through same approach .
but during insert it is not able to call function inside angular controller.
Scala html (interns.scala.html):
#import repository.Interns
#(dataList:play.api.libs.json.JsValue,internForm:Form[Interns])(implicit message:Messages)
#main("List Interns"){
<div ng-app="internApp">
<div ng-controller="InternCtrl">
<table class="table">
<tr>
<th >Id</th>
<th >Name</th>
<th >Email-Id</th>
<th >Mobile No.</th>
<th >Address</th>
<th >Emergency Contact No.</th>
<th></th>
<th><input type="submit" value="Add New Intern" class="btn btn-success" data-toggle="modal" data-target="#addIntern"> </th>
</tr>
<tr ng-repeat="intern in #dataList" class="danger">
<td>{{intern.id}}</td>
<td>{{intern.name}}</td>
<td>{{intern.email}}</td>
<td>{{intern.mobile}}</td>
<td>{{intern.address}}</td>
<td>{{intern.emergency}}</td>
<td> <input type="submit" value="Edit" class="btn btn-primary" data-toggle="modal" data-target="#addIntern"></td>
<td><input type="submit" value="Delete" class="btn btn-danger"> </td>
</tr>
</table>
</div>
</div>
<div ng-app="internApp">
<div ng-controller="AddCtrl">
<div class="modal fade" id="addIntern" role="dialog">
<div class="modal-dialog">
<div class="modal-content" style="height:700px;text-align:center;width:500px">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h1 class="modal-title">Add Intern</h1>
</div>
<form>
<input type="text" placeholder="Name" class="text" ng-model="name" size="30">
<br>
<br>
<input type="text" placeholder="Email" class="text" ng-model="email" size="30">
<br>
<br>
<input type="text" placeholder="Mobile Number" class="text" ng-model="mobile" size="30">
<br>
<br>
<input type="text" placeholder="Address" class="text" ng-model="address" size="30">
<br>
<br>
<input type="text" placeholder="Emergency Contact" class="text" ng-model="emergency" size="30">
<br>
<br>
<input type="submit" class="btn btn-primary" **ng-click="save()"** value="Add Intern" >
<br><br>
</form>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="#routes.Assets.versioned("javascripts/list.js")"></script>
}
Angular controller (list.js):
var internApp = angular.module('internApp', []);
internApp.controller('AddCtrl', function ($scope, $http){
alert("hello")
$scope.save = function(){
var data1 = {"id":8,"name":$scope.name,"email":$scope.email,"mobile":$scope.mobile,"address":$scope.address,"emergency":$scope.emergency};
$http({
method:'POST',
url:'/addNew',
data: JSON.stringify(data1),
contentType: 'application/json',
dataType:'json'
})
}})
internApp.controller('InternCtrl', function ($scope, $http){
$http.get('/list').success(function(data) {
$scope.dataList=data;
});
});
This one works for me without any problems:
https://jsfiddle.net/w3vyak05/2/
As you can see - you see the alert and I added a small part where after submission you see the data underneath the form. Of course in your application you would make the HTTP POST call there.
What is different from your approach:
I am using <form ng-submit="save()"> instead of ng-click. Please be careful when switching - you don't want to end up mixing the two:
Warning: Be careful not to cause "double-submission" by using both the ngClick and ngSubmit handlers together. See the form directive documentation for a detailed discussion of when ngSubmit may be triggered.
What else to keep in mind (sorry, off-topic but had to write it down):
In your code you have this: <input type="submit" class="btn btn-primary" **ng-click="save()"** value="Add Intern" > - I guess you just wanted to draw our attention to the ng-click but do not forget to remove the asterisks.
Your list is populated because this is the only "action" which is executed once the Angular controller has been loaded (just wanted to explain why the one controller is working and the other not).
You are using different syntax for making an HTTP POST and GET requests - try to stick to just one variant. Your future you will thank you :)

AngularJS variable in scope - use variables of different scope

I would have a question concerning variables in scope and visibility.
Currently I have two controller variables:
vm.selectedUser
vm.selectedUserRole
The problem is, that I generate the tables in a ng-repeat loop and all inputs and selects in the different tables share this two mentioned variables above.
My question now would be how can I use this two parameters above in my method:
vm.addInstitutionUserConnection(institutionUserConnectionContent.institution, institutionUserConnectionContent, selectedUser, selectedUserRole)
Is there any chance to do this because the input, select elements and the span-button element (add user) have different scopes (this is my guess - I don't know exactly)
Thanks a lot for help!
<div ng-repeat="institutionUserConnectionsOfInstitution in vm.institutionUserConnectionsOfInstitutions">
<div ng-repeat="institutionUserConnectionContent in institutionUserConnectionsOfInstitution.institutionUserConnectionContents">
<div ng-show="addUser" class="row">
<table>
<tr>
<td class="adduserinput">
<input
type="text"
class="form-control"
placeholder="Benutzer durchsuchen"
ng-model="vm.selectedUser"
typeahead="user as vm.userLabelFormatter(user) for user in vm.getUsersByTerm($viewValue) | limitTo:5"
typeahead-min-length="3"
typeahead-wait-ms="100"
typeahead-editable="false" />
</td>
<td class="adduserroles">
<select class="form-control" ng-model="vm.selectedUserRole" ng-options="role as role for role in vm.roles">
</select>
</td>
<td>
<span class="input-group-btn">
<button class="btn btn-default" type="button" ng-click="vm.addInstitutionUserConnection(institutionUserConnectionContent.institution, institutionUserConnectionContent)">add user</button>
</span>
</td>
</tr>
</table>
</div>
</div>
Do it like this -
<div ng-repeat="institutionUserConnectionsOfInstitution in vm.institutionUserConnectionsOfInstitutions">
<div ng-repeat="institutionUserConnectionContent in institutionUserConnectionsOfInstitution.institutionUserConnectionContents">
<div ng-show="addUser" class="row">
<table>
<tr>
<td class="adduserinput">
<input
type="text"
class="form-control"
placeholder="Benutzer durchsuchen"
ng-model="institutionUserConnectionContent.selectedUser"
typeahead="user as vm.userLabelFormatter(user) for user in vm.getUsersByTerm($viewValue) | limitTo:5"
typeahead-min-length="3"
typeahead-wait-ms="100"
typeahead-editable="false" />
</td>
<td class="adduserroles">
<select class="form-control" ng-model="institutionUserConnectionContent.selectedUserRole" ng-options="role as role for role in vm.roles">
</select>
</td>
<td>
<span class="input-group-btn">
<button class="btn btn-default" type="button" ng-click="vm.addInstitutionUserConnection(institutionUserConnectionContent.institution, institutionUserConnectionContent, institutionUserConnectionContent.selectedUser, institutionUserConnectionContent.selectedUserRole)">add user</button>
</span>
</td>
</tr>
</table>
</div>
</div>
Explanation -
I just changed the vm to institutionUserConnectionContent.
reason - since you'll have multiple rows in the table (ng-repeat), if you use vm, you would end up with overwriting the same selectedUser and selectedUser of one row with other.
Hope this helps.

angular form with typeahead works on plunker/standalone but not in production code

I'm using a form within a table so I can submit some data in row. When I'm in my production/dev environment the form looks as follows. (I use route provider to assign the controller) Everything initially works as expected except that I cannot submit the form when pressing enter.
HTML
<table>
<tr>
<form novalidate ng-submit="addResult(selectedFencer)">
<td>
<input type="search" ng-model="selectedFencer" typeahead="fencer for fencer in fencers" placeholder="Type the fencers name" />
</td>
<td>
<input type="submit" value="Submit" class="button" />
</td>
</form>
</tr>
</table>
Controller
angular.module('RankingsApp')
.controller('CompetitionController', function($scope) {
$scope.fencers = ["Scott","Laura", "James"];
$scope.addResult = function(fencer) {
alert(fencer)
};
});
However, if I put the same code into a plunker/standalone html file it works as expected with the form being submitted when enter is pressed.
http://plnkr.co/edit/3385qhpExge4S5ZdPs1E?p=preview
I initially assumed that my issue was to do with a code error, but if I move the form outside the table in my production code it works as expected.
<form novalidate ng-submit="addResult(selectedFencer)">
<table>
<tr>
<td>
<input type="search" ng-model="selectedFencer" typeahead="fencer for fencer in fencers" placeholder="Type the fencers name" />
</td>
<td>
<input type="submit" value="Submit" class="button" />
</td>
</tr>
</table>
</form>
Has anyone any suggestion on either how I could fix this or a direction I could take to debug it?

AngularJs validate whole model

I have a view with some inputs in a table row. Is there a way to check if the whole model is valid without using form (can't have form in tr ) ?
<tr ng-controller="SomeCtrl">
<td>
<input type="text" ng-model="someModel.name" required="required" ng-minlength="3">
</td>
<td>
<input type="text" ng-model="someModel.x" required="required" ng-minlength="3">
</td>
<td>
<input type="text" ng-model="someModel.y" required="required" ng-minlength="3">
</td>
<td>
<button ng-click="save(someModel)">Save</button>
</td>
</tr>
In controller i want to have something like this
function ($rootScope, $scope, serive) {
$scope.save = function (someModel) {
if (someModel.$valid) {}
};
}
If you use a form and it has a name, it automatically can give you exactly what you required.
<form name="someForm">
<tr ng-controller="SomeCtrl">
<td>
<input type="text" ng-model="someModel.name" data-ng-required="true" ng-minlength="3">
</td>
<td>
<input type="text" ng-model="someModel.x" data-ng-required="true" ng-minlength="3">
</td>
<td>
<input type="text" ng-model="someModel.y" data-ng-required="true" ng-minlength="3">
</td>
<td>
<button data-ng-disabled="!someForm.$valid" ng-click="someForm.$valid && Namesave(someModel)">Save</button>
</td>
</tr>
</form>
Otherwise, there is no automagical way to do that. I guess you can write a directive which gives you all your inputs and their validators, parse them, and have a validation on the whole model, but no such thing readily exists, I believe.
Better way to do it:
ng-form name="myForm" can be used to avoid using tag and it should work - plunker.
but using ng-include will make the form unavailable to controller - plunker , explanation. A work around for this issue is to pass the form as parameter to the controller method - plunker

Resources