Perbarui model sudut setelah menetapkan nilai input dengan jQuery

160

Saya punya skenario sederhana ini:

Elemen input yang nilainya diubah dengan metode jQuery's val ().

Saya mencoba memperbarui model sudut dengan nilai yang ditetapkan jQuery. Saya mencoba menulis arahan sederhana, tetapi tidak melakukan apa yang saya inginkan.

Inilah arahannya:

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

ini adalah bagian jQuery:

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

dan html:

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

<button>clickme</button>

Inilah biola dengan percobaan saya:
http://jsfiddle.net/U3pVM/743/

Dapatkah seseorang tolong tunjukkan saya ke arah yang benar?

Michal J.
sumber
2
Campur AngularJS dan jQuery, di luar arahan, seringkali merupakan ide yang buruk. Apakah jQuery wajib untuk apa yang ingin Anda lakukan?
Blackhole
Mengapa Anda tidak mengatur acara klik dengan sudut ke fungsi di controller untuk mengubah nilai model?
Jimmy Kane
@ Blackhole, saya menggunakan plugin upload jquery yang melakukan tugasnya dan menempatkan path ke file yang diunggah ke dalam input tersembunyi. Yang saya butuhkan adalah memiliki akses ke jalan itu dalam model sudut. Jadi saya pikir saya akan mengaturnya sebagai nilai input tersembunyi dan setelah diubah perbarui model sudut.
Michal J.
Saya tidak melihat panggilan Jquery di biola Anda ... Bisakah Anda memeriksa dan menunjukkan di mana Anda mengubah nilai dengan JQ?
Valentyn Shybanov
Biola Anda terhubung ke aplikasi sampel Todo, yang tidak berhubungan dengan pertanyaan ini.
Stewie

Jawaban:

322

ngModel mendengarkan acara "input", jadi untuk "memperbaiki" kode Anda, Anda harus memicu acara itu setelah menetapkan nilainya:

$('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
});

Untuk penjelasan tentang perilaku khusus ini, periksa jawaban yang saya berikan beberapa waktu lalu: " Bagaimana AngularJS secara internal menangkap peristiwa seperti 'onclick', 'onchange'? "


Namun sayangnya, ini bukan satu-satunya masalah yang Anda miliki. Seperti yang ditunjukkan dengan komentar posting lainnya, pendekatan jQuery-centric Anda jelas salah. Untuk info lebih lanjut, lihat posting ini: Bagaimana cara "berpikir dalam AngularJS" jika saya memiliki latar belakang jQuery? ).

Stewie
sumber
5
Keren! Dengan satu pengecualian: mengapa tidak bekerja pada input tersembunyi? Ketika saya mengalihkan jenis input saya ke teks, itu berfungsi seperti yang diharapkan.
Karol
8
Ini memecahkan masalah besar saat menggunakan plugin kalender jquery. Dengan meretas plugin untuk memicu ('input') setelah input.val () acara ng-change menyala setelah pengguna memilih tanggal kalender. Terima kasih!
Drone Brain
3
Berfungsi sempurna pada input tersembunyi: element.triggerHandler ("change");
falko
2
ini tidak bekerja untuk saya. $ ("# Distance"). Val (data); $ ("# Distance"). Trigger ('input');
Stas Svishov
10
Dengan Angular 1.4.3, inputacara tidak berfungsi di IE termasuk IE11. inputPeristiwa hanya berfungsi ketika $sniff.hasEvent('input')benar tetapi $sniff.hasEvent('input')salah bahkan di IE11! Kita bisa menggunakan changeacara sebagai gantinya.
Shuhei Kagawa
61

Semoga ini bermanfaat bagi seseorang.

Saya tidak bisa mendapatkan jQuery('#myInputElement').trigger('input')acara untuk diambil aplikasi sudut saya.

Namun saya angular.element(jQuery('#myInputElement')).triggerHandler('input')bisa dijemput.

ginman
sumber
2
tolong jelaskan solusinya, jangan hanya menulis kode. saya mendapatkan sudut bukan $ bukan fungsi
Thakhani Tharage
1
$ mewakili jQuery di sini. Itu ditandai dalam pertanyaan.
ginman
Ini bekerja untuk saya juga sementara $ ('myInputElement'). Trigger ('input') tidak stabil. Kadang-kadang tampaknya bekerja secara acak tetapi tidak yang lain dan saya tidak pernah bisa membangun pola. Solusi ini berfungsi setiap saat.
BryanP
2
Milik saya bekerja dengan # awalan:angular.element($('#myInputElement')).triggerHandler('input')
Ebru Yener
PemicuHandler ini bekerja untuk saya juga, saya berurusan dengan textarea bukan input. Terima kasih
Mounir
25

Jawaban yang diterima yang memicu inputacara dengan jQuery tidak berhasil untuk saya. Membuat acara dan mengirim JavaScript asli berhasil.

$("input")[0].dispatchEvent(new Event("input", { bubbles: true }));
Martins Balodis
sumber
Ini juga solusi bagi saya. Menggunakan Angular 1.1.5, jQuery 2.2.4 dan Jasmine 2.5.3. Sangat, SANGAT aneh bahwa tidak ada mekanisme pemicu lain yang berfungsi.
Lars-Erik
Saya sedang mencari metode JS asli untuk memicu validasi formulir ketika menetapkan input dalam skrip dan ini berhasil bagi saya, terima kasih.
bubar
Bekerja bahkan dengan Angular 5, hebat!
Igor
Terima kasih. Terutama membantu dalam webview.evaluatejavascript
Berry Wing
22

Saya tidak berpikir jQuery diperlukan di sini.

Anda bisa menggunakan $ watch dan ng-klik saja

<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>

Di controller Anda:

$scope.$watch('foo', function(newValue, oldValue) {
  console.log(newValue);
  console.log(oldValue);
});
Utopik
sumber
1
Terima kasih Utopik, Anda benar, saya tidak boleh mencampur jquery dengan sudut ketika ada cara bagaimana melakukan pekerjaan menggunakan sudut.
Michal J.
17

Anda harus menggunakan kode berikut untuk memperbarui ruang lingkup model input spesifik sebagai berikut

$('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;
    });
});
jayM
sumber
1
var scope = angular.element($("select")).scope(); scope.$apply(function(){ scope.selectValue = newVal; }); porsi itu banyak membantu saya. Masalah saya memperbarui model sudut setelah panggilan ajax jquery dalam fungsi sukses. Itu lambat dengan $ http karena ada duplikat pendengar perubahan acara untuk elemen yang melakukan sesuatu yang lain jadi saya menggabungkannya ke dalam jQuery.
Emmanuel Mahuni
1
Penggunaan element.scope () adalah ide yang buruk, karena itu hanya berfungsi dengan logging diaktifkan. Jika Anda berada di situs produksi, Anda harus menonaktifkan logging pada konfigurasi Anda dengan $compileProvider.debugInfoEnabled(false);atau $logProvider.debugEnabled(false);Lihat code.angularjs.org/1.4.0/docs/guide/production untuk info lebih lanjut.
RWAM
Saya mencoba metode ini untuk variabel tersembunyi dan berhasil. 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;}); variabel tersembunyi didefinisikan sebagai: <input id = "li_cuboid_id" type = hidden ng-model = "cuboidId">
Rahul Varadkar
7

Saya membuat modifikasi hanya pada inisialisasi pengontrol dengan menambahkan pendengar pada tombol tindakan:

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

Solusi lain tidak berfungsi dalam kasus saya.

Ebru Yener
sumber
4

Saya tahu agak terlambat untuk menjawab di sini, tetapi mungkin saya bisa menghemat beberapa hari sekali.

Saya telah berurusan dengan masalah yang sama. Model tidak akan terisi setelah Anda memperbarui nilai input dari jQuery. Saya mencoba menggunakan peristiwa pemicu tetapi tidak ada hasilnya.

Inilah yang saya lakukan yang dapat menyelamatkan hari Anda.

Deklarasikan variabel dalam tag skrip Anda dalam HTML.

Suka:

<script>
 var inputValue="";

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

</script>

Setelah Anda melakukannya dengan menggunakan layanan angular di bawah ini.

$ window

Sekarang di bawah ini fungsi getData dipanggil dari lingkup pengontrol yang sama akan memberi Anda nilai yang Anda inginkan.

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

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

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

Saya telah menulis plugin kecil ini untuk jQuery yang akan membuat semua panggilan untuk .val(value)memperbarui elemen sudut jika ada:

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

Cukup masukkan skrip ini setelah jQuery dan angular.js dan val(value)pembaruan sekarang akan berfungsi dengan baik.


Versi yang diperkecil:

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

Contoh:

dav_i
sumber
Maaf menggali serius ini, tetapi tahu bagaimana ini akan / bisa bekerja dengan kotak centang atau memilih karena mereka menggunakan .prop bukannya .val? Ini berfungsi sempurna untuk input .val perubahan setidaknya jadi terima kasih!
Austin
@Austin aku takut aku tidak tahu. Ini adalah pertanyaan berusia 5 tahun tentang dua teknologi yang secara luas dianggap ketinggalan zaman, karena itu saya belum menyimpan pengetahuan itu di kepala saya. Semoga berhasil mendapatkan solusi yang Anda butuhkan.
dav_i
2

Jika Anda menggunakan IE, Anda harus menggunakan: input.trigger ("change");

William
sumber
2

tambahkan .change()setelah mengatur nilai.

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

juga jangan lupa menambahkan onchangeatau ng-changememberi tag dalam html

Azeez
sumber
0

Saya melakukan ini untuk dapat memperbarui nilai ngModel dari luar dengan Vanilla / jQuery:

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");
anlijudavid
sumber