9
votes

online code:

http://jsfiddle.net/mb98y/309/

HTML

<div ng-app="myDirective" ng-controller="x">
    <input id="angular" type="text" ng-model="data.test" my-directive>
</div>
    <button onclick="document.querySelector('#angular').value = 'testg';">click</button>

JS

angular.module('myDirective', [])
    .directive('myDirective', function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            scope.$watch(attrs.ngModel, function (v) {
                //console.log('value changed, new value is: ' + v);
                alert('value change: ' + scope.data.test);
            });
        }
    };
});

function x($scope) {
    //$scope.test = 'value here';
    $scope.data = {
        test: 'value here'
    }
}

http://jsfiddle.net/mb98y/310/

HTML

<div ng-app="myDirective" ng-controller="x">
<input id="angular" type="text" my-directive="test">{{test}}</div>
<button onclick="document.querySelector('#angular').value =  'testg';">click</button>

JS

angular.module('myDirective', [])
    .directive('myDirective', function () {
    return {
        restrict: 'A',
        scope: {
            myDirective: '='
        },
        link: function (scope, element, attrs) {
            // set the initial value of the textbox
            element.val(scope.myDirective);
            element.data('old-value', scope.myDirective);

            // detect outside changes and update our input
            scope.$watch('myDirective', function (val) {
                element.val(scope.myDirective);
            });

            // on blur, update the value in scope
            element.bind('propertychange keyup change paste', function (blurEvent) {
                if (element.data('old-value') != element.val()) {
                    console.log('value changed, new value is: ' + element.val());
                    scope.$apply(function () {
                        scope.myDirective = element.val();
                        element.data('old-value', element.val());
                    });
                }
            });
        }
    };
});

function x($scope) {
    $scope.test = 'value here';
}

I wanna click button to set input element value and angularjs(ng-model or scope object) can get it.

But, document.querySelector('#angular').value = 'testg';

change element value in this way, Neither angularjs $watch nor bind function can get value change event. If you input some words in input element by keyboard, they both works.

How can I detect input element value change when set value in this way in angularjs?

2

2 Answers

14
votes

First of all, two-way data binding is here in order to avoid such scenarios.

 <input ng-model='ctrl.field' />

 <button ng-click='ctrl.field = "new value"'>change</button>

Second, there is ng-change directive that works together with ng-model, which can be used to do something when value in the model changed.

 <input ng-model='ctrl.field' ng-change='alert("changed!")' />

If you still want to change value outside of angular directly with DOM, just fire event that angular listen to - blur or keypressed

 <button ng-click='$("#id").val(a); $("#id").trigger("blur")'>change</button>

or

 <button ng-click='angular.element("#id").val(a); angular.element("#id").trigger("blur")'>change</button>
2
votes

Updated fiddle.

You are not supposed to use querySelector (just like you are not supposed to use jQuery) with Angular, unless you have a real good reason to.

You can just modify $scope.data.test, and your text box contents will be updated automatically. In order for this to work, you also need the button to have the same controller (so they share scope), and use ng-click instead of onclick, like so:

<div ng-app="myDirective" ng-controller="x">
    <input id="angular" type="text" ng-model="data.test" my-directive=""></input>
    <button ng-click="data.test = 'testg';">click</button>
</div>