Angular.js: يتم تشغيل Onchange قبل تحديث النموذج لنطاق العزل

تم إنشاؤها على ٢١ أكتوبر ٢٠١٣  ·  11تعليقات  ·  مصدر: angular/angular.js

يتم تشغيل حدث Onchange للعناصر التي لها نطاق معزول قبل تحديث النموذج.

مثال:

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

التعليق الأكثر فائدة

ناريتز ، أنا أعارض بشدة. هناك عقد مبرم مع المطور الذي يستهلك الكود الذي يكون للربط ثنائي الاتجاه الأسبقية. عندما يتم إجراء تغيير في أي مكان على طول سلسلة الربط ، يجب تحديث السلسلة بأكملها قبل المتابعة. لذلك ، حتى إذا كان هناك توجيه آخر يرث من هذا التوجيه ، وهناك شيء آخر يرتبط بربط ارتباط ... إذا تم تحديث هذا النموذج ، فيجب تحديث نموذج نطاق وحدة التحكم الأصلي في الجزء السفلي من المكدس في نفس دورة الملخص من قبل الاستمرار في وظائف أخرى. إنه ما يتوقعه المستهلك.

ال 11 كومينتر

حالة ركن مثيرة للاهتمام ... http://plnkr.co/edit/lsrga8qMcbgNWATrVht3؟p=preview

يحدث هذا فقط عندما يتم تفويض وظيفة onChange إلى عرض النطاق الأصلي للربط "&".

لقد عملنا على أداة RAD تعتمد على angularjs.
كان هذا خطأ رئيسيًا حيث أن كل عنصر واجهة مستخدم في التطبيق يحتوي على إيزولاتيسكوب.
لقد قمنا بحل المشكلة عن طريق إنشاء طريقة وكيل لـ onChange.

ألق نظرة على: https://studio.wavemaker.com/

تحياتي ، فيناي

هل يمكنك نشر مثال على هذا الوكيل وكيف يتم استخدامه؟ قد يساعد في تصحيح هذا.

هل سيتم إصلاحه في أي وقت قريبًا؟ إنه أمر محير للغاية.

بعد مزيد من الدراسة ، يجب أن أقول إن هذا سلوك متوقع .. في مثال plnkr ، تكون قيمة ngModel عبارة عن سلسلة منضمين بين وحدة التحكم والنطاق التوجيهي. الآن عندما تقوم بتغيير القيمة في التوجيه ، سيقوم ngModel بتحديث النطاق _isolate_ أولاً ، وإطلاق ngChange في نفس الملخص. نظرًا لأن الربط ثنائي الاتجاه لم يلتقط بعد تغييرًا في نطاق التوجيه ، فإن ngChange في النطاق الأصلي يحصل على القيمة "القديمة" البالغة x . الآن يحتاج مراقب الربط ثنائي الاتجاه إلى دورتين من الملخصات على الأقل لتحقيق الاستقرار في القيمة ، لذلك يتم تحديث نطاق وحدة التحكم فقط بعد استدعاء ngChange.
أوافق على أن هذا محير ، لكن هكذا يعمل. يمكنك حل هذا عن طريق ربط كائن بالتوجيه الذي يحمل القيمة التي تربطها بـ ngModel. بهذه الطريقة ، يتم تعيين القيمة عن طريق المرجع في كل من نطاق العزل ووحدة التحكم في نفس الوقت وتكون متاحة عند تنفيذ ngChange: http://plnkr.co/edit/fs7S6yX1a5aeo1Ese522؟p=preview

ناريتز ، أنا أعارض بشدة. هناك عقد مبرم مع المطور الذي يستهلك الكود الذي يكون للربط ثنائي الاتجاه الأسبقية. عندما يتم إجراء تغيير في أي مكان على طول سلسلة الربط ، يجب تحديث السلسلة بأكملها قبل المتابعة. لذلك ، حتى إذا كان هناك توجيه آخر يرث من هذا التوجيه ، وهناك شيء آخر يرتبط بربط ارتباط ... إذا تم تحديث هذا النموذج ، فيجب تحديث نموذج نطاق وحدة التحكم الأصلي في الجزء السفلي من المكدس في نفس دورة الملخص من قبل الاستمرار في وظائف أخرى. إنه ما يتوقعه المستهلك.

مرتبط قليلاً ، ومربك بالمثل. عند استخدام ngChange لبدء التحقق في حقل آخر يشارك ngModel ، يتم تشغيل التغيير قبل تحديث $modelValue . جعل التحقق من الصحة معقدًا.

استخدام $timeout كحل بديل. ما زلت مرتبكًا لماذا هذا مطلوب.

مثال:
http://codepen.io/jakobadam/pen/qmBdrJ؟editors=1010

تحياتي ، جاكوب

هل هناك أي خطط لإعادة النظر في هذه القضية؟ ربما إعادة فتح؟

واجهت هذه المشكلة وقراءة التعليقات ، في حين أن الطريقة التي تعمل بها حاليًا بسبب النطاق المعزول منطقية ؛ النتيجة التي تأتي من توقع نموذج محدث عند إطلاق المكالمة عند التغيير والحصول على تكرار النموذج الأول السابق بالتأكيد ليس السلوك الذي تتوقعه كمطور.

أنا ملتزم بالسؤال ، هل ستتم إعادة النظر في هذا؟

لا أعتقد ذلك. السلوك الحالي متوقع وعلى الرغم من أنه غير مرغوب فيه في بعض الحالات ، إلا أنه يوجد على الأقل العديد من الحالات التي يكون فيها. تغييره الآن (أ) سيكون تغييرًا فاصلاً و (ب) سيجعل العديد من حالات الاستخدام غير مدعومة (على سبيل المثال حيث تريد ngChange لتعديل القيمة _ قبل أن يقوم بتحديث الأصل). إنها إحدى تلك الحالات التي لا يمكنك أن تجعل الجميع سعداء ، لذلك علينا أن نلتزم بالإصدار الذي:

  • من المنطقي.
  • لا يكسر المستخدمين الحاليين.
  • يدعم حالات استخدام أكثر تحديدًا / تقدمًا ، حتى لو كان ذلك على حساب القليل من التعليمات البرمجية الإضافية (انظر أدناه).

التنفيذ الحالي لـ ngChange مرتبط بشدة بمفهوم ngModel . الارتباطات التوجيهية هي مفهوم مستقل تمامًا. يمكن أن يعمل الاثنان معًا بشكل جيد ، لكن لا ينبغي أن يؤثر على التنفيذ / الأعمال الداخلية لبعضهما البعض.

#

كما ذكرنا سابقًا ، إذا كان رد الاتصال الخاص بك يحتاج إلى الوصول إلى القيمة المحدثة ، فهناك بعض الخيارات:

  1. قم بتمرير القيمة المحدثة كوسيطة إلى رد الاتصال.

  2. إذا كنت تريد تشغيله بشكل غير متزامن (أي بعد انتهاء الملخص ونشر جميع الروابط) ، يمكنك دائمًا استخدام $timeout داخل رد الاتصال.

  3. إذا كنت تريد إصدارًا "غير متزامن" من ngChange ، فمن السهل أيضًا تنفيذه كتوجيه مخصص. (يمكنك أيضًا الكتابة فوق التوجيه المضمن ، لكنني بالتأكيد لا أوصي بذلك.) على سبيل المثال:

.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()" />
هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات