jQueryで入力値を設定した後に角度モデルを更新する


160

私はこの簡単なシナリオを持っています:

jQueryのval()メソッドによって値が変更される入力要素。

jQueryが設定した値で角度モデルを更新しようとしています。単純なディレクティブを記述しようとしましたが、それは私が望むことをしていません。

ディレクティブは次のとおりです。

var myApp = angular.module('myApp', []);
myApp.directive('testChange', function() {
    return function(scope, element, attrs) {        
        element.bind('change', function() {
            console.log('value changed');
        })
    }
})

これはjQuery部分です:

$(function(){
    $('button').click(function(){
        $('input').val('xxx');
    })
})

およびhtml:

<div ng-app="myApp">
    <div ng-controller="MyCtrl">
        <input test-change ng-model="foo" />
        <span>{{foo}}</span>
    </div>
</div>

<button>clickme</button>

これが私の試みのフィドルです:http :
//jsfiddle.net/U3pVM/743/

誰かが私を正しい方向に向けてもらえますか?


2
ディレクティブ以外でAngularJSとjQueryを混在させることは、多くの場合悪い考えです。あなたがしたいことのためにjQueryは必須ですか?
ブラックホール2013年

モデルの値を変更するために、コントローラの関数に角度を付けたクリックイベントを設定してみませんか?
ジミー・ケイン

@Blackhole、私はその仕事をし、アップロードされたファイルへのパスを隠し入力に入れるjqueryアップロードプラグインを使用しています。私が必要なのは、角度モデルでそのパスにアクセスすることだけです。だから私はそれを隠された入力の値として設定し、それが変更された後に角度モデルを更新すると思いました。
Michal J.

私のフィドルにJqueryの呼び出しが表示されません... JQで値を変更する場所を確認してポイントできますか?
Valentyn Shybanov 2013年

あなたのフィドルは、この質問とは関係のないTodoサンプルアプリにリンクしています。
Stewie 2013年

回答:


322

ngModelは「入力」イベントをリッスンするため、コードを「修正」するには、値を設定した後にそのイベントをトリガーする必要があります。

$('button').click(function(){
    var input = $('input');
    input.val('xxx');
    input.trigger('input'); // Use for Chrome/Firefox/Edge
    input.trigger('change'); // Use for Chrome/Firefox/Edge + IE11
});

「:私はしばらく前に与えたことを、この答えて、この特定の動作チェックの説明についてはどのようにAngularJSは、内部的に『onclickの』、 『のonchange』のようなイベントをキャッチしますか?


しかし、残念ながら、これが唯一の問題ではありません。他の投稿コメントで指摘されているように、jQuery中心のアプローチは明らかに間違っています。詳細については、この投稿をご覧ください。jQueryのバックグラウンドがある場合、どうすれば「AngularJSで考える」ことができますか?)。


5
涼しい!1つの例外を除いて、なぜそれが隠し入力で機能しないのですか?入力タイプをテキストに切り替えると、期待どおりに機能します。
Karol 2013

8
これにより、jqueryカレンダープラグインを使用する際の主要な問題が解決されました。プラグインをハックして、input.val()の後にトリガー( 'input')することにより、ユーザーがカレンダーの日付を選択した後にng-changeイベントが発生します。ありがとう!
ドローンブレイン

3
非表示の入力で完璧に機能します:element.triggerHandler( "change");
ファルコ2013

2
これは私にはうまくいきません。$( "#Distance")。val(data); $( "#Distance")。trigger( 'input');
Stas Svishov 2014年

10
Angular 1.4.3では、inputイベントはIE11を含むIEでは機能しません。 inputイベント$sniff.hasEvent('input')はtrueの場合にのみ機能します$sniff.hasEvent('input')、IE11でもfalseです。代わりにchangeイベント を使用できます。
香川周平

61

これが誰かに役立つことを願っています。

jQuery('#myInputElement').trigger('input')角度の付いたアプリでイベントを取得できませんでした。

しかし、angular.element(jQuery('#myInputElement')).triggerHandler('input')迎えに来ることができました。


2
ソリューションを説明するだけでコードを記述しないでください。私は角張っていません$は関数ではありません
タハニタラージ2015年

1
ここで$はjQueryを表します。質問にタグ付けされています。
ジンマン2015年

$( 'myInputElement')。trigger( 'input')が不安定な間、これも私にとってはうまくいきました。それは時々ランダムに機能するように見えて他の人には機能しなかったようで、私はパターンを確立できませんでした。このソリューションは常に機能します。
BryanP 2015

2
鉱山は#接頭辞で処理されます:angular.element($('#myInputElement')).triggerHandler('input')
Ebru Yener '26

このtriggerHandlerも私のために働きました、私は入力ではなくtextareaを扱っていました。ありがとう
Mounir

25

inputjQueryでイベントをトリガーするという承認された回答が機能しませんでした。イベントを作成し、ネイティブJavaScriptでディスパッチすることでうまくいきました。

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

これも私の解決策でした。Angular 1.1.5、jQuery 2.2.4およびJasmine 2.5.3を使用します。非常に、他のトリガーメカニズムが機能しないことは非常に奇妙です。
Lars-Erik

スクリプトで入力を設定するときにフォーム検証をトリガーするネイティブJSメソッドを探していましたが、これでうまくいきました。
分散

Angular 5でも動作します!
イゴール

ありがとうございました。特にwebview.evaluatejavascriptで役立ちます
Berry Wing

22

ここではjQueryは必要ないと思います。

代わりに$ watchng-clickを使用できます

<div ng-app="myApp">
  <div ng-controller="MyCtrl">
    <input test-change ng-model="foo" />
    <span>{{foo}}</span>

    <button ng-click=" foo= 'xxx' ">click me</button>
    <!-- this changes foo value, you can also call a function from your controller -->
  </div>
</div>

あなたのコントローラーで:

$scope.$watch('foo', function(newValue, oldValue) {
  console.log(newValue);
  console.log(oldValue);
});

1
Utopikに感謝します。そうです、angularを使用してジョブを実行する方法がある場合、jqueryとangularを混在させるべきではありません。
Michal J.

17

特定の入力モデルのスコープを次のように更新するには、次のコードを使用する必要があります

$('button').on('click', function(){
    var newVal = $(this).data('val');
    $('select').val(newVal).change();

    var scope = angular.element($("select")).scope();
    scope.$apply(function(){
        scope.selectValue = newVal;
    });
});

1
var scope = angular.element($("select")).scope(); scope.$apply(function(){ scope.selectValue = newVal; }); その部分は私を大いに助けました。私の問題は、success関数でjquery ajaxを呼び出した後に角度モデルを更新することでした。$ httpでは、他のことをしている要素の変更イベントリスナーが重複していたため、遅いため、jQueryにマージしました。
Emmanuel Mahuni 2016

1
element.scope()の使用は、ロギングが有効になっている場合にのみ機能するため、お勧めできません。本番サイトを使用している場合は、設定でのロギングを無効にする$compileProvider.debugInfoEnabled(false);か、$logProvider.debugEnabled(false);詳細についてcode.angularjs.org/1.4.0/docs/guide/productionを参照してください。
RWAM

私は隠し変数にこのメソッドを試してみましたが、うまくいきました。var li_cuboid_id = $( '#li_cuboid_id'); li_cuboid_id.val(json.cuboidId).change(); var scope = angular.element($( "#li_cuboid_id"))。scope(); scope。$ apply(function(){scope.cuboidId = json.cuboidId;}); 非表示の変数は次のように定義されます:<input id = "li_cuboid_id" type = hidden ng-model = "cuboidId">
Rahul Varadkar

7

アクションボタンにリスナーを追加して、コントローラーの初期化のみに変更を加えました。

$(document).on('click', '#action-button', function () {
        $timeout(function () {
             angular.element($('#input')).triggerHandler('input');
        });
});

他の解決策は私の場合うまくいきませんでした。


4

ここで答えるのが少し遅いのはわかっていますが、1日1回節約できるかもしれません。

私は同じ問題を扱ってきました。jQueryからの入力の値を更新すると、モデルは入力されません。トリガーイベントを使用しようとしましたが、結果がありませんでした。

これが私があなたの日を救うかもしれないことです。

HTMLのスクリプトタグ内で変数を宣言します。

お気に入り:

<script>
 var inputValue="";

// update that variable using your jQuery function with appropriate value, you want...

</script>

以下の角度のサービスを使用してそれを実行したら。

$ window

次に、同じコントローラスコープから呼び出されたgetData関数は、必要な値を提供します。

var myApp = angular.module('myApp', []);

app.controller('imageManagerCtrl',['$scope','$window',function($scope,$window) {

$scope.getData = function () {
    console.log("Window value " + $window.inputValue);
}}]);

3

.val(value)存在する場合、角度要素を更新するためにすべての呼び出しを行うjQuery用のこの小さなプラグインを作成しました。

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

例:


これを深く掘り下げて申し訳ありませんが、これがチェックボックスまたは選択でどのように/機能するかについての考えは、それらが.valの代わりに.propを使用しているためですか?これは、少なくとも入力.valの変更に対して完全に機能しているので、ありがとうございます!
オースティン

@オースティンわからない。これは、古くなっていると広く考えられている2つのテクノロジーに関する5年前の質問です。そのため、知識を頭に残していません。しかし、あなたが必要とする解決策を得るために幸運を祈ります。
dav_i

2

IEを使用している場合は、次を使用する必要があります。input.trigger( "change");


2

.change()値を設定してから追加してください。

例:('id').val.('value').change();

また、html に追加onchangeまたはng-changeタグ付けすることを忘れないでください


0

Vanilla / jQueryを使用して外部からngModelの値を更新できるようにするために、これを行いました。

function getScope(fieldElement) {
    var $scope = angular.element(fieldElement).scope();
    var nameScope;
    var name = fieldElement.getAttribute('name');
    if($scope) {
        if($scope.form) {
            nameScope = $scope.form[name];
        } else if($scope[name]) {
            nameScope = $scope[name];
        }
    }
    return nameScope;
}

function setScopeValue(fieldElement, newValue) {
    var $scope = getScope(fieldElement);
    if($scope) {
        $scope.$setViewValue(newValue);
        $scope.$validate();
        $scope.$render();
    }
}

setScopeValue(document.getElementById("fieldId"), "new value");
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.