Angular.js: Onchange dipicu sebelum pembaruan model untuk cakupan isolate

Dibuat pada 21 Okt 2013  ·  11Komentar  ·  Sumber: angular/angular.js

Peristiwa onchange untuk elemen yang memiliki cakupan isolate dipicu sebelum pembaruan model.

Contoh:

<!doctype html>
<html ng-app="App">
    <head>

        <link rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" />

        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.js"></script>
        <script src="http://code.angularjs.org/1.0.6/angular.js"></script>
        <script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>

        <script type="text/javascript">
            "use strict"

            var App = angular.module('App', []);
            App.controller('Ctrl', function ($scope,$timeout) {

                $scope.change1 = function () {
                    console.warn("inside change", $scope.y);
                }

                $scope.change2 = function () {
                    console.warn("inside change", $scope.x);    
                }

            });

            App.directive("wminput", function () {
                return {
                    restrict: "E",
                    replace: true,
                    scope: {
                        "onChange":"&",
                        "value": "="
                    },
                    template: '<input type="text" data-ng-model="value" data-ng-change="onChange();">'
                }
            });

        </script>

    </head>
    <body>
        <div data-ng-controller="Ctrl">
            "Onchange will be triggered after the model update"
            <input data-ng-change="change1()" data-ng-model="y">
            <br><br>
            "Onchange will be triggered before the model update"
            <wminput on-change="change2()" value="x"></wminput>
        </div>

    </body>
</html>
$compile forms low works as expected confusing bug

Komentar yang paling membantu

Narretz, saya sangat tidak setuju. Ada kontrak yang dibuat dengan pengembang yang menggunakan kode yang diutamakan pengikatan dua arah. Saat perubahan dilakukan di mana saja di sepanjang rantai pengikatan, seluruh rantai harus diperbarui sebelum melanjutkan. Jadi, bahkan jika direktif lain mewarisi dari direktif ini, dan sesuatu yang lebih jauh terikat ke pengikatan pengikatan ... jika model itu diperbarui, model lingkup pengontrol asli di bagian bawah tumpukan harus diperbarui dalam siklus intisari yang sama sebelumnya melanjutkan ke fungsi lainnya. Itu yang diharapkan dari konsumen.

Semua 11 komentar

Kasus sudut yang menarik ... http://plnkr.co/edit/lsrga8qMcbgNWATrVht3?p=preview

Ini terjadi hanya jika fungsi onChange didelegasikan ke cakupan induk lebar pengikatan '&'.

Kami telah mengerjakan alat RAD berdasarkan angularjs.
Ini adalah bug utama karena setiap widget dalam aplikasi memiliki isolateScope.
Kami telah menyelesaikan masalah dengan membuat metode proxy untuk onChange.

Lihat di: https://studio.wavemaker.com/

Salam, Vinay

Bisakah Anda memposting contoh proxy ini dan cara penggunaannya? Mungkin membantu dalam debugging ini.

Apakah akan diperbaiki dalam waktu dekat? Ini sangat membingungkan.

Setelah pertimbangan lebih lanjut, saya harus mengatakan bahwa ini adalah perilaku yang diharapkan .. Dalam contoh plnkr, nilai ngModel adalah dua string terikat antara pengontrol dan lingkup direktif. Sekarang, saat Anda mengubah nilai di direktif, ngModel akan memperbarui cakupan _isolate_ terlebih dahulu, dan mengaktifkan ngChange di intisari yang sama. Karena pengikatan dua arah belum mengambil perubahan pada lingkup direktif, ngChange dalam lingkup induk mendapatkan nilai "lama" x . Sekarang pengamat pengikatan dua arah memerlukan setidaknya dua siklus intisari untuk menstabilkan nilai, sehingga cakupan pengontrol hanya diperbarui setelah ngChange dipanggil.
Saya setuju bahwa ini membingungkan, tetapi begitulah cara kerjanya. Anda dapat mengatasinya dengan mengikat objek ke direktif yang menyimpan nilai yang Anda ikat ke ngModel. Dengan begitu, nilai ditetapkan dengan referensi di isolate dan cakupan pengontrol secara bersamaan dan tersedia saat ngChange dijalankan: http://plnkr.co/edit/fs7S6yX1a5aeo1Ese522?p=preview

Narretz, saya sangat tidak setuju. Ada kontrak yang dibuat dengan pengembang yang menggunakan kode yang diutamakan pengikatan dua arah. Saat perubahan dilakukan di mana saja di sepanjang rantai pengikatan, seluruh rantai harus diperbarui sebelum melanjutkan. Jadi, bahkan jika direktif lain mewarisi dari direktif ini, dan sesuatu yang lebih jauh terikat ke pengikatan pengikatan ... jika model itu diperbarui, model lingkup pengontrol asli di bagian bawah tumpukan harus diperbarui dalam siklus intisari yang sama sebelumnya melanjutkan ke fungsi lainnya. Itu yang diharapkan dari konsumen.

Sedikit terkait, dan juga membingungkan. Saat menggunakan ngChange untuk memicu validasi di bidang lain yang berbagi ngModel , perubahan dipicu sebelum $modelValue diperbarui. Membuat validasi berbelit-belit.

Menggunakan $timeout sebagai solusi. Masih bingung kenapa itu dibutuhkan.

Contoh:
http://codepen.io/jakobadam/pen/qmBdrJ?editors=1010

salam, Jakob

Apakah ada rencana untuk meninjau kembali masalah ini? Mungkin buka kembali?

Saya mengalami masalah ini dan membaca komentar, sementara cara kerjanya saat ini karena ruang lingkup isolate masuk akal; hasil yang datang dari mengharapkan model yang diperbarui ketika panggilan on-change diaktifkan dan mendapatkan model satu iterasi sebelumnya jelas bukan perilaku yang Anda harapkan sebagai pengembang.

Saya mematuhi pertanyaan, apakah ini akan ditinjau kembali?

Saya rasa tidak. Perilaku saat ini diharapkan dan meskipun tidak diinginkan dalam beberapa kasus, setidaknya ada banyak kasus di mana itu. Mengubahnya sekarang akan (a) menjadi perubahan yang mengganggu dan (b) membuat banyak kasus penggunaan tidak didukung (mis. Di mana Anda ingin ngChange untuk mengubah nilai _before_ memperbarui induknya). Ini adalah salah satu kasus di mana Anda tidak dapat membuat semua orang senang, jadi kami harus tetap menggunakan versi yang:

  • Masuk akal.
  • Tidak merusak pengguna yang sudah ada.
  • Mendukung kasus penggunaan yang lebih spesifik / lanjutan, meskipun dengan biaya kode tambahan (lihat di bawah).

Implementasi ngChange ini terikat erat dengan konsep ngModel . Pengikatan arahan adalah konsep yang sepenuhnya independen. Keduanya dapat bekerja sama dengan baik, tetapi tidak mempengaruhi implementasi / kerja internal satu sama lain.

#

Seperti yang telah disebutkan, jika callback spesifik Anda memerlukan akses ke nilai yang diperbarui, ada beberapa opsi:

  1. Teruskan nilai yang diperbarui sebagai argumen ke callback.

  2. Jika Anda membutuhkannya untuk dijalankan secara asinkron (yaitu setelah intisari selesai dan semua binding telah disebarkan), Anda selalu dapat menggunakan $timeout di dalam callback.

  3. Jika Anda menginginkan versi "asinkron" dari ngChange , penerapannya sebagai petunjuk kustom juga mudah. (Anda juga dapat menimpa direktif bawaan, tetapi saya pasti tidak akan merekomendasikannya.) Misalnya:

.directive('myAsyncChange', function($timeout) {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function(scope, element, attr, ctrl) {
      ctrl.$viewChangeListeners.push(function() {
        $timeout(function() {
          scope.$eval(attr.myAsyncChange);
        });
      });
    }
  };
});
<input ng-model="foo" my-async-change="onChange()" />
Apakah halaman ini membantu?
0 / 5 - 0 peringkat