อัปเดตโมเดลเชิงมุมหลังจากตั้งค่าอินพุตด้วย jQuery


160

ฉันมีสถานการณ์ง่าย ๆ นี้:

องค์ประกอบอินพุตซึ่งค่าจะถูกเปลี่ยนโดยวิธี val () ของ jQuery

ฉันพยายามอัปเดตโมเดลเชิงมุมด้วยค่าที่ 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 จำเป็นสำหรับสิ่งที่คุณต้องการทำหรือไม่?
Blackhole

เหตุใดคุณจึงไม่ตั้งค่าเหตุการณ์การคลิกด้วยเชิงมุมเป็นฟังก์ชันในคอนโทรลเลอร์เพื่อเปลี่ยนค่าของแบบจำลอง
Jimmy Kane

@Blackhole ฉันใช้ jquery upload plugin ที่ใช้งานได้และใส่พา ธ ไปยังไฟล์ที่อัพโหลดไปยังอินพุตที่ซ่อนอยู่ ทั้งหมดที่ฉันต้องการคือการเข้าถึงเส้นทางนั้นในโมเดลเชิงมุม ดังนั้นฉันคิดว่าฉันจะตั้งค่าเป็นค่าของอินพุตที่ซ่อนอยู่และหลังจากเปลี่ยนการอัปเดตโมเดลเชิงมุม
มิคาลเจ.

ฉันไม่เห็นการโทร Jquery ในซอของคุณ ... คุณสามารถตรวจสอบและชี้ที่คุณเปลี่ยนค่าด้วย JQ ได้หรือไม่?
Valentyn Shybanov

ซอของคุณเชื่อมโยงไปยังแอปตัวอย่างสิ่งที่ต้องทำซึ่งไม่เกี่ยวข้องกับคำถามนี้
Stewie

คำตอบ:


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-centric ของคุณนั้นผิดปกติ สำหรับข้อมูลเพิ่มเติมดูที่โพสต์นี้: ฉันจะ“ คิดใน AngularJS” ได้อย่างไรถ้าฉันมีพื้นหลัง jQuery )


5
เย็น! ด้วยข้อยกเว้นหนึ่งประการ: ทำไมจึงไม่ทำงานกับอินพุตที่ซ่อนอยู่ เมื่อฉันสลับประเภทอินพุตเป็นข้อความมันทำงานได้ตามที่คาดไว้
Karol

8
วิธีนี้แก้ไขปัญหาสำคัญเมื่อใช้ปลั๊กอินปฏิทิน jquery โดยการแฮ็คปลั๊กอินเพื่อทริกเกอร์ ('อินพุต') หลังจาก input.val () เหตุการณ์ ng-change จะเริ่มหลังจากผู้ใช้เลือกวันที่ในปฏิทิน ขอบคุณ!
Drone Brain

3
ทำงานได้สมบูรณ์แบบในการป้อนข้อมูลที่ซ่อนอยู่: element.triggerHandler ("change");
falko

2
สิ่งนี้ไม่ได้ผลสำหรับฉัน $ ( "# ระยะทาง") Val (ข้อมูล). $ ( "# ระยะทาง") ทริกเกอร์ ( 'ป้อนข้อมูล').
Stas Svishov

10
ด้วย Angular 1.4.3 inputเหตุการณ์ไม่ทำงานบน IE รวมถึง IE11 inputเหตุการณ์ใช้งานได้เฉพาะเมื่อ$sniff.hasEvent('input')เป็นจริงแต่$sniff.hasEvent('input')เป็นเท็จแม้ใน IE11! เราสามารถใช้changeเหตุการณ์แทน
Shuhei Kagawa

61

หวังว่านี่จะเป็นประโยชน์สำหรับใครบางคน

ฉันไม่สามารถรับjQuery('#myInputElement').trigger('input')กิจกรรมเพื่อรับแอพเชิงมุมของฉัน

ผมเป็น แต่สามารถที่จะได้รับangular.element(jQuery('#myInputElement')).triggerHandler('input')จะหยิบขึ้นมา


2
กรุณาอธิบายวิธีการแก้ปัญหาอย่าเพิ่งเขียนรหัส ฉันได้รับเชิงมุมไม่ใช่ $ ไม่ใช่ฟังก์ชั่น
Thakhani Tharage

1
$ แสดง jQuery ที่นี่ มันถูกติดแท็กในคำถาม
ginman

สิ่งนี้ใช้ได้สำหรับฉันด้วยในขณะที่ $ ('myInputElement') ทริกเกอร์ ('อินพุต') ไม่สม่ำเสมอ ดูเหมือนว่าจะทำงานแบบสุ่มบางครั้ง แต่ไม่ใช่คนอื่นและฉันไม่สามารถสร้างรูปแบบได้ วิธีนี้ใช้ได้ผลทุกครั้ง
BryanP

2
Mine ทำงานร่วมกับ # prefix:angular.element($('#myInputElement')).triggerHandler('input')
Ebru Yener

ทริกเกอร์นี้ Handler ทำงานสำหรับฉันด้วยฉันกำลังจัดการกับ textarea ที่ไม่ป้อนข้อมูล ขอบคุณ
Mounir

25

คำตอบที่ยอมรับซึ่งเรียกใช้inputเหตุการณ์กับ jQuery ไม่ทำงานสำหรับฉัน การสร้างกิจกรรมและการมอบหมายงานโดยใช้จาวาสคริปต์นั้นเป็นไปได้

$("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 เยี่ยม!
Igor

ขอบคุณ. มีประโยชน์อย่างยิ่งใน webview.evaluatejavascript
Berry Wing

22

ฉันไม่คิดว่าจำเป็นต้องใช้ jQuery ที่นี่

คุณสามารถใช้$ watchและng-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 คุณพูดถูกฉันไม่ควรผสม jquery กับ angular เมื่อมีวิธีการทำงานโดยใช้ 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; }); ส่วนนั้นช่วยฉันได้มาก ปัญหาของฉันคือการอัปเดตโมเดลเชิงมุมหลังจากการโทร jquery ajax ในฟังก์ชั่นความสำเร็จ มันช้าด้วย $ http เพราะมีผู้ฟังเหตุการณ์การเปลี่ยนแปลงที่ซ้ำกันสำหรับองค์ประกอบที่ทำอย่างอื่นดังนั้นฉันจึงรวมมันเป็น jQuery
Emmanuel Mahuni

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 = angular.element ($ ("# li_cuboid_id")). 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

ฉันรู้ว่ามันสายไปหน่อยนะที่จะตอบคำถามที่นี่ แต่บางทีฉันอาจจะประหยัดบ้างวันละครั้ง

ฉันจัดการกับปัญหาเดียวกันแล้ว โมเดลจะไม่แสดงเมื่อคุณอัปเดตค่าอินพุตจาก jQuery ฉันพยายามใช้เหตุการณ์ทริกเกอร์ แต่ไม่มีผลลัพธ์

นี่คือสิ่งที่ฉันทำซึ่งอาจช่วยวันของคุณ

ประกาศตัวแปรภายในแท็กสคริปต์ของคุณเป็น HTML

ชอบ:

<script>
 var inputValue="";

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

</script>

เมื่อคุณทำอย่างนั้นโดยใช้บริการด้านล่างของเชิงมุม

$ หน้าต่าง

ตอนนี้ด้านล่างฟังก์ชัน getData ที่เรียกจากขอบเขตตัวควบคุมเดียวกันจะให้ค่าที่คุณต้องการ

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

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

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

3

ฉันได้เขียนปลั๊กอินเล็ก ๆ นี้สำหรับ 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);

ตัวอย่าง:


ขออภัยที่จะขุดมันขึ้นมา แต่ความคิดใด ๆ ที่จะ / สามารถทำงานกับช่องทำเครื่องหมายหรือเลือกได้ตั้งแต่การใช้งาน .prop แทนที่จะเป็น. val? มันทำงานได้อย่างสมบูรณ์แบบสำหรับการป้อนข้อมูล. การเปลี่ยนแปลงอย่างน้อยที่สุดขอบคุณมาก!
ออสติน

@ Austin ฉันกลัวฉันไม่รู้ นี่เป็นคำถามอายุ 5 ปีเกี่ยวกับเทคโนโลยีสองอย่างที่ถือว่าล้าสมัยอย่างกว้างขวางเช่นนี้ฉันไม่ได้เก็บความรู้ไว้ในหัวของฉัน ขอให้โชคดีในการแก้ปัญหาที่คุณต้องการ
dav_i


2

เพิ่ม .change()หลังจากตั้งค่า

ตัวอย่าง:('id').val.('value').change();

อย่าลืมเพิ่มonchangeหรือng-changeแท็กใน html


0

ฉันทำสิ่งนี้เพื่อให้สามารถอัปเดตค่าของ ngModel จากภายนอกด้วย 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");
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.