ngModel doesn't bind to select option - angularjs

I can't figure out why i can't bind to a select element
there is my code:
<select ng-model="site" ng-change="getAll()">
<option value="SG1">SG1</option>
<option value="PZ1">PZ1</option>
<option value="NE1">NE1</option>
</select>
getAll() make an alert of 'site' but the var is never updated.
$scope.site is nerver use except in getAll()
$scope.getAll = function () {
alert($scope.site);
}
If i set $scope.site to a value it is display but never update either
Edit:
I forgot a big detail...
The select is display with a ng-include directive
<section id="sectionLeft" ng-include="nav[navId]">
</section>

ng-include creates a new scope which prototypally inherits from your controller. So you are initially reading the selected option from your controller, but when the select element writes a new selected option it ends up writing to the inherited scope.
You can bind to an object instead.
Controller:
$scope.data = { site: "SG1" };
$scope.getAll = function() {
alert($scope.data.site);
}
Template:
<select ng-model="data.site" ng-change="getAll()">
<option value="SG1">SG1</option>
<option value="PZ1">PZ1</option>
<option value="NE1">NE1</option>
</select>
See this answer for more details.
If you don't like switching to an object, look up controller as syntax and bind directly to the controller instead of $scope.

I've fiddled your code and i'm able to get the updated value in the alert box.
$scope.getAll = function() {
alert($scope.site);
};
Working Fiddle

Related

AngularJs ng-mouseover not working in option tags

I use angularJS and I want to call function when mouse change over in option list. I tried ng-mouseover="changeProjectColor(t)" but it not working for me.
<select id="select-tamplete" ng-model="tamplete">
<option ng-repeat="t in tampletes" ng-mouseover="changeProjectColor(t)" ng-value="t">{{t.name}}</option>
</select>
controller:
app.controller('ControlBoxCtrl',function($scope, adminSer, $log){
$scope.adminSer = adminSer;
$scope.tampletes = [
{name:"gray",colorClass:"gray"},
{name:"green",colorClass:"green"},
{name:"yellow",colorClass:"yellow"},
{name:"blue",colorClass:"blue"},
{name:"purple",colorClass:"purple"},
{name:"red",colorClass:"red"},
{name:"amber-light",colorClass:"amber-light"},
{name:"teal",colorClass:"teal"}
];
$scope.changeProjectColor = function(){
$log.debug("change color");
}
});
You cannot attach ng-mouseover, ng-clicked, ng-mousemove events with options list. You can do so with the select element since events can only be attached to elements and not to options. Better use ng-change event with selectbox to accomplish your requirement.
<select id="select-tamplete" ng-model="tamplete" ng-options="t.name for t in tampletes" ng-change="changeProjectColor(tamplete)">
</select>

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>

How to use watch over selected options and add into an array in angularjs

// i wanna put watch on option selection and put inside an array multipleVlaue bt its not working.
//Html
<select ng-model="category1" ng-options="item1 for item1 in abms">
<option value="" ng-init="category1"></option>
</select>
//js
$scope.multipleVlaue = [];
$scope.$watch('category1', function(){
$scope.multipleVlaue.push($scope.category1);
}, true);
Here is the Code
What im doing wrong?
You are the victim of not Understanding the Scopes
In short, ng-repeat creates new child scope and primitive values like (Numbers, String, Boolean) when defined on parent scope doesn't update value from inside the child scope, so you need to use . dot in your ng-model
So your code would like this
// html
<select ng-model="obj.category1" ng-options="item1 for item1 in abms">
//js
$scope.$watch('obj.category1', function (val) {
if ($scope.obj.category1) {
$scope.multipleVlaue.push($scope.obj.category1);
}
console.log($scope.multipleVlaue);
}, true);
See fiddle

Angularjs select list not initialize default value

I have 2 select lists:
<select class="input-large" ng-model="bu.box.categoryId" ng-change="getSubCats()">
<option ng-repeat="cat in cats" value="{{cat.id}}">{{cat.name}}</option>
</select>
<select class="input-large" ng-model="bu.box.subCategoryId">
<option ng-repeat="subcat in subCats" value="{{subcat.id}}">{{subcat.name}}</option>
</select>
The object bu, subcats is injected to my controller from resolve and exists before bindings is render and cats i get from local storage:
$stateProvider.state('box',
{
url: '/box-card/:id',
templateUrl: '/partials/main.module/contollers/box.html?v=' + global_app_version,
controller: 'BoxController as boxCtrl',
resolve: {
Box: function ($stateParams, httpService) {
return httpService.getBox({ boxid: $stateParams.id });
}
}
})
Controller variables initialization look like this:
function boxController($scope, localStorageService, httpService, $state, appData, uiGridConstants, $modal, helpersService, $stateParams, $sce, Box) {
$scope.bu = Box.data.bu;
$scope.cats = localStorageService.get("cats");
$scope.subCats = Box.data.currentSubCats;
............
var controllers = angular.module('app.controllers');
controllers.controller('BoxController', boxController);
The problem is, when the select lists is rendered, they not initialized correctly,
The first option is selected instead of relevant initialization by ng-model.
What happen here? Why is not working correctly?
I checked all variables in debug, all fine... Need help here.
Try to solve the problem with ng-selected.
<select class="input-large" ng-model="bu.box.categoryId" ng-init="cat = cats[0]" ng-change="getSubCats()">
<option ng-repeat="cat in cats" value="{{cat.id}}">{{cat.name}}</option>
</select>
<select class="input-large" ng-model="bu.box.subCategoryId" ng-init="subcat = subCats[0]">
<option ng-repeat="subcat in subCats" value="{{subcat.id}}">{{subcat.name}}</option>
</select>
I use in my project ng-init like ng-init="subcat = subCats[0]"
change the subCats[0] and cats[0] for your init values
Try using $scope.$apply() .
From the article:
If you write any code that uses Ajax without $http, or listens for
events without using Angular’s ng-* listeners, or sets a timeout
without $timeout, you should wrap your code in $scope.$apply
It looks like exactly your case. Box is updated in a background request and angular listeners do not know that it was updated.
UPD1
Also Just noticed that the problem could hide here
$scope.bu is initialized before $scope.cats so model actually tries to match a still empty list of options.
upd2
just noticed in the comment that ng-options binding was a bit off.
try using
<select ng-options="cat.name for cat.id in cats track by cat.id" class="input-large" ng-model="bu.box.categoryId" ng-change="getSubCats()">

why select items are not being populated

Here is my html code
<select id="userGroups" name="userGroups" ng-model="userGroups" class="form-control">
<option value="{{grp.groupId}}" ng-repeat="grp in groups">{{grp.groupName}}</option>
</select>
here is my controller
function MyController($scope, MYAPI) {
$scope.groups = MYAPI.GroupList.get();
}
Why options are not being popuplated?
Ok I have changed my controller to resolve the GroupList before populating the view, but its still not showing
MYApp.controller('CreateUserController', ['$scope', 'groupList', function($scope, groupList) {
$scope.groups = groupList;
debugger; //here I can see groups has objects which I need to display
}]);
but still dropdown is not loading...
As Martin said you need to use ng-options.
This is how it should look like:
<select id="userGroups"
name="userGroups"
ng-model="userGroups"
ng-options="grp.groupId as grp.groupName for grp in groups"
class="form-control">
</select>
Accorting to the AngularJS documentation of select you have to use ng-options. This use case is not supported by ng-repeat:
ngOptions provides an iterator facility for the <option> element which should be used instead of ngRepeat when you want the select model to be bound to a non-string value. This is because an option element can only be bound to string values at present.

Resources