AngularJS : jQuery로 변경 될 때 ng-model 바인딩이 업데이트되지 않음


98

이것은 내 HTML입니다.

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

상자에 입력하면 양방향 바인딩 메커니즘을 통해 모델이 업데이트됩니다. 단.

그러나 JQuery를 통해 이것을 할 때 ...

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

모델을 업데이트하지 않습니다. 왜?


1
두 번째로 시작하는 이유는 무엇입니까? 프레임 워크를 사용하고 있으며이를 우회하고 DOM 조작을 통해 값을 설정하기로 결정합니다. 초보자에게 각도로 줄 수있는 최고의 조언 : jquery가 있다는 것을 잊어 버리십시오. 90 %의 경우 angular는 충분하고 나머지 10 %는 지시문의 링크 내에서 jqlite를 통해 얻을 수 있습니다 (요소는 실제로 조작 할 준비가 된 jqlite 래핑 된 요소입니다).
무효

1
매우 중요한 질문
에드 메릴랜드 Kamruzzaman.

DOM 조작을 사용하여 각도 모델을 변경하고 싶을 수있는 매우 좋은 이유가 있습니다. A / B 테스트 도구를 사용하는 개발자이거나이면에서 양식을 채우고 싶거나 greasemonkey 스크립트를 작성 중일 수 있습니다. 양식을 자동 완성합니다.
Shadaez

답변:


134

Angular는 그 변화에 대해 알지 못합니다. 이를 위해 다음을 호출 $scope.$digest()하거나 변경 해야합니다 $scope.$apply().

$scope.$apply(function() { 
   // every changes goes here
   $('#selectedDueDate').val(dateText); 
});

더티 검사 를 더 잘 이해하려면 이것을 참조하십시오.

업데이트 : 다음 은 예입니다.


: 나는 당신처럼이 만든이 말을 fiddle.jshell.net/AladdinMhaimeed/agvTz/8을 하지만이 작동하지 않습니다
알라딘 Mhemed

1
fiddle.jshell.net/agvTz/38을 참조하십시오 function. $ scope. $ apply를 호출하여 함수를 인수로 전달해야합니다. 그리고 $ scope를 변경할 때 $ apply를 호출해야합니다. 아, 예를 들어 컨트롤러 내부에 DOM 조작을 넣을 것으로 예상합니다. 실제 앱에서는 이것이 잘못되었습니다.)
Renan Tomal Fernandes

그러면 좋은 각도 연습을하려면 어떻게해야합니까? DOM 조작을 지시문으로 분리 하시겠습니까?
Aladdin Mhemed 2010 년

2
예, 여기에 fiddle.jshell.net/agvTz/39 예제가 있습니다 . 지시문은 간단한 datepicker="scopeKeyThatYouWant"입력으로 원하는만큼 여러 번 사용할 수 있습니다
Renan Tomal Fernandes

.. $ scope. $ digest ()를 호출하여 해결하십시오. 느려질까요?
Thant Zin

29

그냥 사용하십시오.

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

이벤트 trigger('input')에서 datepicker와 함께 사용 했습니다 onSelect. 값을 올바르게 업데이트합니다.
iman

이것은 나를 위해 트릭을했습니다. 지시문 테스트에서 바인딩 된 입력 값을 업데이트하고 .val('something'호출을 래핑 $apply(또는 $digest나중에 호출 )하지 못했습니다.
Tom Seldon 2015

2
몇 시간의 검색 끝에 이것이 작동했습니다! 감사합니다!
Dan

Alhamdulillah, 완벽합니다. 덕분에 내 시간을 저장합니다
에드 메릴랜드를 Kamruzzaman.

진실. 나는 $('#selectedDueDate').val(dateText).trigger('change');나를 위해 일하지 않는 것을 사용하고 있었다. .trigger('input');마법처럼 작동
jafarbtech

17

변수를 범위에 직접 배치하지 않으면 더 안정적으로 업데이트된다는 것을 발견했습니다.

"dateObj.selectedDate"를 사용해보고 컨트롤러에서 selectedDate를 dateObj 객체에 다음과 같이 추가합니다.

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

이것은 나를 위해 일했습니다.


4
이것은 나에게도 효과적이었습니다. 양방향 바인딩이 작동하지 않는 이유를 파악하기 위해 2 시간 이상을 낭비했습니다. 페이지에서는 제대로 작동했지만 컨트롤러의 범위가 업데이트되지 않았습니다. 그런 다음 나는 절망에서 당신의 접근 방식을 시도했습니다 (이것이 사실이어야한다는 것이 이해가되지 않았기 때문에) 그리고 뜨거운 젠장, 작동했습니다! 감사!
TMc 2014 년

3
여기도 마찬가지입니다. angularJs 전문가가 이것이 왜 작동하는지 설명 할 수 있습니까? 뷰는 그 자체가 중첩 된 범위의이 때로는 문제가 발생할 업데이트를 바로보기 - 범위가 아닌 컨트롤러 범위를 얻을 것입니다
톰 카버

1
나를 위해 잘 작동합니다! 도대체 왜 베어 스코프에서 똑같이 작동하지 않는지 궁금합니다.
Stephen

1
각도와는 거의 관련이 없으며 자바 스크립트가 작동하는 방식과 관련이 있습니다. 범위 변수를 객체에 할당하면 var가 기본 값과 동일하게 설정 될 때 수행되는 값이 아니라 참조로 할당됩니다. 나는 여기 내 게시물에서 그것에 대해 이야기했습니다. stackoverflow.com/questions/14527377/... . 나는 plnkr.co/edit/WkCT6aYao3qCmzJ8t5xg?p=preview 를 설명하기 위해 그 게시물에서 만든이 플렁크 를 참조 했습니다 .
닉 브래디

4

이 시도

var selectedDueDateField = document.getElementById("selectedDueDate");
var element = angular.element(selectedDueDateField);
element.val('new value here');
element.triggerHandler('input');

angular의 컨트롤러 $ scope에 접근 할 수 없을 때 사용할 수 있습니다. 예를 들어 Tampermonkey로 스크립트를 작성할 때.
wassertim


2

Angular의 범위 밖에서 일어나는 일이 무엇이든 Angular는 그것을 결코 알 수 없습니다.

다이제스트 사이클은 모델-> 컨트롤러에서 변경 한 다음 컨트롤러-> 모델에서 변경합니다.

최신 모델을 확인해야하는 경우 다이제스트주기를 트리거해야합니다.

그러나 다이제스트주기가 진행 중일 가능성이 있으므로주기를 확인하고 초기화해야합니다.

가급적이면 항상 안전한 적용을 수행하십시오.

       $scope.safeApply = function(fn) {
            if (this.$root) {
                var phase = this.$root.$$phase;
                if (phase == '$apply' || phase == '$digest') {
                    if (fn && (typeof (fn) === 'function')) {
                        fn();
                    }
                } else {
                    this.$apply(fn);
                }
            }
        };


      $scope.safeApply(function(){
          // your function here.
      });

1

AngularJS는 문자열, 숫자 및 부울을 값으로 전달하고 배열과 객체를 참조로 전달합니다. 따라서 빈 개체를 만들고 날짜를 해당 개체의 속성으로 만들 수 있습니다. 그런 식으로 각도는 모델 변경을 감지합니다.

컨트롤러에서

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

HTML에서

<div ng-controller="yourController">
<input id="selectedDueDate" type="text" ng-model="vm.selectedDate" />
</div>

1

ng-model은 입력 이벤트를 수신하고 범위가 업데이트되므로 입력 요소 의 변경 이벤트 를 트리거해야합니다 . 그러나 일반 jQuery 트리거가 작동하지 않았습니다 . 하지만 여기에 매력처럼 작동하는 것이 있습니다.

$("#myInput")[0].dispatchEvent(new Event("input", { bubbles: true })); //Works

팔로 잉이 작동하지 않았습니다.

$("#myInput").trigger("change"); // Did't work for me

합성 이벤트 생성 및 전달 에 대해 자세히 알아볼 수 있습니다 .


0

나는 jQuery를위한이 작은 플러그인을 작성했다. 이것은 .val(value)존재한다면 각도 요소 를 업데이트 하기 위해 모든 호출을 할 것이다.

(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);

jQuery와 angular.js 다음에이 스크립트를 넣으면 val(value)업데이트가 잘 작동합니다.


축소 된 버전 :

!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);

예:


이 대답은 다른 유사한 질문에 대한 내 대답 에서 그대로 복사되었습니다 .


0

다음을 사용하십시오.

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

대신에:

$('#selectedDueDate').val(dateText);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.