Angular.js Select tag via ‘ng-control’

Subtitle:  Don’t Trust Your Eyes

My project has been bouncing technologies like basketballs against the backboard. The latest techno-basketball to sink is Angular.js.  I don’t intend to do a thorough review of this technology here since it is well documented in the Google/Stackoverflow community.  But I have been having fun with populating a <Select> tag’s options using the built in angular directives.

First here are some links I found useful in my quest to resolve this issue:

Basically I am replacing this code block (originally coded to work in a Dust.js format:

<!-- Year -->
<div>
  <label for="yearID">Year:</label>
  <div>
    <select id="yearID" name="year"
      value="{{ academicRecords[0].completionYear }}"
      ng-model="academicRecords[0].completionYear">
      title="Please select the completion year"></select>

… with the Angular directive code below:

<select 
   ng-options="y.value as y.option for y in yearList" 
   ng-model="academicRecords[0].completionYear">
     <option style="display:none" " 
             title="Please select the completion year">
             Year:
     </option>
</select>

First thing i have to do is create a $scope.yearList (my name) variable to populate the list:

$scope.yearList = $scope.getYearList();

And here is $scope.getYearList() function and the other supporting variable/function to populate this list:

$scope.getYearList = function () {
   var min = 50 ;  // Number of years to reach back to
   var year = new Date().getFullYear();
   var yearArray = [];

   do {
     // yearID.add( new Option(year,year), null );
     yearArray.push($scope.yearObject(year--));
     min--;
   } while (min>0);
   return yearArray;
 }
// Create individual JSON Array objects to populate list
$scope.yearObject = function (year) {
 return {
   option: ""+year ,  value : ""+year }
 }

Assign the appropriate function call to the <select>’s ng-option:

ng-options="y.value group by y.option for y in yearList"

$scope.yearList as entry point fulfills this request (fills out my list.)

With everything setup I have a beautiful (auto-populated) Select List of Option Labels appropriately populating. My head scratcher at this point is controlling which values goe into the ‘Value=”” ‘ tag.  It is being generated as a 0 based list.  {0-49 in this case}

Image

But the option value is correct (see 2012) above. So it *can’t* (famous last words) be a monumental effort get the correct values in “value=” as well.

So I Google search the following:  angular ng-option value.  

And here is what I come up with:

  • Using a case where the year comes back as 1984, submitting the form I see the following result (from Google Chrome Dev Mode):

YearCompleted:
Constructor
$dirty: false
$error: Object
$formatters: Array[0]
$invalid: false
$modelValue: “1984”
$name: “YearCompleted”
$parsers: Array[0]
$pristine: true
$render: function render()
{ $setPristine: function ()
{ $setValidity: function (validationErrorKey, isValid)
{ $setViewValue: function (value)
{ $valid: true $viewChangeListeners: Array[0]
$viewValue: “1984”

Despite the <option value=”0″>2013</option>  not being the value=”” we may intuitively KNOW should be present (via standard HTML processing,)  the 2-way binding correct delivers the correctly selected value upon submit.An astute developer should rightly note my example’s values and text are the same :

<option value=2013>2013</option>

So I ran a quick test in which I changed the JSON populating the target select tag

$scope.yearObject = function (year) {
  return {
    value: 'Pass Me! Pass Me!'+year ,
    text : ''+year
  }
 }

Notice for the “value : ” JSON element I added:

'Pass Me! Pass Me!'+year ,

GIVEN: none of the above code populating the SELECT tag was modified

RESULT: refreshing browser, choosing year 2001:

angular.js.select-2001

Despite choosing ‘2001’, it still shows ‘2013’ selected.

We will see this is an auto-magical mind bender at this point.

I Click [SUBMIT] and the Chrome DevConsole reveals to me the submitted values (via 2 way binding) are the following:

$valid: true
YearCompleted: Constructor
$dirty: true
$error: Object
$formatters: Array[0]
$invalid: false
$modelValue: "Pass Me! Pass Me!2001"
$name: "YearCompleted"
$parsers: Array[0]
$pristine: false
$render: function render() {
$setPristine: function () {
$setValidity: function (validationErrorKey, isValid) {
$setViewValue: function (value) {
$valid: true
$viewChangeListeners: Array[0]
$viewValue: "Pass Me! Pass Me!2001"

Intuitively any Web Developer will expect the “Value” property of an <Option> tag to get picked up and passed to the 2-way binding (causing us to see the list Id’s in the
“value” property as a problem.)  But (beyond the scope of my research tonight) Angular is tracking the values elsewhere, so upon submit, the appropriate value  {probably keyed to the Id’ values} is bound to the variable/object.  This is why I subtitled this blog post Don’t Trust Your Eyes.

Hopefully this will be found helpful to those who initially have this same question as you start working with Angular.  Happy Coding!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s