Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

This is my HTML:

<input id="selectedDueDate" type="text" ng-model="selectedDate" />

When I type into the box, the model is updated via the 2-way-binding mechanism. Sweet.

However when I do this via JQuery...

$('#selectedDueDate').val(dateText);

It doesn't update the model. Why?

share|improve this question

7 Answers 7

up vote 57 down vote accepted

Angular doesn't know about that change. For this you should call $scope.$digest() or make the change inside of $scope.$apply(function() { $()... });

See this to better understand dirty-checking

UPDATE: Here is an example

share|improve this answer
    
I made this like you say: fiddle.jshell.net/AladdinMhaimeed/agvTz/8 but it does not work –  Aladdin Homs Oct 16 '12 at 5:58
1  
See this fiddle.jshell.net/agvTz/38 You should call the function $scope.$apply passing a function as argument. And $apply should be call when you will make the changes on $scope, so, inside of onSelect. Ah, I expect that you put DOM manipulation inside of controller just for the example, in a real app this is wrong ;) –  Renan Tomal Fernandes Oct 16 '12 at 15:05
    
then what should I do to make good angular practice? separate DOM manipulation into a directive? –  Aladdin Homs Oct 17 '12 at 3:16
1  
Yes, here an example fiddle.jshell.net/agvTz/39 the directive can be used as many times you want with a simple datepicker="scopeKeyThatYouWant" in the input –  Renan Tomal Fernandes Oct 17 '12 at 3:45
    
Just call.. $scope.$digest() to settle. will it slow down ? –  Thant Zin Jun 4 '13 at 2:52

I have found that if you don't put the variable directly against the scope it updates more reliably.

Try using some "dateObj.selectedDate" and in the controller add the selectedDate to a dateObj object as so:

$scope.dateObj = {selectedDate: new Date()}

This worked for me

share|improve this answer
1  
This worked for me as well. I'd wasted over 2 hours trying to figure out why two-way binding wasn't working. It worked fine on the page, but the scope in the controller was not being updated. Then I tried your approach out of desperation (because it made no sense to me that this should be true) and hot damn, it worked! Thanks! –  TMc May 25 '14 at 1:47
    
Same here - can any angularJs guru explain why this works? It's like the view has it's own nested scope and sometimes you get stuck updating just the view-scope, not the controller-scope –  Tom Carver Sep 15 '14 at 16:13
    
Works well for me! I wonder why in the heck it doesn't work the same on the bare scope. –  Stephen Nov 19 '14 at 3:40

Just use;

$('#selectedDueDate').val(dateText).trigger('input');
share|improve this answer
    
Doesn't work for me unfortunately. –  dav_i Mar 12 at 17:23
    
I used trigger('input') with a datepicker in its onSelect event. It updates the value correctly. –  iman Mar 17 at 19:55
    
This did the trick for me. I was updating the value of a bound input from a directive test and wrapping the .val('something' call in an $apply (or calling $digest afterward) didn't work. –  Tom Seldon 8 hours ago

I've written this little plugin for jQuery which will make all calls to .val(value) update the angular element if present:

(function($, ng) {
  'use strict';

  var $val = $.fn.val; // save original jQuery function

  // override jQuery function
  $.fn.val = function (value) {
    // if getter, just return original
    if (!arguments.length) {
      return $val.call(this);
    }

    // get result of original function
    var result = $val.call(this, value);

    // trigger angular input (this[0] is the DOM object)
    ng.element(this[0]).triggerHandler('input');

    // return the original result
    return result; 
  }
})(window.jQuery, window.angular);

Just pop this script in after jQuery and angular.js and val(value) updates should now play nice.


Minified version:

!function(n,t){"use strict";var r=n.fn.val;n.fn.val=function(n){if(!arguments.length)return r.call(this);var e=r.call(this,n);return t.element(this[0]).triggerHandler("input"),e}}(window.jQuery,window.angular);

Example:

// the function
(function($, ng) {
  'use strict';
  
  var $val = $.fn.val;
  
  $.fn.val = function (value) {
    if (!arguments.length) {
      return $val.call(this);
    }
    
    var result = $val.call(this, value);
    
    ng.element(this[0]).triggerHandler('input');
    
    return result;
    
  }
})(window.jQuery, window.angular);

(function(ng){ 
  ng.module('example', [])
    .controller('ExampleController', function($scope) {
      $scope.output = "output";
      
      $scope.change = function() {
        $scope.output = "" + $scope.input;
      }
    });
})(window.angular);

(function($){  
  $(function() {
    var button = $('#button');
  
    if (button.length)
      console.log('hello, button');
    
    button.click(function() {
      var input = $('#input');
      
      var value = parseInt(input.val());
      value = isNaN(value) ? 0 : value;
      
      input.val(value + 1);
    });
  });
})(window.jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div ng-app="example" ng-controller="ExampleController">
  <input type="number" id="input" ng-model="input" ng-change="change()" />
  <span>{{output}}</span>
  <button id="button">+</button>
</div>


This answer was copied verbatim from my answer to another similar question.

share|improve this answer

I think what you are trying to use is just the Angular HTML Templating. You do not need to use AngularJS to accomplish this.

This is available in Mustache https://mustache.github.io/

You can update your model and then just re-template the required area (calling Mustache).

share|improve this answer

AngularJS pass string, numbers and booleans by value while it passes arrays and objects by reference. So you can create an empty object and make your date a property of that object. In that way angular will detect model changes.

In controller

app.module('yourModule').controller('yourController',function($scope){
$scope.vm={selectedDate:''}
});

In html

<div ng-controller="yourController">
<input id="selectedDueDate" type="text" ng-model="vm.selectedDate" />
</div>
share|improve this answer

Angular doesn't know about that change using jquery.

<input id="selectedDueDate" type="text" ng-model="selectedDate" />

<div ng-bind="selectedDate"></div>
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.