JQuery ile giriş değerini ayarladıktan sonra açısal modeli güncelleyin


160

Bu basit senaryo var:

Değeri jQuery'nin val () yöntemiyle değiştirilen girdi öğesi.

JQuery set değeri ile açısal modeli güncellemeye çalışıyorum. Basit bir direktif yazmaya çalıştım, ama istediğimi yapmıyorum.

İşte yönerge:

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

bu jQuery kısmı:

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

ve html:

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

<button>clickme</button>

İşte denememle keman:
http://jsfiddle.net/U3pVM/743/

Birisi bana doğru yönde işaret edebilir?


2
Mix AngularJS ve jQuery, direktiflerin dışında genellikle kötü bir fikirdir. JQuery yapmak istediğiniz şey için zorunlu mudur?
Kara delik

Modelin değerini değiştirmek için neden tıklama olayını denetleyicideki bir işleve açısal olarak ayarlamıyorsunuz?
Jimmy Kane

@Blackhole, işini yapan ve yüklenen dosyaya gizli girişe giden yolu koyan jquery upload eklentisini kullanıyorum. İhtiyacım olan tek şey açısal modelde bu yola erişebilmek. Bu yüzden onu gizli girdi değeri olarak ayarlayacağımı düşündüm ve değiştirildikten sonra açısal modeli güncelleyin.
Michal J.

Kemanınızda Jquery çağrısı görmüyorum ... JQ ile değer değiştirdiğiniz yeri kontrol edebilir ve gösterebilir misiniz?
Valentyn Shybanov

Kemanınız bu soru ile ilgili olmayan bir Todo örnek uygulamasına bağlanır.
Stewie

Yanıtlar:


322

ngModel "input" olayını dinler, bu nedenle kodunuzu "düzeltmek" için değeri ayarladıktan sonra bu olayı tetiklemeniz gerekir:

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

Bu özel davranışın açıklaması için bir süre önce verdiğim cevabı inceleyin: " AngularJS dahili olarak 'onclick', 'onchange' gibi olayları nasıl yakalar? "


Ama maalesef, sahip olduğunuz tek sorun bu değil. Diğer gönderi yorumlarında belirtildiği gibi, jQuery merkezli yaklaşımınız yanlıştır. Daha fazla bilgi için şu gönderiye bir göz atın: Bir jQuery arka planım varsa “AngularJS'de nasıl düşünürüm”? ).


5
Güzel! Bir istisna dışında: neden gizli girdilerde çalışmıyor? Giriş türümü metne değiştirdiğimde, beklendiği gibi çalışıyor.
Karol

8
Bu, jquery takvim eklentilerini kullanırken büyük bir sorunu çözdü. İnput.val () sonrasında tetiklenecek eklentiyi hackleyerek ('input') ng-change olayı kullanıcı takvim tarihini seçtikten sonra tetiklenir. Teşekkürler!
Drone Brain

3
Gizli girişte mükemmel çalışır: element.triggerHandler ("change");
falko

2
bu benim için çalışmıyor. $ ( "# Uzaklık") val (veri).; $ ( "# Uzaklık") tetik ( 'giriş').;
Stas Svishov

10
Angular 1.4.3 ile inputetkinlik IE11 dahil IE üzerinde çalışmaz. inputolay yalnızca $sniff.hasEvent('input')doğru ancak $sniff.hasEvent('input')IE11'de bile yanlış olduğunda çalışır ! Bunun yerine changeetkinliği kullanabiliriz .
Shuhei Kagawa

61

Umarım bu birisi için yararlıdır.

jQuery('#myInputElement').trigger('input')Etkinliğin açısal uygulamamı almasını sağlayamadım .

Ancak alınmayı başardım angular.element(jQuery('#myInputElement')).triggerHandler('input').


2
Lütfen çözümü açıklayın sadece kod yazmayın. i açısal olsun $ değil bir işlev değil
Thakhani Tharage

1
$ burada jQuery temsil eder. Soruda etiketlenir.
ginman

$ ('MyInputElement'). Trigger ('input') lapa lapa olurken bu da benim için çalıştı. Bazen rastgele çalışıyor gibi görünüyordu ama diğerleri değil ve asla bir desen oluşturamadım. Bu çözüm her seferinde işe yarar.
BryanP

2
Benimki # önek ile çalıştı:angular.element($('#myInputElement')).triggerHandler('input')
Ebru Yener

Bu triggerHandler benim için de çalıştı, girdi olmayan textarea ile uğraşıyordum. Teşekkürler
Mounir

25

inputJQuery ile olayı tetikleyen kabul edilen cevap benim için işe yaramadı. Bir etkinlik oluşturmak ve yerel JavaScript ile göndermek hile yaptı.

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

Benim için de çözüm buydu. Açısal 1.1.5, jQuery 2.2.4 ve Jasmine 2.5.3'ü kullanma. Çok, başka hiçbir tetik mekanizmasının çalışmadığı garip.
Lars-Erik

Bir komut dosyasında bir giriş ayarlarken form doğrulama tetiklemek için yerel JS yöntemi arıyordu ve bu benim için çalıştı, teşekkürler.
Dispers

Açısal 5 ile bile çalışıyor, harika!
Igor

Teşekkür ederim. Özellikle webview.evaluatejavascript
Berry Wing

22

Burada jQuery gerekli olduğunu sanmıyorum.

Bunun yerine $ watch ve ng-click kullanabilirsiniz

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

Kumandanızda:

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

1
Teşekkür ederim Utopik, haklısın, açısal kullanarak işi yapmanın bir yolu olduğunda jquery'yi açısal ile karıştırmamalıyım.
Michal J.

17

Belirli giriş modelinin kapsamını aşağıdaki gibi güncellemek için aşağıdaki kodu kullanmanız gerekir

$('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; }); bu kısım bana çok yardımcı oldu. Benim sorunum başarı fonksiyonunda bir jquery ajax çağrısından sonra açısal bir model güncelleme oldu. Bu yüzden jQuery içine birleştirilen başka bir şey yapıyordum öğe için yinelenen değişiklik olay dinleyicisi vardı $ http ile yavaştı.
Emmanuel Mahuni

1
Element.scope () işlevinin kullanılması kötü bir fikirdir, çünkü yalnızca günlüğe kaydetme etkinken çalışır. Eğer birlikte yapılandırmasına günlüğü devre dışı bırakması gerekir üretim sitesinde Eğer varsa $compileProvider.debugInfoEnabled(false);veya $logProvider.debugEnabled(false);bakınız code.angularjs.org/1.4.0/docs/guide/production fazla bilgi için.
RWAM

Gizli değişken için bu yöntemi denedim ve işe yaradı. var li_cuboid_id = $ ('# li_cuboid_id'); li_cuboid_id.val (json.cuboidId) .change (); var scope = angular.element ($ ("# li_cuboid_id")). scope (); kapsam. $ Apply (function () {scope.cuboidId = json.cuboidId;}); gizli değişken şu şekilde tanımlanır: <input id = "li_cuboid_id" type = hidden ng-model = "cuboidId">
Rahul Varadkar

7

İşlem düğmesinde dinleyici ekleyerek yalnızca denetleyicinin başlatılmasında değişiklikler yaptım:

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

Benim durumumda başka çözümler işe yaramadı.


4

Burada cevap vermek için biraz geç olduğunu biliyorum ama belki günde bir kere kurtarabilirim.

Ben de aynı problemle uğraşıyorum. JQuery'den giriş değerini güncellediğinizde model doldurulmaz. Tetikleyici olayları kullanmayı denedim ama sonuç yok.

İşte yaptığım şey, gününüzü kurtarabilir.

Komut dosyası etiketinizdeki bir değişkeni HTML olarak bildirin.

Sevmek:

<script>
 var inputValue="";

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

</script>

Bir kez aşağıdaki açısal hizmetini kullanarak yaptı.

$ pencere

Şimdi aynı kontrolör kapsamından çağrılan getData fonksiyonu size istediğiniz değeri verecektir.

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)Varsa açısal öğeyi güncellemek için tüm çağrıları yapacak jQuery için bu küçük eklentiyi yazdım :

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

Sadece jQuery ve angular.js sonra bu komut dosyası pop ve val(value)güncellemeler şimdi güzel oynamak gerekir.


Küçültülmüş sürüm:

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

Misal:


Bunu kazmak için özür dilerim, ancak bunun onay kutusu ile nasıl çalışabileceği / çalışabileceği veya .val yerine .prop kullandığından beri seçebilecekleri hakkında herhangi bir fikir? Bu giriş .val değişiklikleri için mükemmel çalışıyor en azından çok teşekkür ederim!
Austin

@Austin korkarım bilmiyorum. Bu, yaygın olarak modası geçmiş olarak kabul edilen iki teknoloji hakkında 5 yıllık bir soru, çünkü bilgiyi kafamda tutmadım. Gereksinim duyduğunuz çözümü elde etmek için iyi şanslar.
dav_i

2

IE kullanıyorsanız şunları kullanmanız gerekir: input.trigger ("change");


2

.change()değeri ayarladıktan sonra ekleyin .

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

ayrıca html'ye eklemeyi onchangeveya ng-changeetiketlemeyi unutmayın


0

Bunu vanilla / jQuery ile dışarıdan ngModel değerini güncelleyebilmek için yaptım:

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");
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.