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.
Related
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>
I am practicing my angular.js and form validation. I want to make it so that the form won't submit when I click submit if variables user_valid and pass_valid are false. I do thus perfectly fine when writing code outside of angularjs by calling return false;.
But when work in angular.js, and insert ng-submit='loginVal()', and type in my controller:`
logApp.controller('logForm', function($scope, $http){
user_valid = false;
pass_valid = false;
$scope.loginVal = function(){
if (user_valid == false && pass_valid == false){
return false;
console.log('Submit Stopped');
}
}`
...
});
The form still submits, and it shows in console Navigated to ~form-action url~. I don't know why it is submitting. The rest of the functions in the controller have nothing related to this function, so i excluded it.
HTML:
<form name='login' method="post" action="" ng-submit='loginVal()'>
{% csrf_token %}
<!-- LOGIN FORM -->
<table id='show-table'>
<tr>
<td width='20%'>Username</td>
<td width="80%">
<div class='col-md-12' id='userField'>
<input name='name' type="text" ng-model='username' ng-change='checkName()'/>
<div id='success'></div>
<div id='failure'></div>
</div>
</td>
</tr>
<tr>
<td>Password</td>
<td>
<div class='col-md-12'>
<input name="pwd" type="password" ng-model='password' />
</div>
</td>
</tr>
<td></td>
<td><input type="submit" value="Login" id='loginSubmit' disabled /></td>
</tr>
</table>
</form>
Remove the action and the method attributes in the form tag
EDIT
Look at this fiddle: https://jsfiddle.net/80Laf822/1/
<div ng-controller="FormController">
<form name='loginForm' method="post" action="" ng-submit='loginVal()'>
<!-- LOGIN FORM -->
<table id='show-table'>
<tr>
<td width='20%'>Username</td>
<td width="80%">
<div class='col-md-12' id='userField'>
<input name='name' type="text" ng-model='username' required/>
<div id='success'></div>
<div id='failure'></div>
</div>
</td>
</tr>
<tr>
<td>Password</td>
<td>
<div class='col-md-12'>
<input name="pwd" type="password" ng-model='password' required/>
</div>
</td>
</tr>
<tr>
<td></td>
<td>
<input type="submit" value="Login" id='loginSubmit' ng-disabled="loginForm.$invalid" />
</td>
</tr>
</table>
</form>
</div>
You can use the required attribute in the input and the property $invalid of the form to automatically disable or enable the button if the form is valid or not. You can do all type of things like patterns, max-length, min-lenght ...
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 :)
I am building a table using angular ng-repeat. I need to have the ability to update or delete each row independently and thus need to validate each row independently.
<tr ng-repeat="item in model.items" >
<td><input type="text" ng-model="item.AccountNumber" ng-maxlength="model.validation.maxAccountLength" /></td>
<td><select ng-model="item.OriginCountry" ng-options="country.Id as country.Name for country in model.OriginCountries"></select></td>
<td><select ng-model="item.DestinationCountry" ng-options="country.Id as country.Name for country in model.DestinationCountries"></select></td>
<td><input type="text" ng-model="item.Zone" ng-maxlength="4" /></td>
<td><button type="button" ng-click="updateItem(item)" class="btn btn-warning" ><i class="fa fa-refresh"></i></button></td>
<td><button type="button" ng-click="removeItem(item)" class="btn btn-danger"><i class="fa fa-trash-o"></i></button></td>
</tr>
Is it possible to validate each row idependently
Try to wrap the row contents with forms and add name attributes to your inputs/selects
<tr ng-repeat="item in model.items" >
<td>
<form name="form">
<input name="account_number" type="text" ng-model="item.AccountNumber" ng-maxlength="model.validation.maxAccountLength" /></td>
<td>name="origin" ng-model="item.OriginCountry" ng-options="country.Id as country.Name for country in model.OriginCountries"></select></td>
<td><select name="destination" ng-model="item.DestinationCountry" ng-options="country.Id as country.Name for country in model.DestinationCountries"></select></td>
<td><input name="zone" type="text" ng-model="item.Zone" ng-maxlength="4" /></td>
<td><button type="button" ng-click="updateItem(item)" class="btn btn-warning" ><i class="fa fa-refresh"></i></button></td>
<td><button type="button" ng-click="removeItem(item)" class="btn btn-danger"><i class="fa fa-trash-o"></i></button>
</form>
</td>
</tr>
Now you can use the FormController state like form.$submitted or form.zone.$touched
(https://docs.angularjs.org/guide/forms)
I have made simple example: http://codepen.io/anon/pen/VLpYJm?editors=101
In this example I need to get field.type and using it with ng-switch.
<div ng-app="app">
<table ng-controller="tableController">
<tr ng-repeat="item in items">
<td>
{{item}}
</td>
<td>
<select ng-model="item" ng-options="field.label for field in fields track by field.name" required="required" />
</td>
<td>
<div ng-switch on="item.type">
<div ng-switch-when="BOOLEAN">
<input ng-model="item.value" type="checkbox" />
</div>
<div ng-switch-default>
<input ng-model="item.value" type="text" class="form-control" required="">
</div>
</div>
</td>
<td>{{selected}}</td>
</tr>
</table>
</div>