javascript - شغّل jQuery code بعد أن تكمل AngularJS عرض HTML




(3)

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

ولكن في تجربتي ، كما يقول البروتوكول الاختياري ، فإنه عادة ما يتم تشغيل بعض الإضافات أو الأساليب في jQuery على DOM المُجمَّع أخيراً ، والتي في هذه الحالة وجدت أن الحل الأكثر بساطة هو إنشاء أمر توجيهي مع setTimeout ، حيث أن الدالة setTimeout تحصل على دفعت إلى نهاية قائمة الانتظار للمتصفح ، على حق دائما بعد كل شيء يتم في الزاوي ، عادة ng-repeat الذي يستمر بعد وظيفة الوالدين postLinking

angular.module('myApp', [])
.directive('pluginNameOrWhatever', function() {
  return function(scope, element, attrs) {        
    setTimeout(function doWork(){
      //jquery code and plugins
    }, 0);        
  };
});

لمن يتساءل لماذا لا يستخدم المهلة $ ، فإنه يتسبب في دورة هضم أخرى غير ضرورية تماما.

تصحيح:

ثنإكس إلى drzaus للرابط إلى كيفية استخدام المهلة $ دون التسبب في هضم http://www.codelord.net/2015/10/14/angular-nitpicking-differences-between-timeout-and-settimeout/

في وحدة التحكم ، أحصل على بعض بيانات JSON باستخدام http أو خدمات موارد $ دولار. ثم اكتب هذه البيانات في نطاق $ وتقوم AngularJS بتحديث بنية HTML الخاصة بالصفحة. مشكلتي هي أنني بحاجة لمعرفة ما هو الحجم الجديد (العرض والارتفاع) للقائمة (أعني عنصر HTML DOM) المملوء بتوجيه ng-repeat Angular. وبالتالي ، لا بد لي من تشغيل شفرة جافا سكريبت مباشرة بعد الانتهاء من الزوايا تحديث هيكل DOM. ما هي الطريقة الصحيحة للقيام بذلك؟ لقد فتشت الإنترنت على مدار الأربع ساعات الماضية ، لكن لم أجد أي حل لمشكلتي.

هذه هي الطريقة التي أتلقى بها بيانات JSON:

var tradesInfo = TradesInfo.get({}, function(data){
    console.log(data);
    $scope.source.profile = data.profile;
            $scope.trades = $scope.source.profile.trades;
        $scope.activetrade = $scope.trades[0];
        $scope.ready = true;


    init();  //I need to call this function after update is complete

});

وهذا ما يحدث في وظيفة init() :

function init(){
    alert($('#wrapper').width());
    alert($('#wrapper').height());
}

أعلم أنه يجب أن يكون هناك شيء سهل لحل هذه المشكلة ولكن لا يمكنني العثور عليه الآن. شكرا مقدما.


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

var tradesInfo = TradesInfo.get({}, function(data) {
  console.log(data);
  $scope.profile = data.profile;
  // ...
});


directive('heightStuff', ['$timeout',
  function($timeout) {
    return {
      scope: {
        myData: '='
      },
      link: function($scope, element, attrs) {
        $scope.$watch('myData', function() {
          $timeout(function() { // You might need this timeout to be sure its run after DOM render.
            element.width()
            element.height()
          }, 0, false);
        })
      }
    };
  }
]);
<div height-stuff my-data="profile"></div>

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


في الواقع في هذه الحالة فإن الطريقة الزاوي ليست الطريقة السهلة ولكن الطريقة الصحيحة الوحيدة :)

عليك كتابة توجيه وإرفاق العنصر الذي تريد معرفة ارتفاعه. ومن وحدة التحكم التي تبث حدثًا $ ، سيصادف التوليف الحدث وستتمكّن من إجراء معالجة DOM. أبدا في وحدة تحكم.

var tradesInfo = TradesInfo.get({}, function(data){
    console.log(data);
    $scope.source.profile = data.profile;
    ...

    $scope.$broadcast('dataloaded');
});


directive('heightStuff', ['$timeout', function ($timeout) {
    return {
        link: function ($scope, element, attrs) {
            $scope.$on('dataloaded', function () {
                $timeout(function () { // You might need this timeout to be sure its run after DOM render.
                    element.width()
                    element.height()
                }, 0, false);
            })
        }
    };
}]);




angularjs