Angularjs select value is undefined - angularjs

Now I am trying to get the value from select dropdown, but it return undefined. The thing is in html level it works as expect, Here is my code:
<div class='subcontent'>
<input id="me" type="radio" class='choosemethod' ng-model="paymentmethod" value="Y"><label for="me" class='choosemethod'>Me</label>
<input id="company" type="radio" ng-model="paymentmethod" value="N" class='choosemethod'><label for="company" class='choosemethod'>My Company</label><br/>
<span class='helptext'>Who makes payments to this account?</span><span class='help' style='margin-left:20px;width:20px;height:20px;'>help</span>
</div>
<div class='paymentmethods subcontent' ng-switch on="paymentmethod">
<select ng-model='selectedmethod' ng-init="selectedmethod=Memethods[0]" id='methods' ng-switch-when='Y'>
<option ng-repeat="method in Memethods" value="{{method}}">{{method}}</option>
</select>
<select ng-model='selectedmethod' ng-init="selectedmethod=companies[0]" ng-switch-when='N' style='float:left'>
<option ng-repeat='companyoption in companies' value="{{companyoption}}">{{companyoption}}</option>
</select>
<div class='clear'></div>
<label for ='methods'>Payment Method</label><span class='help' style='margin-left:20px;width:20px;height:20px;'>help</span>
</div>
In js:
$scope.Memethods = ['Same as Card/Account Name','American Express','American Express Corp','Cash','Checking','MasterCard','My Visa','VISA'];
$scope.companies = ['Company Paid','MyAMEX'];
it shows fine in page, but when I try to get the value, it shows undefined. any idea?

This is the classic "angular dot notation" issue.
Here is a working example
Basically, ng-switch creates a new scope, so when the select sets the selectedmethod property, it is doing so on the new scope, not the controller scope as you are expecting. One solution is to create a parent object for your model.
angular.module('app',[])
.controller('main', function($scope){
$scope.selection = {};
$scope.Memethods = ['Same as Card/Account Name','American Express','American Express Corp','Cash','Checking','MasterCard','My Visa','VISA'];
$scope.companies = ['Company Paid','MyAMEX'];
})
and note how it's referenced differently in the html:
<select ng-model='selection.selectedmethod' ng-init="selection.selectedmethod=companies[0]" ng-switch-when='N' style='float:left'>
<option ng-repeat='companyoption in companies' value="{{companyoption}}">{{companyoption}}</option>
</select>
A different (maybe better) way would be to use the "ControllerAs" syntax, which has the effect of doing this for you.
angular.module('app',[])
.controller('main', function($scope){
this.Memethods = ['Same as Card/Account Name','American Express','American Express Corp','Cash','Checking','MasterCard','My Visa','VISA'];
this.companies = ['Company Paid','MyAMEX'];
})
<body ng-app="app" ng-controller="main as main">
<div class='subcontent'>
<input id="me" type="radio" class='choosemethod' ng-model="paymentmethod" value="Y">
<label for="me" class='choosemethod'>Me</label>
<input id="company" type="radio" ng-model="paymentmethod" value="N" class='choosemethod'>
<label for="company" class='choosemethod'>My Company</label>
<br/>
<span class='helptext'>Who makes payments to this account?</span><span class='help' style='margin-left:20px;width:20px;height:20px;'>help</span>
</div>
<div class='paymentmethods subcontent' ng-switch on="paymentmethod">
<select ng-model='main.selectedmethod' ng-init="main.selectedmethod=main.Memethods[0]" id='methods' ng-switch-when='Y'>
<option ng-repeat="method in main.Memethods" value="{{method}}">{{method}}</option>
</select>
<select ng-model='main.selectedmethod' ng-init="main.selectedmethod=main.companies[0]" ng-switch-when='N' style='float:left'>
<option ng-repeat='companyoption in main.companies' value="{{companyoption}}">{{companyoption}}</option>
</select>
<div class='clear'></div>
<label for='methods'>Payment Method</label><span class='help' style='margin-left:20px;width:20px;height:20px;'>help</span>
</div>
<div>{{main.selectedmethod}}</div>
</body>

you can refer to this simple example
html code :
<div ng-controller="Main" ng-app>
<div>selections = {{selections}}</div>
<div>
<p>Model doesn't get updated when selecting:</p>
<select ng-repeat="selection in selections" ng-model="selection" ng-options="i.id as i.name for i in items">
<option value=""></option>
</select>
</div>
js code:
function Main($scope) {
$scope.selections = ["", "id-2", ""];
$scope.reset = function() {
$scope.selections = ["", "", ""];
};
$scope.sample = function() {
$scope.selections = [ "id-1", "id-2", "id-3" ];
}
$scope.items = [{
id: 'id-1',
name: 'Name 1'},
{
id: 'id-2',
name: 'Name 2'},
{
id: 'id-3',
name: 'Name 3'}];
}

The ng-model inside value must have Initialize before it represents. So the ng-init comes before the ng-model. inside the options $first is used for select the first value.
<select ng-init= "selectedmethod=companies[0]" ng-model='selectedmethod' ng-switch-when='N' style='float:left'>
<option ng-repeat='companyoption in companies' value="{{companyoption}}" ng-selected="$first">{{companyoption}}
</option>
</select>

Related

AngularJs: Ng-model object and single model Together

I do not have enough English to describe it, but I think you will understand it from the codes.
Basically my problem is that ng-model = "" ng-options = "" does not come up with form data when used together.
<select class="form-control" name="car_id" ng-model="car_id" ng-options="I.car_brand_code as I.car_brand_name for I in CarList" ng-change="GetState()" >
<option value="">Select Car</option>
</select>
The selection box for the brands of these cars
<div class="form-group">
<label class="mtb10">Model Year</label>
<input type="text" name="modelYear" class="form-control" ng-model="data.modelYear" placeholder="Car Year...">
</div>
This is the other form objects. Where ng-model is a different data "data." I can get it. How can I get the value in the selection box.
I need to get the "car_id" value.
Try this :
On change of the dropdown options pass the selected value into the function as a param.
Use array.filter() method to fetch the model year for the selected car based on the car id.
DEMO
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl',function($scope) {
$scope.CarList = [
{
"car_brand_code": 1,
"car_brand_name": "Maruti",
"model_year": 1990
},
{
"car_brand_code": 2,
"car_brand_name": "Ford",
"model_year": 2005
}
];
$scope.GetState = function(carId) {
var selectedCar = $scope.CarList.filter(function(item) {
return item.car_brand_code == carId;
});
$scope.data = {
"modelYear" : selectedCar[0].model_year
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<select class="form-control" name="car_id" ng-model="car_id" ng-options="I.car_brand_code as I.car_brand_name for I in CarList" ng-change="GetState(car_id)" >
<option value="">Select Car</option>
</select>
<div class="form-group">
<label class="mtb10">Model Year</label>
<input type="text" name="modelYear" class="form-control" ng-model="data.modelYear" placeholder="Car Year...">
</div>
</div>

How to remove/clear scope variable on ng-change

I have a dropdown with a ng-change event handler:
<label>Person:</label>
<select class="form-control" ng-model="select" ng-change="change()">
<option value="0">a </option>
<option value="1">b </option>
<option value="2">c </option>
</select>
On change i assign data from an array to $scope.person:
$scope.change = function(){
$scope.person = $scope.persons[$scope.select];
};
The array:
$scope.persons = [
{'name': 'Peter'},
{'name': 'John'},
{'name': 'Mark'}
];
When a person is selected (for example $scope.select == 0/Peter) there is a possibility to add a value to that person ($scope.person.value) via radio buttons:
<label><input type="radio" ng-model="person.value" value="1"> Value 1 </label><br/>
<label><input type="radio" ng-model="person.value" value="2"> Value 2</label><br/>
<label><input type="radio" ng-model="person.value" value="3"> Value 3</label><br/>
When a value ($scope.person.value) is added to a person, and i change the dropdown I want to remove/clear that value. So that when you reselect that person in the dropdown $scope.person.value is undefined.
$scope.change = function(){
//This is not working
delete $scope.person;
// This is not working either
$scope.person.value = '';
$scope.person = $scope.persons[$scope.select];
};
I want to know how to clear the value stored in $scope.person.value on change of the dropdown. Now the variable is still defined when I reselect the person. Here is a working example.
I think the variable is still saved, you should remove the value by yourself:
$scope.change = function(){
delete $scope.person;
$scope.person = '';
$scope.person = $scope.persons[$scope.select];
//Remove the assigned value
delete $scope.person.value;
};
your problem is here,
$scope.person = $scope.persons[$scope.select];
when you do this, and then assign a 'value' property, you actually modify the object in the persons array. try below,
$scope.change = function() {
$scope.person = angular.copy($scope.persons[$scope.select]);
console.log($scope.person);
};
$scope.$watch('person.value', function(n) {
console.log(n);
});
As #Kevin Sanchez say, you need delete value from person.
Like this delete $scope.person.value;
Live example on jsfiddle.
var myApp = angular.module('myApp', []);
function MyCtrl($scope) {
$scope.persons = [{
'name': 'Peter'
}, {
'name': 'John'
}, {
'name': 'Mark'
}];
$scope.change = function() {
if ($scope.person)
delete $scope.person.value;
$scope.person = $scope.persons[$scope.select];
};
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="MyCtrl">
<label>Person:</label>
<select class="form-control" ng-model="select" ng-change="change()">
<option value="0">a</option>
<option value="1">b</option>
<option value="2">c</option>
</select>
<br>
<br>{{ person }}
<br>
<br>
<label>
<input type="radio" ng-model="person.value" value="1">Option 1</label>
<br/>
<label>
<input type="radio" ng-model="person.value" value="2">Option 2</label>
<br/>
<label>
<input type="radio" ng-model="person.value" value="3">Option 3</label>
<br/>
</div>
</div>

ng-repeat in AngularJS not working

Here is a simple Select done in Angular
<select ng-model="myCar">
<option ng-repeat="car in cars" value="{{car}}">{{car}}</option>
</select>
I have the following in my scope in angular.js
$scope.cars = ["Toyota", "Ford", "Rolls"];
why isn't the options showing up, instead I get {{car}}
You can try this.
<select ng-model="myCar" ng-options = "car for car in cars" ng-init="myCar = 'Rolls'">
</select>
or this
<select ng-model="myCar" ng-init="myCar = 'Rolls'">
<option ng-repeat="car in cars" value={{car}}>{{car}}</option>
</select>
Your's code is working fine. Only the default value isn't selected, so at the beginning it shows blank.
Refer here.
HTML:
<div ng-app="app" ng-controller="test">
<select ng-model="myCar">
<option value="">Select</option>
<option ng-repeat="car in cars" value="{{car}}">{{car}}</option>
</select>
</div>
JS:
var app = angular.module('app', []);
app.controller('test', function ($scope) {
$scope.cars = ["Toyota", "Ford", "Rolls"];
});

Get value when selected ng-option changes

I have in my .html page a dropdown list,
Dropdown:
<select ng-model="blisterPackTemplateSelected" data-ng-options="blisterPackTemplate as blisterPackTemplate.name for blisterPackTemplate in blisterPackTemplates">
<option value="">Select Account</option>
</select>
I want to execute an action when the user select a value. So In my controller I did:
Controller:
$scope.$watch('blisterPackTemplateSelected', function() {
alert('changed');
console.log($scope.blisterPackTemplateSelected);
});
But the changing the value in the dropdownlist doesn't trigger the code : $scope.$watch('blisterPackTemplateSelected', function()
As a result I tried another method with a : ng_change = 'changedValue()' on the select tag
and
Function:
$scope.changedValue = function() {
console.log($scope.blisterPackTemplateSelected);
}
But the blisterPackTemplateSelected is stored into a child scope. I read that the parent can't get access to the child scope.
What is the correct/best way to execute something when a selected value in a dropdown list changes? If it's method 1, what am I doing wrong with my code?
as Artyom said you need to use ngChange and pass ngModel object as argument to your ngChange function
Example:
<div ng-app="App" >
<div ng-controller="ctrl">
<select ng-model="blisterPackTemplateSelected" ng-change="changedValue(blisterPackTemplateSelected)"
data-ng-options="blisterPackTemplate as blisterPackTemplate.name for blisterPackTemplate in blisterPackTemplates">
<option value="">Select Account</option>
</select>
{{itemList}}
</div>
</div>
js:
function ctrl($scope) {
$scope.itemList = [];
$scope.blisterPackTemplates = [{id:1,name:"a"},{id:2,name:"b"},{id:3,name:"c"}];
$scope.changedValue = function(item) {
$scope.itemList.push(item.name);
}
}
Live example: http://jsfiddle.net/choroshin/9w5XT/4/
I may be late for this but I had somewhat the same problem.
I needed to pass both the id and the name into my model but all the orthodox solutions had me make code on the controller to handle the change.
I macgyvered my way out of it using a filter.
<select
ng-model="selected_id"
ng-options="o.id as o.name for o in options"
ng-change="selected_name=(options|filter:{id:selected_id})[0].name">
</select>
<script>
angular.module("app",[])
.controller("ctrl",['$scope',function($scope){
$scope.options = [
{id:1, name:'Starbuck'},
{id:2, name:'Appolo'},
{id:3, name:'Saul Tigh'},
{id:4, name:'Adama'}
]
}])
</script>
The "trick" is here:
ng-change="selected_name=(options|filter:{id:selected_id})[0].name"
I'm using the built-in filter to retrieve the correct name for the id
Here's a plunkr with a working demo.
Please, use for it ngChange directive.
For example:
<select ng-model="blisterPackTemplateSelected"
ng-options="blisterPackTemplate as blisterPackTemplate.name for blisterPackTemplate in blisterPackTemplates"
ng-change="changeValue(blisterPackTemplateSelected)"/>
And pass your new model value in controller as a parameter:
ng-change="changeValue(blisterPackTemplateSelected)"
Best practise is to create an object (always use a . in ng-model)
In your controller:
var myObj: {
ngModelValue: null
};
and in your template:
<select
ng-model="myObj.ngModelValue"
ng-options="o.id as o.name for o in options">
</select>
Now you can just watch
myObj.ngModelValue
or you can use the ng-change directive like so:
<select
ng-model="myObj.ngModelValue"
ng-options="o.id as o.name for o in options"
ng-change="myChangeCallback()">
</select>
The egghead.io video "The Dot" has a really good overview, as does this very popular stack overflow question: What are the nuances of scope prototypal / prototypical inheritance in AngularJS?
You can pass the ng-model value through the ng-change function as a parameter:
<select
ng-model="blisterPackTemplateSelected"
data-ng-options="blisterPackTemplate as blisterPackTemplate.name for blisterPackTemplate in blisterPackTemplates"
ng-change="changedValue(blisterPackTemplateSelected)">
<option value="">Select Account</option>
</select>
It's a bit difficult to know your scenario without seeing it, but this should work.
You can do something like this
<html ng-app="App" >
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script>
angular.module("App",[])
.controller("ctrl",['$scope',function($scope){
$scope.changedValue = function(item){
alert(item);
}
}]);
</script>
<div >
<div ng-controller="ctrl">
<select ng-model="blisterPackTemplateSelected" ng-change="changedValue(blisterPackTemplateSelected)" >
<option value="">Select Account</option>
<option value="Add">Add</option>
</select>
</div>
</div>
</html>
instead of add option you should use data-ng-options.I have used Add option for testing purpose
I am late here but I resolved same kind of problem in this way that is simple and easy.
<select ng-model="blisterPackTemplateSelected" ng-change="selectedBlisterPack(blisterPackTemplateSelected)">
<option value="">Select Account</option>
<option ng-repeat="blisterPacks in blisterPackTemplates" value="{{blisterPacks.id}}">{{blisterPacks.name}}</option>
and the function for ng-change is as follows;
$scope.selectedBlisterPack= function (value) {
console.log($scope.blisterPackTemplateSelected);
};
You will get selected option's value and text from list/array by using filter.
editobj.FlagName=(EmployeeStatus|filter:{Value:editobj.Flag})[0].KeyName
<select name="statusSelect"
id="statusSelect"
class="form-control"
ng-model="editobj.Flag"
ng-options="option.Value as option.KeyName for option in EmployeeStatus"
ng-change="editobj.FlagName=(EmployeeStatus|filter:{Value:editobj.Flag})[0].KeyName">
</select>
I had the same issue and found a unique solution. This is not best practice, but it may prove simple/helpful for someone. Just use jquery on the id or class or your select tag and you then have access to both the text and the value in the change function. In my case I'm passing in option values via sails/ejs:
<select id="projectSelector" class="form-control" ng-model="ticket.project.id" ng-change="projectChange(ticket)">
<% _.each(projects, function(project) { %>
<option value="<%= project.id %>"><%= project.title %></option>
<% }) %>
</select>
Then in my Angular controller my ng-change function looks like this:
$scope.projectChange = function($scope) {
$scope.project.title=$("#projectSelector option:selected").text();
};
I have tried some solutions,but here is basic production snippet. Please, pay attention to console output during quality assurance of this snippet.
Mark Up :
<!DOCTYPE html>
<html ng-app="appUp">
<head>
<title>
Angular Select snippet
</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" />
</head>
<body ng-controller="upController">
<div class="container">
<div class="row">
<div class="col-md-4">
</div>
<div class="col-md-3">
<div class="form-group">
<select name="slct" id="slct" class="form-control" ng-model="selBrand" ng-change="Changer(selBrand)" ng-options="brand as brand.name for brand in stock">
<option value="">
Select Brand
</option>
</select>
</div>
<div class="form-group">
<input type="hidden" name="delimiter" value=":" ng-model="delimiter" />
<input type="hidden" name="currency" value="$" ng-model="currency" />
<span>
{{selBrand.name}}{{delimiter}}{{selBrand.price}}{{currency}}
</span>
</div>
</div>
<div class="col-md-4">
</div>
</div>
</div>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js">
</script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js"></script>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js">
</script>
<script src="js/ui-bootstrap-tpls-2.5.0.min.js"></script>
<script src="js/main.js"></script>
</body>
</html>
Code:
var c = console;
var d = document;
var app = angular.module('appUp',[]).controller('upController',function($scope){
$scope.stock = [{
name:"Adidas",
price:420
},
{
name:"Nike",
price:327
},
{
name:"Clark",
price:725
}
];//data
$scope.Changer = function(){
if($scope.selBrand){
c.log("brand:"+$scope.selBrand.name+",price:"+$scope.selBrand.price);
$scope.currency = "$";
$scope.delimiter = ":";
}
else{
$scope.currency = "";
$scope.delimiter = "";
c.clear();
}
}; // onchange handler
});
Explanation:
important point here is null check of the changed value, i.e. if value is 'undefined' or 'null' we should to handle this situation.

angular: how do I make a dependent required field country->state?

I have a field country. Some countries in the list like the US or Canada are divided into states. When such countries are selected, a second select appears and is required.
HTML:
<label>Country*</label>
<select name="country" class="gu3" ng-model="companyCriteria.country" ng-options="country.label for country in countries" required=""></select>
<div class="row" ng-show="stateAvailable">
<label>Province*</label>
<select name="state" class="gu3" ng-model="companyCriteria.state" required="">
<option ng-repeat="state in states" value="{{state.code}}">{{state.label}}</option>
</select>
</div>
Controller:
app.controller('CompanyController', function ( $scope, companies , Countries, States ... ) {
//...
$scope.countries = Countries;
$scope.states = [];
$scope.stateAvailable = false;
$scope.$watch( 'companyCriteria.country', function( after, before ) {
if ( searchCompanyCriteria.country && searchCompanyCriteria.country.div ) {
$scope.states = States.get( after.code );
$scope.stateAvailable = true;
} else {
$scope.states = [];
$scope.stateAvailable = false;
}
} );
$scope.search = function () {
if ( !$scope.companyForm.$valid ) return; //Returns when states are hidden
//Do search ...
};
the problem is that $scope.companyForm.$valid is false when the state select is hidden. I'm not sure how to proceed to code it in an angular and elegant way (without having to hack with the dom the jquery way).
Note: Angular v1.2.0-rc.3
Instead of ng-show use ng-if (assuming you're using angular 1.1.5 or higher):
<div class="row" ng-if="stateAvailable">
<label>Province*</label>
<select name="state" class="gu3" ng-model="companyCriteria.state" required>
<option ng-repeat="state in states" value="{{state.code}}">{{state.label}}</option>
</select>
</div>
Or, just use ng-required:
<select name="state" ng-model="companyCriteria.state" ng-required="stateAvailable">
<option ng-repeat="state in states" value="{{state.code}}">{{state.label}}</option>
</select>
You can use ng-required to resolve an angular expression and set the field to required:
<label>Country*</label>
<select name="country" class="gu3" ng-model="companyCriteria.country" ng-options="country.label for country in countries" required=""></select>
<div class="row" ng-show="stateAvailable">
<label>Province*</label>
<select name="state" class="gu3" ng-model="companyCriteria.state" ng-required="companyCriteria.country">
<option ng-repeat="state in states" value="{{state.code}}">{{state.label}}</option>
</select>
</div>
This will only require the state, if the country has been set with a value. However, you can put in any scoped expression here (so if you want to call a controller function returning a boolean, that would work as well).
The documentation for ng-required is here.

Resources