AngularJS: অ্যাঙ্গুলারজেএস কোনও টেমপ্লেট রেন্ডার করার পরে কীভাবে অতিরিক্ত কোড চালাবেন?


182

আমার ডিওমে একটি কৌনিক টেম্পলেট রয়েছে। আমার নিয়ামক যখন কোনও পরিষেবা থেকে নতুন ডেটা পান, এটি $ স্কোপটিতে মডেলটি আপডেট করে এবং টেমপ্লেটটিকে পুনরায় রেন্ডার করে। এখন পর্যন্ত সব ভাল।

সমস্যাটি হ'ল টেমপ্লেটটি পুনরায় রেন্ডার হওয়ার পরে এবং ডোমে থাকার পরেও আমাকে কিছু অতিরিক্ত কাজ করতে হবে (এক্ষেত্রে একটি জিকুয়েরি প্লাগইন)।

দেখে মনে হচ্ছে এখানে শোনার মতো কোনও ইভেন্ট হওয়া উচিত, যেমন আফটাররেন্ডার, তবে আমি এরকম কোনও কিছুই পাই না। হয়তো কোনও নির্দেশিকা যাওয়ার একটি উপায় হতে পারে তবে এটি খুব তাড়াতাড়িই আগুনে ছড়িয়ে পড়েছে বলে মনে হয়েছিল।

এখানে আমার সমস্যাটির রূপরেখা একটি জেএসফিডাল: ফিডল-অ্যাঙ্গুলারআইসু

== আপডেট ==

সহায়ক মন্তব্যের উপর ভিত্তি করে, আমি সেই অনুযায়ী DOM হেরফের পরিচালনা করার জন্য একটি নির্দেশিকায় সরে গিয়েছি এবং একটি মডেল বাস্তবায়িত করেছি - নির্দেশের ভিতরে দেখুন। তবে, আমি এখনও একই বেস ইস্যু করছি; টেমপ্লেটটি সংকলন করে ডিওমে প্রবেশের আগে $ ঘড়ির ইভেন্টের অভ্যন্তরের কোডটি অগ্নিসংযোগ করে, সুতরাং, jquery প্লাগইন সর্বদা একটি খালি সারণির মূল্যায়ন করে।

মজার বিষয় হল, আমি যদি অ্যাসিঙ্ক কলটি সরিয়ে ফেলি তবে পুরো জিনিসটি ভাল কাজ করে, তাই এটি সঠিক দিকের একটি পদক্ষেপ।

এই পরিবর্তনগুলি প্রতিবিম্বিত করতে এখানে আমার আপডেট করা ফিডলটি রয়েছে: http://jsfiddle.net/uNREn/12/


এটি আমার একটি প্রশ্নের অনুরূপ বলে মনে হচ্ছে। stackoverflow.com/questions/11444494/… । সম্ভবত সেখানে কিছু সাহায্য করতে পারে।
dnc253

উত্তর:


39

এই পোস্টটি পুরানো, তবে আমি আপনার কোডটি এতে পরিবর্তন করি:

scope.$watch("assignments", function (value) {//I change here
  var val = value || null;            
  if (val)
    element.dataTable({"bDestroy": true});
  });
}

দেখতে jsfiddle

আমি এটি আপনাকে সাহায্য করে আশা করি


ধন্যবাদ, এটি খুব সহায়ক। এটি আমার পক্ষে সেরা সমাধান কারণ এটিতে নিয়ামকের কাছ থেকে ডোম ম্যানিপুলেশন প্রয়োজন হয় না, এবং তাত্পর্যপূর্ণভাবে অ্যাসিঙ্ক্রোনাস সার্ভিস প্রতিক্রিয়া থেকে ডেটা আপডেট হওয়ার পরেও কাজ করবে (এবং আমার কন্ট্রোলারে আমাকে $ ইভালএেন্সিক ব্যবহার করতে হবে না)।
gorebash

9
এটি কি অবহেলা করা হয়েছে? যখন আমি এটি চেষ্টা করি এটি ডম রেন্ডার হওয়ার ঠিক আগে কল করে । এটি কোনও ছায়া ডোম বা কোনও কিছুর উপর নির্ভরশীল?
শাইনে

আমি কৌণিকের তুলনায় তুলনামূলকভাবে নতুন এবং আমি কীভাবে আমার নির্দিষ্ট ক্ষেত্রে এই উত্তরটি প্রয়োগ করতে পারি তা দেখতে পাচ্ছি না। আমি বিভিন্ন উত্তর এবং অনুমান দেখছি, কিন্তু এটি কাজ করছে না। 'ওয়াচ' ফাংশনটি কী দেখানো উচিত তা আমি নিশ্চিত নই। আমাদের কৌণিক অ্যাপ্লিকেশনটির বিভিন্ন বিভিন্ন নির্দেশনা রয়েছে, যা পৃষ্ঠায় পরিবর্তিত হয়ে পৃথক হতে পারে, তবে কীভাবে 'ওয়াচ' করব তা আমি কীভাবে জানতে পারি? কোনও পৃষ্ঠা রেন্ডারিং শেষ হয়ে গেলে অবশ্যই কিছু কোড বন্ধ করে দেওয়ার সহজ উপায় আছে?
মোজফেটচার

63

প্রথমত, রেন্ডারিংয়ের সাথে জগাখিচির সঠিক জায়গাটি নির্দেশিকা। আমার পরামর্শটি হ'ল জুমকিউই প্লাগইনগুলির মতো ডাইমকে এই জাতীয় নির্দেশ দিয়ে মোড়ক করতে হবে।

আমার একই সমস্যা ছিল এবং এই স্নিপেট নিয়ে এসেছি। এটি ব্যবহার করে $watchএবং $evalAsyncআপনার কোডগুলি নির্দেশের ng-repeatসমাধান হওয়ার পরে এবং টেমপ্লেটগুলি পছন্দ করার পরে চলে তা নিশ্চিত করে to{{ value }} রেন্ডার ।

app.directive('name', function() {
    return {
        link: function($scope, element, attrs) {
            // Trigger when number of children changes,
            // including by directives like ng-repeat
            var watch = $scope.$watch(function() {
                return element.children().length;
            }, function() {
                // Wait for templates to render
                $scope.$evalAsync(function() {
                    // Finally, directives are evaluated
                    // and templates are renderer here
                    var children = element.children();
                    console.log(children);
                });
            });
        },
    };
});

আশা করি এটি আপনাকে কিছু লড়াই প্রতিরোধে সহায়তা করতে পারে।


এটি সুস্পষ্টভাবে উল্লেখ করে চলেছে, তবে এটি যদি আপনার পক্ষে কাজ করে না, আপনার লিঙ্ক ফাংশন / নিয়ন্ত্রণকারীগুলিতে অ্যাসিক্রোনাস অপারেশনগুলি পরীক্ষা করুন। আমি মনে করি না $ evalAncnc এগুলিকে বিবেচনায় নিতে পারে।
LOAS

আপনি একটি এর linkসাথে একটি ফাংশন একত্রিত করতে পারেন তা লক্ষণীয় templateUrl
ওয়াটওয়ার

35

মিসকোর পরামর্শ অনুসরণ করে, আপনি যদি অ্যাসিঙ্ক অপারেশন চান, তবে $ টাইমআউট () এর পরিবর্তে (যা কাজ করে না)

$timeout(function () { $scope.assignmentsLoaded(data); }, 1000);

$ evalAsync () (যা কাজ করে) ব্যবহার করুন

$scope.$evalAsync(function() { $scope.assignmentsLoaded(data); } );

বেহালার । আমি একটি "ডেটা সারি সরিয়ে ফেলুন" লিঙ্কটিও যুক্ত করেছি যা ডেটা / মডেলটির পরিবর্তনের অনুকরণ করে $ স্কোপ.সাইগমেন্টগুলি সংশোধন করবে - যা ডেটা পরিবর্তন কাজ করে তা দেখানোর জন্য।

দ্য রানটাইম ধারণামূলক সংক্ষিপ্ত বিবরণ পৃষ্ঠার অধ্যায় ব্যাখ্যা করেছেন যে evalAsync ব্যবহার করা উচিত যখন আপনি বর্তমান সময় স্ট্যাক ফ্রেম বাহিরে ঘটতে কিছু প্রয়োজন, কিন্তু করার আগে ব্রাউজারের রেন্ডার করে। (এখানে অনুমান করা হচ্ছে ... "বর্তমান স্ট্যাক ফ্রেম" এ সম্ভবত কৌণিক ডিওএম আপডেটগুলি অন্তর্ভুক্ত রয়েছে)) ব্রাউজারটি রেন্ডারগুলির পরে আপনার যদি কিছু হওয়ার দরকার হয় তবে $ টাইমআউট ব্যবহার করুন।

যাইহোক, আপনি ইতিমধ্যে খুঁজে পেয়েছেন হিসাবে, আমি মনে করি না যে এখানে async অপারেশন করার কোনও প্রয়োজন আছে।


4
$scope.$evalAsync($scope.assignmentsLoaded(data));কোনও ধারণা আইএমও করে না। এর পক্ষে যুক্তিটি $evalAsync()একটি ফাংশন হওয়া উচিত। আপনার উদাহরণে আপনি যখন ফাংশনটি পরবর্তী মৃত্যুর জন্য নিবন্ধিত করা উচিত তখন কল করে ফেলছেন।
hgoebl

@ hgoebl, $ evalAsync এর যুক্তি কোনও ফাংশন বা এক্সপ্রেশন হতে পারে। এই ক্ষেত্রে আমি একটি এক্সপ্রেশন ব্যবহার করেছি। তবে আপনি ঠিক বলেছেন, তাত্ক্ষণিকভাবে এক্সপ্রেশনটি কার্যকর হয়ে যায়। উত্তরটি পরে সম্পাদনের জন্য একটি ফাংশনে এটি মোড়ানোর জন্য পরিবর্তন করেছি। এটি ধরার জন্য ধন্যবাদ
মার্ক রাজকক

26

আমি খুঁজে পেয়েছি সবচেয়ে সহজ (সস্তা এবং প্রফুল্ল) সমাধানটি এনজি-শো = "কিছু ফাংশনট্যাটএলওয়েজ রিটার্নস জিরো অরনিথিং ()" দিয়ে একটি রেন্ডার করা শেষ উপাদানটির শেষে একটি ফাঁকা স্প্যান যুক্ত করুন। স্প্যান উপাদানটি প্রদর্শিত হবে কিনা তা পরীক্ষা করার জন্য এই ফাংশনটি চালানো হবে। এই ফাংশনে অন্য কোনও কোড কার্যকর করুন।

আমি বুঝতে পারি যে এটি করার জন্য এটি সবচেয়ে মার্জিত উপায় নয়, তবে এটি আমার পক্ষে কাজ করে ...

আমার একইরকম পরিস্থিতি ছিল, যদিও অ্যানিমেশন শুরু হওয়ার সাথে সাথে লোডিং ইন্ডিকেটরটি সরিয়ে ফেলতে আমার যেখানে প্রয়োজন হয়েছিল সেখানে সামান্য বিপরীত হয়েছে, মোবাইল ডিভাইসগুলিতে কৌণিক প্রদর্শিত হওয়া অ্যানিমেশনটির চেয়ে অনেক দ্রুত শুরু করছিল, এবং একটি এনজি-ক্লোব ব্যবহার করা অপ্রতুল ছিল কারণ লোডিং ইন্ডিকেটরটি ছিল কোনও বাস্তব তথ্য প্রদর্শিত হওয়ার আগে ভালভাবে সরানো হয়েছে। এই ক্ষেত্রে আমি আমার প্রথম 0 রেন্ডার উপাদানটিতে ফিরতি 0 ফাংশনটি যুক্ত করেছি এবং সেই ফাংশনে লোডিং ইন্ডিকেটরটি লুকিয়ে থাকা ভ্যারিকে উল্টিয়ে ফেলেছি। (অবশ্যই আমি এই ফাংশন দ্বারা চালিত লোডিং সূচকটিতে একটি এনজি-হাইড যুক্ত করেছি।


3
এটি নিশ্চিতভাবে একটি হ্যাক তবে এটি আমার যা প্রয়োজন তা ঠিক। আমার কোডটি রেন্ডার করার পরে ঠিক (বা একেবারে খুব কাছাকাছি) চালাতে বাধ্য করে। একটি আদর্শ বিশ্বে আমি এটি করব না তবে আমরা এখানে ...
অ্যান্ড্রু

আমাকে বিল্ট ইন $anchorScrollসার্ভিসটি ডম রেন্ডার করার পরে কল করার জন্য প্রয়োজন ছিল এবং এই কৌশলটি আর কিছুই করছিল বলে মনে হয়নি। হ্যাকিশ কিন্তু কাজ করে।
প্যাট মিগলিয়াচিয়ো

এনজি-থিম একটি ভাল বিকল্প
ফ্লাইং গ্যাম্বিট

1
ng-init সর্বদা কাজ না করে। উদাহরণস্বরূপ, আমার কাছে এনজি-রিপিট রয়েছে যা ডোমে অনেকগুলি চিত্র যুক্ত করে। এনজি-রিপিটে প্রতিটি চিত্র যুক্ত হওয়ার পরে যদি আমি কোনও ফাংশন বলতে চাই তবে আমাকে এনজি-শো ব্যবহার করতে হবে।
মাইকেল ব্রেমারক্যাম্প

7

2
মন্তব্যের জন্য ধন্যবাদ. সম্ভবত আমি কৌণিক খুব নতুন কিন্তু আমি আমার কোডটিতে এটি কীভাবে কাজ করব তা দেখছি না। আপনি আমাকে নির্দেশ করতে পারে এমন কোন উদাহরণ আছে?
গোরাব্যাশ

4

অবশেষে আমি সমাধানটি পেয়েছি, আমি আমার সংগ্রহ আপডেট করার জন্য একটি রেস্ট পরিষেবা ব্যবহার করছিলাম। ডেটেবল জেকারি রূপান্তর করতে নিম্নলিখিত কোডটি:

$scope.$watchCollection( 'conferences', function( old, nuew ) {
        if( old === nuew ) return;
        $( '#dataTablex' ).dataTable().fnDestroy();
        $timeout(function () {
                $( '#dataTablex' ).dataTable();
        });
    });

3

আমি বেশ প্রায়শই এটি করতে হয়েছিল। মডেলের স্টাফগুলি পুরোপুরি ডিওএম-এ লোড হওয়ার পরে আমার একটি নির্দেশনা রয়েছে এবং কিছু জ্যাকেই স্টাফ করা দরকার। সুতরাং আমি আমার যুক্তিটিকে লিঙ্কটিতে রেখেছি: নির্দেশকের কার্যকারিতা এবং কোডটিকে একটি সেটটাইমআউট (ফাংশন () {.....}, 1) এ মোড়ানো; ডোম লোড হওয়ার পরে সেটটাইমআউটটি চালিত হবে এবং কোড কার্যকর করার আগে ডিওএম লোড হওয়ার পরে 1 মিলি সেকেন্ড সময় স্বল্পতম হয়। এটি আমার পক্ষে কাজ করে বলে মনে হচ্ছে তবে একবারে কোনও টেম্পলেট লোড করার পরে কৌণিক কোনও ইভেন্ট উত্থাপন করতে চাইবে যাতে সেই টেমপ্লেটের দ্বারা ব্যবহৃত নির্দেশাবলী jquery স্টাফ করতে পারে এবং DOM উপাদানগুলিতে অ্যাক্সেস করতে পারে। আশাকরি এটা সাহায্য করবে.



2

না কোনও $ সুযোগ। $ EvalAsync () বা $ সময়সীমা (fn, 0) আমার জন্য নির্ভরযোগ্যভাবে কাজ করেছে।

আমাকে দু'জনকে একত্রিত করতে হয়েছিল। আমি একটি নির্দেশিকা তৈরি করেছি এবং ভাল পরিমাপের জন্য ডিফল্ট মানের চেয়েও বেশি অগ্রাধিকার রেখেছি। এটির জন্য এখানে একটি নির্দেশিকা রয়েছে (নোট আমি নির্ভরতা ইনজেক্ট করার জন্য এনজিআইএনেক্ট ব্যবহার করি):

app.directive('postrenderAction', postrenderAction);

/* @ngInject */
function postrenderAction($timeout) {
    // ### Directive Interface
    // Defines base properties for the directive.
    var directive = {
        restrict: 'A',
        priority: 101,
        link: link
    };
    return directive;

    // ### Link Function
    // Provides functionality for the directive during the DOM building/data binding stage.
    function link(scope, element, attrs) {
        $timeout(function() {
            scope.$evalAsync(attrs.postrenderAction);
        }, 0);
    }
}

নির্দেশকে কল করতে আপনি এইটি করবেন:

<div postrender-action="functionToRun()"></div>

এনজি-রিপিটটি চলার পরে যদি আপনি এটি কল করতে চান, আমি আমার এনজি-রিপিট এবং এনজি-ইফ = = "$ লাস্ট" এ একটি ফাঁকা স্প্যান যুক্ত করেছি:

<li ng-repeat="item in list">
    <!-- Do stuff with list -->
    ...

    <!-- Fire function after the last element is rendered -->
    <span ng-if="$last" postrender-action="$ctrl.postRender()"></span>
</li>

1

কিছু পরিস্থিতিতে যেখানে আপনি একটি পরিষেবা আপডেট করেন এবং একটি নতুন দর্শন (পৃষ্ঠা) এ পুনর্নির্দেশ করেন এবং তারপরে আপনার পরিষেবাদি আপডেট হওয়ার আগে আপনার নির্দেশিকাটি লোড হয়ে যায় আপনি যদি আপনার $ ওয়াচ বা $ সময়সীমা ব্যর্থ হন তবে সম্প্রচারিত করতে পারেন $ রুটস্কোপ $

দৃশ্য

<service-history log="log" data-ng-repeat="log in requiedData"></service-history>

নিয়ামক

app.controller("MyController",['$scope','$rootScope', function($scope, $rootScope) {

   $scope.$on('$viewContentLoaded', function () {
       SomeSerive.getHistory().then(function(data) {
           $scope.requiedData = data;
           $rootScope.$broadcast("history-updation");
       });
  });

}]);

নির্দেশিকা

app.directive("serviceHistory", function() {
    return {
        restrict: 'E',
        replace: true,
        scope: {
           log: '='
        },
        link: function($scope, element, attrs) {
            function updateHistory() {
               if(log) {
                   //do something
               }
            }
            $rootScope.$on("history-updation", updateHistory);
        }
   };
});

1

আমি বেশ সহজ সমাধান নিয়ে এসেছি। এটি করার সঠিক উপায় কিনা তা আমি নিশ্চিত নই তবে এটি ব্যবহারিক অর্থে কার্যকর হয়। আসুন আমরা কীভাবে রেন্ডার করতে চাই তা সরাসরি দেখি। উদাহরণস্বরূপ কোনও নির্দেশে যার মধ্যে কিছু ng-repeatগুলি রয়েছে , আমি অনুচ্ছেদে বা পুরো এইচটিএমএলের পাঠ্যের দৈর্ঘ্য (আপনার অন্যান্য জিনিস থাকতে পারে!) দেখব। নির্দেশনাটি এরকম হবে:

.directive('myDirective', [function () {
    'use strict';
    return {

        link: function (scope, element, attrs) {
            scope.$watch(function(){
               var whole_p_length = 0;
               var ps = element.find('p');
                for (var i=0;i<ps.length;i++){
                    if (ps[i].innerHTML == undefined){
                        continue
                    }
                    whole_p_length+= ps[i].innerHTML.length;
                }
                //it could be this too:  whole_p_length = element[0].innerHTML.length; but my test showed that the above method is a bit faster
                console.log(whole_p_length);
                return whole_p_length;
            }, function (value) {   
                //Code you want to be run after rendering changes
            });
        }
}]);

নোট করুন যে কোডটি আসলে রেন্ডারিং পরিবর্তনের পরিবর্তে সম্পূর্ণ রেন্ডারিংয়ের পরে চলে । তবে আমি অনুমান করি বেশিরভাগ ক্ষেত্রে আপনি যখনই রেন্ডারিং পরিবর্তন ঘটে তখন আপনি পরিস্থিতি পরিচালনা করতে পারেন। এছাড়াও আপনি pযদি রেন্ডারিংয়ের কাজ শেষ হওয়ার পরে কেবল একবার আপনার কোডটি চালাতে চান তবে এই মডেলের সাথে এই দৈর্ঘ্যের (বা অন্য কোনও পরিমাপ) তুলনা করার কথা ভাবতে পারেন । আমি এই সম্পর্কে কোন চিন্তা / মন্তব্য প্রশংসা করি।


0

আপনি 'jQuery পাসস্ট্র্রু' মডিউলটি ব্যবহার করতে পারেন কৌণিক-ইউআই । আমি সফলভাবে একটি jQuery টাচ ক্যারোসেল প্লাগইনটি কয়েকটি চিত্রের সাথে বেঁধেছি যা আমি একটি ওয়েব পরিষেবা থেকে অ্যাসিঙ্ক পুনরুদ্ধার করে এবং এনজি-রিপিট দিয়ে রেন্ডার করি।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.