title: select2, ng-model and angular
body: <p>Using <a href="https://select2.github.io/" rel="nofollow">jquery-select2</a> (<strong>not</strong> ui-select) and angular, I'm trying to set the value to the ng-model.</p>
  
  <p>I've tried using <code>$watch</code> and <code>ng-change</code>, but none seem to fire after selecting an item with select2.</p>
  
  <p>Unfortunately, I am using a purchased template and cannot use angular-ui.</p>
  
  <p><strong>HTML:</strong></p>
  
  <pre><code>&lt;input type="hidden" class="form-control select2remote input-medium"
      ng-model="contact.person.id"
      value="{{ contact.person.id }}"
      data-display-value="{{ contact.person.name }}"
      data-remote-search-url="api_post_person_search"
      data-remote-load-url="api_get_person"
      ng-change="updatePerson(contact, contact.person)"&gt;
  </code></pre>
  
  <p><strong>ClientController:</strong></p>
  
  <pre><code>$scope.updatePerson = function (contact, person) {
      console.log('ng change');
      console.log(contact);
      console.log(person);
  } // not firing
  
  $scope.$watch("client", function () {
      console.log($scope.client);
  }, true); // not firing either
  </code></pre>
  
  <p><strong>JQuery integration:</strong></p>
  
  <pre><code>var handleSelect2RemoteSelection = function () {
      if ($().select2) {
          var $elements = $('input[type=hidden].select2remote');
          $elements.each(function(){
              var $this = $(this);
              if ($this.data('remote-search-url') &amp;&amp; $this.data('remote-load-url')) {
                  $this.select2({
                      placeholder: "Select",
                      allowClear: true,
                      minimumInputLength: 1,
                      ajax: { // instead of writing the function to execute the request we use Select2's convenient helper
                          url: Routing.generate($this.data('remote-search-url'), {'_format': 'json'}),
                          type: 'post',
                          dataType: 'json',
                          delay: 250,
                          data: function (term, page) {
                              return {
                                  query: term, // search term
                              };
                          },
                          results: function (data, page) { // parse the results into the format expected by Select2.
                              return {
                                  results: $.map(data, function (datum) {
                                      var result = {
                                          'id': datum.id,
                                          'text': datum.name
                                      };
                                      for (var prop in datum) {
                                          if (datum.hasOwnProperty(prop)) {
                                              result['data-' + prop] = datum[prop];
                                          }
                                      }
                                      return result;
                                  })
                              }
                          }
                      },
                      initSelection: function (element, callback) {
                          // the input tag has a value attribute preloaded that points to a preselected movie's id
                          // this function resolves that id attribute to an object that select2 can render
                          // using its formatResult renderer - that way the movie name is shown preselected
                          var id = $(element).val(),
                              displayValue = $(element).data('display-value');
                          if (id &amp;&amp; id !== "") {
                              if (displayValue &amp;&amp; displayValue !== "") {
                                  callback({'id': $(element).val(), 'text': $(element).data('display-value')});
                              } else {
                                  $.ajax(Routing.generate($this.data('remote-load-url'), {'id': id, '_format': 'json'}), {
                                      dataType: "json"
                                  }).done(function (data) {
                                      callback({'id': data.id, 'text': data.name});
                                  });
                              }
                          }
                      },
                  });
              }
          });
      }
  };
  </code></pre>
  
  <p>Any advice would be greatly appreciated! :)</p>
  
  <p><strong>UPDATE</strong></p>
  
  <p>I've managed to put together <a href="http://plnkr.co/edit/Ca0fCKFPHjZCPh3OUMYg" rel="nofollow">a plunk</a> which seems to similarly reproduce the problem - it now appears as if the ng-watch and the $watch events are fired only when first changing the value.
  Nevertheless, in my code (and when adding further complexity like dynamically adding and removing from the collection), it doesn't even seem to fire once.</p>
  
  <p>Again, pointers in the right direction (or in any direction really) would be greatly appreciated!</p>