equating variables which are coming from http calls - angularjs

I have a select tag with options populated by AngularJS. I am trying to select an option if it equals to another property in scope. Option values and scope property I am trying to compare are both coming from async http call. So there is always delay, then it is not working properly. What is the best practice to make sure that both scope property are resolved and ready to compare.
ng-selected="MusteriId == option.Value" is comparing part.
<select id="MusteriId" name="MusteriId" ng-model="MusteriId">
<option ng-selected="MusteriId == option.Value"
ng-repeat="option in MusteriList" value="{{option.Value}}">
{{option.Text}}
</option>
</select>
This is my controller where two http calls are performed.
(function() {
var biletController = function ($scope, $http, commonFunctions) {
$scope.Id = null;
$scope.BiletNo = null;
$scope.BiletTarihi = null;
$scope.CurrencyId = null;
$scope.MusteriId = null;
$scope.PAID_EUR = null;
$scope.PAID_TL = null;
$scope.PAID_USD = null;
$scope.ServisIstiyorMu = null;
$scope.TOTAL = null;
$scope.TourId = null;
$scope.MusteriList = null;
$scope.openEditFormJS = function(e) {
$http.get('/Bilet/Get/' + e)
.then(function (response) {
console.log(response.data);
$scope.Id = response.data.Id;
$scope.BiletNo = response.data.BiletNo;
if (response.data.BiletTarihi) {
$scope.BiletTarihi = commonFunctions.formatDate(new Date(parseInt(response.data.BiletTarihi.substr(6))));
}
$scope.CurrencyId = response.data.CurrencyId;
$scope.MusteriId = response.data.MusteriId;
$scope.PAID_EUR = response.data.PAID_EUR;
$scope.PAID_TL = response.data.PAID_TL;
$scope.PAID_USD = response.data.PAID_USD;
$scope.ServisIstiyorMu = response.data.ServisIstiyorMu;
$scope.TOTAL = response.data.TOTAL;
$scope.TourId = response.data.TourId;
$('#modal').modal('show');
});
$http.get('/Bilet/GetMusteriSelectList')
.then(function (response) {
console.log(response.data);
$scope.MusteriList = response.data;
});
};
};
app.controller('BiletController', ['$scope', '$http', 'commonFunctions', biletController]);
}());

Use the ng-value directive for non-string values1
<select id="MusteriId" name="MusteriId" ng-model="MusteriId">
<option ̶n̶g̶-̶s̶e̶l̶e̶c̶t̶e̶d̶=̶"̶M̶u̶s̶t̶e̶r̶i̶I̶d̶ ̶=̶=̶ ̶o̶p̶t̶i̶o̶n̶.̶V̶a̶l̶u̶e̶"̶
ng-repeat="option in MusteriList" ng-value="option.Value">
{{option.Text}}
</option>
</select>
For more information, see Using ngValue to bind the model to an array of objects
Don't use ngSelected with ngModel2
<select id="MusteriId" name="MusteriId" ng-model="MusteriId">
<option ̶n̶g̶-̶s̶e̶l̶e̶c̶t̶e̶d̶=̶"̶M̶u̶s̶t̶e̶r̶i̶I̶d̶ ̶=̶=̶ ̶o̶p̶t̶i̶o̶n̶.̶V̶a̶l̶u̶e̶"̶
ng-repeat="option in MusteriList" value="{{option.Value}}">
{{option.Text}}
</option>
</select>
From the Docs:
Note: ngSelected does not interact with the <select> and ngModel directives, it only sets the selected attribute on the element. If you are using ngModel on the select, you should not use ngSelected on the options, as ngModel will set the select value and selected options.
— AngularJS ng-selected API Reference
See additional Docs:
Using ng-repeat to generate select options
Using select with ng-options and setting a default value
See Stackoverflow:
Using ng-repeat to generate select options (with Demo)

Related

Retrieve Selected Option Value From HTML DropDownList

I've a DropDownList where user has to select options and save it to database. I am using the following with AngularJs:
<select>
<option>----Please Select Sub-Category----</option>
<option ng-repeat="m in Categories" value="{{ m.CategoryId }}" ng-model="saveProducts.CategoryId">{{ m.Category }}</option>
</select>
I can show the values in the above DropDownList but stuck to retrieve the value from the selected and pass it to the scope. I've tried even this, a silly one:
<select>
<option>----Please Select Sub-Category----</option>
<option ng-repeat="m in Categories" value="{{ m.CategoryId }}" ng-model="m.CategoryId">{{ m.Category }}</option>
</select>
But that will not work. saveProducts is the object (scope) where I am passing values but is there any easy way where I can pass option value with the above procedure?
Here what I am doing to save data in database and it works fine except the option value, it's unable to retrieve values with the above:
productApp.controller('addProductController', function ($scope, $http) {
$scope.addData = function () {
$http({
method: 'POST',
url: '/Product/AddProductsToDb',
data: $scope.saveProducts
}).success(function () {
$scope.saveProducts = null;
}).error(function () {
alert('Failed');
});
}
});
This is the output I have and just want to pass the option value from it:
Update 1 - This is what I've tried but I can show the value in the alert method using as follows:
<select ng-model="saveProducts.ParentId"
ng-options="m.Category for m in Categories track by m.CategoryId">
<option value="">----Please Select Sub-Category----</option>
</select>
AngularJs Controller:
productApp.controller('addProductController', function ($scope, $http) {
$scope.addData = function () {
angular.forEach($scope.saveProducts, function (model, index) {
$scope.saveProducts.ParentId = (model.CategoryId);
});
alert($scope.saveProducts.ParentId);
$http({
method: 'POST',
url: '/Product/AddProductsToDb',
data: $scope.saveProducts
}).success(function () {
$scope.saveProducts = null;
}).error(function () {
alert('Failed');
});
}
});
Note: It saves TextBox input value but stuck with DropDownList. Unable to retrieve select option value and save it to database.
You should have a property to store the selected option. You can use ng-options to render the dropdown.
<select ng-model="selectedCategory"
ng-options="option.Category for option in Categories track by option.CategoryId ">
<option value="">Select Option</option>
</select>
Now your select element's ng-model is set to selectedCategory. So in your add method you can access that and use that for saving.
$scope.addData = function () {
console.log($scope.selectedCategory);
//to do : use selectedCategory
}
Use ngOptions. Depending on the structure of your Categories data, you could do something like:
<select ng-options="m as m.yourProperty for m in Categories" ng-model="selected"></select>
Then, in Angular...
$scope.selected = $scope.Categories[0];
Read the ngOptions documentation to tweak according to your needs.

Angular populate from JSON through httpd and then choose selected

I'm fairly new to Angular and i'm trying to do something quite simple. I want to populate a dropdown box and have the selected value from database as selected option. Here is my dropdown code.
<select ng-options="option.fname+' '+option.lname for option in students track by option.id"
class="form-control"
name="studentId"
ng-model="selectedStudent"
id="studentId"
ng-change="loadStudent()"
>
<option value="">Please choose a student</option>
</select>
Now, in my module and the controller, i have this code which populates the dropdown and i can see the options (student.id, student.fname , student.lname):
$scope.students = {};
$scope.selectedStudent = null;
$scope.populateStudents = function() {
$http({
method: 'POST',
url: 'ajax/getStudents',
data: { teacherId: 0 }
}).success(function (result) {
$scope.students = result;
$scope.selectedStudent = 4;
});
}
This runs i guess on page load as i have this :
Then on the above script and after the $scope.students is loaded, i write
$scope.selectedStudent = 4; which I want to preselect the student with student.id = 4.
What happens though is that the default
<option value="">Please choose a student</option> is becoming <option value="" select="selected">Please choose a student</option> instead of the student with id 4.
What am I doing wrong ?
Thank you.
When you use ngOptions with an array of complex objects, you must use an identical complex object to "select" one of the options, not just a number. So, once your $http call has returned, find the item in the list with the id you want and assign your scope variable to be the entire student object:
$http({
method: 'POST',
url: 'ajax/getStudents',
data: { teacherId: 0 }
}).success(function (result) {
$scope.students = result;
angular.forEach($scope.students, function(student) {
if (student.id == 4) {
$scope.selectedStudent = student;
}
});
});
If you add the as statement to your ng-repeat you can select the student by id like so:
<select ng-options="option.id as option.fname+' '+option.lname for option in students track by option.id"
class="form-control"
name="studentId"
ng-model="selectedStudent"
id="studentId"
ng-change="loadStudent()"
>
<option value="">Please choose a student</option>
</select>
$scope.selectedStudent = { id: 4 };
I prefer to use lodash or underscore to find an item in a list rather than using forEach:
$scope.selectedStudent = lodash.find($scope.students, { 'id': 4 });

dropdown value disappears when select

I have one select in which I bind data from database by get method.it binds data perfectly in select.but when I select one of it option .its disappears..any help appreciated.
This is my HTML Code:
<select class="form-control" ng-model="MainCategory" ng-options="main.Name for main in MainCategory track by main.ID" placeholder="Select Main Category">
<option value=""></option>
</select>
this is my contoller code
var baseURL = 'http://localhost:50928/api/ProductAPI/';
var MainCategory = [];
url = baseURL + "GetMainCategoryList";
$http.get(url)
.success(function (data) {
$scope.MainCategory = data;
console.log(data);
}).error(function (data) {
console.log(data);
});
Your ng-options data is MainCategory and your ng-model is binded to it as well. This means that selecting an options turns your data to one value only - your selected option. In your case you should have a data property, lets say - categories.
Like this:
ng-options="main.Name for main in categories track by main.ID"
In addition you will hold in your controller another property for the selected Category and ng-model will bind to it:
ng-model="selectedCategoty"

AngularJS - Currency exchange filter with external output

I am trying to build a filter based on this post. I want to be able to switch from one currency to the other by switching a select input with an ng-click on it, but I'm failing to get the input into the filter.
My html is:
<div ng-controller="myCtrl">
you have, {{money | currency}}...<br><br>
</div>
<select>
<option ng-click="currencySymbol = 'USD'; currencyRate=exchange.usd.rate">USD<option>
<option ng-click="currencySymbol = '£'; currencyRate=exchange.pound.rate">£<option>
<option ng-click="currencySymbol = '€'; currencyRate=exchange.euro.rate">€<option>
</select>
And the Angular part:
angular
.module('myApp', [])
.controller('myCtrl', function($scope) {
$scope.money = 100;
$scope.exchange = [
{"usd":{"rate":1}},
{"pound":{"rate":0.702846}},
{"euro":{"rate":0.885055}}
];
})
.filter('currency', function() {
var defaultCurrency = 'USD';
return function(input, currencySymbol, currencyRate) {
var out = "";
currencySymbol = currencySymbol || defaultCurrency;
currencyRate = currencyRate || 1.00;
out = input * currencyRate;
return out + ' ' + currencySymbol;
}
});
You can check the JsFiddle here
Thanks in advance!
Quite a few updates here:
First off, your dropdown is located outside of the controller
You could use the ng-options directive to clean up your select menu
You have ng-click on each option which doesn't work well with the complex model you are trying to maintain
If you pass the whole selected option into the filter, you can manage everything from that one scope variable keeping the data in one place
Here is a working example
http://jsfiddle.net/r0m4n/dLLtzqyr/1/
This will be your simplified html:
<div ng-controller="myCtrl">
you have, {{money | currency: selectedCurrency}}...
<br>
<br>
<select ng-model="selectedCurrency" ng-options="item as item.label for item in exchange">
</select>
</div>
And your js:
angular
.module('myApp', [])
// controller here
.controller('myCtrl', function($scope) {
$scope.money = 100;
$scope.exchange = [{
label: "USD",
rate: 1
}, {
label: "£",
rate: 0.702846
}, {
label: "€",
rate: 0.885055
}];
$scope.selectedCurrency = $scope.exchange[0];
})
.filter('currency', function() {
return function(input, selectedCurrency) {
var out = "";
out = input * selectedCurrency.rate;
return out + ' ' + selectedCurrency.label;
}
});
You define 3 parameter in your filter currency. Whenever you use your filter, you need to give these parameters to your filter. In your case :
<div ng-controller="myCtrl">
you have, {{money | currency:currencySymbol:exchange[2].euro.rate}}...<br><br>
</div>
In AngularJS world, you call your filter after the | and you use : as a separator for parameters (the first parameter input is always given implicitly).
To make the debug easier, you can add this in your filter :
return function(input, currencySymbol, currencyRate) {
console.info('currency parameter', input, currencySymbol, currencyRate);
Please note that I hardcoded the parameter currencyRate because it's not handy to retrieve with the way you store your array.

Responding to drop down selection change in angular without model binding

I have a drop down that should cause a data fetch on change. I don't need two way binding to a model for the drop down. I just want it initially populated with a list of departments and when a user selects one, it gets the list of users in that department.
The select looks like this:
<select class="form-control" id="selDepartmentList" ng-model="departmentList" ng-change="getUsersInDepartment(document.getElementById("selDepartmentList").options[document.getElementById("selDepartmentList").selectedIndex].value)">
<option value="-1">All</option>
<option ng-repeat="dept in departmentList"
value="{{dept.DepartmentId}}">
{{dept.DepartmentName}}
</option>
</select>
I tried ng-change without ng-model, but it fails since ng-change requires ng-model for some reason. I tried setting ng-model to null and empty string, but neither worked. I also tried not using ng-change at all and using onchange, but getUsersInDepartment can't be found through onchange since it's attached to my controller. With ng-model set to departmentList, the drop down won't hold a value, any selection is erased.
All I want to have happen is that when a user selects a department it passes the id for that department to getUsersInDepartment, which will then fetch the user list. But right now getUsersInDepartment is never called.
departmentList is defined in my controller and attached to $scope. All the examples I've seen have some kind of selectedModelObject that they bind to the drop down. I don't have one of those.
My controller looks like:
controller('AdminTableCtrl', function ( $scope, coreAPIservice ) {
$scope.userList = [];
$scope.departmentList = [];
coreAPIservice.GetUserList().success(function (response) {
$scope.userList = response;
});
coreAPIservice.GetDepartmentList().success(function (response) {
$scope.departmentList = response;
});
$scope.getUsersInDepartment = function(deptId) {
if(deptId === -1) {
coreAPIservice.GetUserList().success(function (response) {
$scope.userList = response;
});
}
else {
coreAPIservice.GetUsersInDepartmentList(deptId).success(function (response) {
$scope.userList = response;
});
}
}
});
Edit:
My original attempt with ng-options:
<select class="form-control" id="selDepartment"
ng-model="selectedDepartment"
ng-options="dept as dept.DepartmentName for dept in departmentList track by dept.DepartmentId">
<option value="">Select Team...</option>
</select>
selectedDepartment is defined as:
$scope.selectedDepartment = {};
The solution is to avoid decorating the <select> element with any angular directives and instead place ng-click on each <option>.
Like this:
<select class="form-control" id="selDepartmentList">
<option value="-1" selected>All</option>
<option ng-repeat="dept in departmentList"
ng-click="getUsersInDepartment(dept.DepartmentId)"
value="{{dept.DepartmentId}}">
{{dept.DepartmentName}}
</option>
</select>
Making a custom directive should work for this problem.
angular
.module('my_module')
.directive('ngCustomChange', function($parse) {
return function(scope, element, attrs) {
var fn = $parse(attrs.ngCustomChange);
element.bind('change', function(event) {
scope.$apply(function() {
event.preventDefault();
fn(scope, {$event:event});
});
});
};
});
<select ng-custom-change="$ctrl.myFunction()">
<option value="1">Value 1</option>
<option value="2">Value 2</option>
</select>

Resources