0

I cannot figure out why data binding is not working on a select tag, as the docs specifies.

This is my select element:

<select id="start-type" ng-model="startType">
  <option value="day-of-week">Day of the week</option>
  <option value="month">Month</option>
  <option value="month-day">Day and month</option>
  <option value="year">Year</option>
  <option value="year-month">Month and year</option>
  <option value="local-time" selected>Time</option>
  <option value="local-date">Date</option>
  <option value="local-date-time">Date and time</option>
</select>
<label for="start-type">Start type</label>

The issue is that whenever an item is selected the $scope.startType model is never changed. It's always blank.

I have tried defining $scope.startType in my controller but I don't see why that would change anything because it should work as it already is. And of course, it didn't help.

I have gone through several working examples, but I can't see what I am missing here.

Edit: I figured out what's happening. The CSS framework I am using didn't have Angular in mind at all. It is rendering a custom view for a select using its own divs and layout, while hiding the actual select element. But they didn't even hook the select action into the hidden select, so the angular directives or data binding are never being triggered... Any clue on how I could put it all together?

dabadaba
  • 9,064
  • 21
  • 85
  • 155
  • "so the angular directives or data binding are never being triggered... Any clue on how I could put it all together?" - this needs to be asked as a separate question – jusopi Jul 14 '16 at 18:12
  • @jusopi yeah I know, I found out about the actual issue after creating this question. – dabadaba Jul 14 '16 at 18:38

3 Answers3

3

In order to bind to a pre selected value on the select's ng-model, you need to use ng-options instead.

<select id="start-type" 
        ng-model="startType" 
        ng-options="type.value as type.label for type in startTypes">

Where startTypes is defined on your controller:

$scope.startTypes = [{value:'day-of-week', label:'Day of Week'}, ...]

edit

Per @John S's comment below, you might want to add a default/blank option when the $scope.startType == undefined so that the UI renders correctly.

<option ng-selected="true" value="">select a market vertical</option>

source = Why does AngularJS include an empty option in select?

Community
  • 1
  • 1
jusopi
  • 6,791
  • 2
  • 33
  • 44
  • In my experience this directive will not behave properly unless you have just one option tag that looks like ``. Other than this this answer is the right way to do it. – John S Jul 14 '16 at 16:47
  • agreed, and I wish the angular team would've done a better job at handling such cases. I did answer a related issue here - http://stackoverflow.com/questions/12654631/why-does-angularjs-include-an-empty-option-in-select/36893473#36893473 – jusopi Jul 14 '16 at 16:49
  • it is actually in the AngularJS docs but they dont make a big deal of it. I missed it several times. Generally what happens is you will get the wrong index selected on the model. Super confusing. – John S Jul 14 '16 at 16:52
  • isn't there a way to make it work with fixed values in the html? The css framework I am using doesn't render the options properly if used in this fashion. It only does the other way. – dabadaba Jul 14 '16 at 16:54
  • @dabadaba it may be a value/reference type issue. Try changing $scope.startTypes to $scope.something.startTypes – John S Jul 14 '16 at 16:56
  • @JohnS No, you didn't udnerstand me. The options are showing up but they're not being rendered properly by the css framework, it looks awful. That's why I want to define a fixed select with its options instead of having them in the controller. – dabadaba Jul 14 '16 at 16:57
  • Ok this was not the issue at all. Check out my edit. – dabadaba Jul 14 '16 at 17:05
  • @dabadaba Gotcha, this is still the "Angular" way to do it. What is the CSS framework you are using? – John S Jul 14 '16 at 17:12
1

I can see it working. Check out the snippet below

  • Make sure you have the controller and the app declared correctly
  • Also use try using ng-options and have the values come from the controller like in this example.

angular.module('demo', []).controller('DemoController', function($scope) {
  $scope.logModelValue = function() {
    console.log($scope.startType);
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<body ng-app="demo">
  <div ng-controller="DemoController">
    <label for="start-type">Start type</label>
    <select id="start-type" ng-model="startType" ng-change="logModelValue()">
      <option value="day-of-week">Day of the week</option>
      <option value="month">Month</option>
      <option value="month-day">Day and month</option>
      <option value="year">Year</option>
      <option value="year-month">Month and year</option>
      <option value="local-time" selected>Time</option>
      <option value="local-date">Date</option>
      <option value="local-date-time">Date and time</option>
    </select>
    <span>{{startType}}</span>
    <button ng-click="logModelValue()">Console log model value</button>
  </div>
</body>

EDIT
Looks like the trouble is with getting materializecss and angular working together. You could either write your own angular wrappers over materializecss or use this library angular-materialize

Srijith
  • 1,434
  • 9
  • 14
  • I have tried setting up `ng-change` on the select tag and `ng-click` on any of the options to trigger a dummy method that logs something and none work. – dabadaba Jul 14 '16 at 16:46
  • Updated the snippet. I have added ng-change as well. It works. Can you try as in the snippet above? – Srijith Jul 14 '16 at 16:50
  • Yeah I tried something like that and as I said nothing is logged. The `ng-change` directive isn't being triggered. – dabadaba Jul 14 '16 at 16:56
  • Can you post your entire code here? Not sure how I can help without seeing the whole thing! – Srijith Jul 14 '16 at 16:57
  • I copied the select block directly from my project. What else would you need? – dabadaba Jul 14 '16 at 16:58
  • Well for a start your html file, ng-app, controller declaration...etc From looking at the code you posted it should work just like in my answer, but need more information to help you – Srijith Jul 14 '16 at 16:59
  • Read your edit. Try using https://github.com/krescruz/angular-materialize which has got angular wrappers for materializecss. – Srijith Jul 15 '16 at 06:08
1

I would use ng-model, and ng-change. Ng-change would be evaluated whenever the selected value is changed.