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.