অ্যাঙ্গুলারজেএস-এ আমি কীভাবে গতিশীলভাবে কোনও নির্দেশিকা যুক্ত করতে পারি?


212

আমি যা করছি তার একটি খুব সিদ্ধ ডাউন সংস্করণ রয়েছে যা সমস্যাটি জুড়ে যায়।

আমি একটি সহজ আছে directive। আপনি যখনই কোনও উপাদানকে ক্লিক করেন, এটি অন্য একটি যুক্ত করে। তবে সঠিকভাবে রেন্ডার করার জন্য এটি প্রথমে সংকলন করা দরকার।

আমার গবেষণা আমাকে নেতৃত্ব দেয় $compile। তবে সমস্ত উদাহরণ একটি জটিল কাঠামো ব্যবহার করে যা এখানে প্রয়োগ করতে আমি জানি না really

ফিডলগুলি এখানে: http://jsfiddle.net/paulocoelho/fBjbP/1/

এবং জেএস এখানে:

var module = angular.module('testApp', [])
    .directive('test', function () {
    return {
        restrict: 'E',
        template: '<p>{{text}}</p>',
        scope: {
            text: '@text'
        },
        link:function(scope,element){
            $( element ).click(function(){
                // TODO: This does not do what it's supposed to :(
                $(this).parent().append("<test text='n'></test>");
            });
        }
    };
});

জোশ ডেভিড মিলার দ্বারা সমাধান: http://jsfiddle.net/paulocoelho/fBjbP/2/

উত্তর:


259

আপনার সেখানে প্রচুর অর্থহীন jQuery রয়েছে তবে $ সংকলন পরিষেবাটি এই ক্ষেত্রে আসলে খুব সহজ :

.directive( 'test', function ( $compile ) {
  return {
    restrict: 'E',
    scope: { text: '@' },
    template: '<p ng-click="add()">{{text}}</p>',
    controller: function ( $scope, $element ) {
      $scope.add = function () {
        var el = $compile( "<test text='n'></test>" )( $scope );
        $element.parent().append( el );
      };
    }
  };
});

আপনি লক্ষ করবেন যে আমি আপনার নির্দেশিকাটিকেও বেশ কয়েকটি সেরা অনুশীলনগুলি অনুসরণ করার জন্য রিফেক্টর করেছি। আপনি যদি সেগুলির কোনও সম্পর্কে আপনার কাছে প্রশ্ন থাকে তবে আমাকে জানান।


34
অসাধারণ. এটা কাজ করে। দেখুন, এই সাধারণ এবং মৌলিক উদাহরণগুলি সেগুলি যা অ্যাঙ্গুলার ডক্সে দেখানো উচিত। তারা জটিল উদাহরণ দিয়ে শুরু।
পিসিওহেলো

1
ধন্যবাদ, জোশ, এটি সত্যই কার্যকর ছিল। আমি প্লেনক্রিতে একটি সরঞ্জাম তৈরি করেছি যা আমরা বাচ্চাদের কোড শিখতে সহায়তা করার জন্য একটি নতুন কোডারডোজোতে ব্যবহার করছি এবং আমি কেবল এটি প্রসারিত করেছি যাতে এখন আমি ডেটপিকার, সতর্কতা, ট্যাব ইত্যাদির মতো কৌণিক বুটস্ট্র্যাপ নির্দেশিকা ব্যবহার করতে পারি App এবং এই মুহুর্তে এটি কেবল ক্রোমে কাজ করছে যদিও: এম্বেড.পিএলএনকিআর.কম
ডাব্লুআই

3
জোশ - এটি ব্যবহার না করে এটি সম্পাদন করার সহজ উপায় $compileকী? আপনার উত্তরের জন্য ধন্যবাদ!
ডাবলসওয়ারভ

3
@ Doubleswirve এই ক্ষেত্রে, কেবলমাত্র এনজিআরপিট ব্যবহার করা আরও সহজ হবে। :-) তবে আমি ধরে নিয়েছি আপনার অর্থ পৃষ্ঠাটিতে গতিময়ভাবে নতুন নির্দেশিকা যুক্ত করা, যার ক্ষেত্রে উত্তরটির উত্তর নেই - এর চেয়ে সহজ উপায় নেই কারণ $compileপরিষেবাটি যা তারের নির্দেশনাগুলিকে আপ করে এবং ইভেন্ট চক্রের মধ্যে সেগুলি সরিয়ে দেয়। $compileএইরকম পরিস্থিতিতে ইঙ্গিত করার কোনও উপায় নেই , তবে বেশিরভাগ ক্ষেত্রে এনজিরাপিট-এর মতো আরেকটি নির্দেশ একই কাজ সম্পাদন করতে পারে (সুতরাং এনজিপিপিট আমাদের জন্য সংকলন করছে)। আপনার কি নির্দিষ্ট ব্যবহারের কেস আছে?
জোশ ডেভিড মিলার

2
প্রিলিংক পর্যায়ে সংকলন হওয়া উচিত নয়? আমি মনে করি যে নিয়ামকটিতে কেবল নন-ডোম, ইউনিট-টেস্টেবল কোড থাকা উচিত তবে আমি লিঙ্ক / নিয়ামক ধারণাটিতে নতুন তাই আমি নিজেকে অনিশ্চিত করছি। এছাড়াও, একটি মৌলিক বিকল্প হ'ল এনজি-অন্তর্ভুক্ত + আংশিক + এনজি-কন্ট্রোলার যেহেতু এটি উত্তরাধিকার সূত্রে প্রাপ্ত দিকনির্দেশক হিসাবে কাজ করবে ।
মার্কাস রডেল

77

নিখুঁত রাইসবল এলইএর একটি নতুন উপাদান-নির্দেশ যুক্ত করার উদাহরণ ছাড়াও

newElement = $compile("<div my-directive='n'></div>")($scope)
$element.parent().append(newElement)

অস্তিত্বের উপাদানগুলিতে একটি নতুন অ্যাট্রিবিউট-ডাইরেক্টিভ যুক্ত করা এইভাবে ব্যবহার করা যেতে পারে:

আসুন যদি আপনার অন-মাছি যুক্ত করতে চান বলে my-directiveকরতে spanউপাদান।

template: '<div>Hello <span>World</span></div>'

link: ($scope, $element, $attrs) ->

  span = $element.find('span').clone()
  span.attr('my-directive', 'my-directive')
  span = $compile(span)($scope)
  $element.find('span').replaceWith span

আশা করি এইটি কাজ করবে.


3
সর্বাধিক কল স্ট্যাকের আকার ত্রুটি ছাড়িয়ে যাওয়ার জন্য মূল নির্দেশটি সরাতে ভুলবেন না।
এসআরচামিম

হাই, আপনি প্রোগ্রামযুক্তভাবে নির্দেশিকাগুলি একটি সহজ প্রক্রিয়া যুক্ত করার জন্য আমার নতুন প্রস্তাবিত এপিআই সম্পর্কে ধারণা প্রদান করবেন? github.com/angular/angular.js/issues/6950 ধন্যবাদ!
trusktr

আমি আশা করি ২০১৫ সালে আমাদের কল স্ট্যাকের আকারের সীমা থাকবে না। :(
সাইকো বিএম

3
Maximum call stack size exceededত্রুটি সবসময় অসীম পুনরাবৃত্তির কারণ ঘটবে। স্ট্যাকের আকার বাড়ানো সমাধান করতে পারে এমন কোনও উদাহরণ আমি কখনও দেখিনি।
গুঞ্চারস

অনুরূপ সমস্যাটির মুখোমুখি, আপনি কি আমাকে এখানে সহায়তা করতে পারবেন stackoverflow.com/questions/38821980/…
পান্ডু দাস

45

কৌণিকভাবে কৌণিকের উপর নির্দেশাবলী যুক্ত করার জন্য দুটি স্টাইল রয়েছে:

অন্য নির্দেশিকায় একটি কৌণিক নির্দেশাবলী যুক্ত করুন

  • একটি নতুন উপাদান (োকানো (নির্দেশিকা)
  • উপাদানটিতে একটি নতুন বৈশিষ্ট্য (নির্দেশিকা) সন্নিবেশ করা হচ্ছে

একটি নতুন উপাদান (োকানো (নির্দেশিকা)

ইহা সহজ. এবং আপনি "লিঙ্ক" বা "সংকলন" ব্যবহার করতে পারেন।

var newElement = $compile( "<div my-diretive='n'></div>" )( $scope );
$element.parent().append( newElement );

উপাদানটিতে একটি নতুন বৈশিষ্ট্য .োকানো হচ্ছে

এটা শক্ত, এবং দু'দিনের মধ্যে আমাকে মাথাব্যথা করে তোলে।

"Ile সংকলন" ব্যবহার করা সমালোচনামূলক পুনরাবৃত্ত ত্রুটি বাড়িয়ে তুলবে !! উপাদানটি পুনরায় সংকলন করার সময় এটি বর্তমান নির্দেশকে উপেক্ষা করা উচিত।

$element.$set("myDirective", "expression");
var newElement = $compile( $element )( $scope ); // critical recursive error.
var newElement = angular.copy(element);          // the same error too.
$element.replaceWith( newElement );

সুতরাং, আমাকে নির্দেশের "লিঙ্ক" ফাংশনটি কল করার একটি উপায় খুঁজে বের করতে হবে। বন্ধের অভ্যন্তরে গভীরভাবে লুকিয়ে থাকা দরকারী পদ্ধতিগুলি পাওয়া খুব কঠিন।

compile: (tElement, tAttrs, transclude) ->
   links = []
   myDirectiveLink = $injector.get('myDirective'+'Directive')[0] #this is the way
   links.push myDirectiveLink
   myAnotherDirectiveLink = ($scope, $element, attrs) ->
       #....
   links.push myAnotherDirectiveLink
   return (scope, elm, attrs, ctrl) ->
       for link in links
           link(scope, elm, attrs, ctrl)       

এখন, এটা ভাল কাজ।


1
যদি সম্ভব হয় তবে ভ্যানিলা জেএস-এ এলিমেন্টের সাথে একটি নতুন বৈশিষ্ট্য সন্নিবেশ করার একটি ডেমো দেখতে পছন্দ করবেন - আমি কিছু মিস করছি ...
প্যাট্রিক

উপাদানটিতে একটি নতুন বৈশিষ্ট্য সন্নিবেশ করার আসল উদাহরণটি এখানে (আমার গিথুব
ব্লব

1
সৎভাবে সাহায্য করে না। যদিও এইভাবে আমি আমার সমস্যার সমাধান শেষ করেছি: stackoverflow.com/a/20137542/1455709
প্যাট্রিক

হ্যাঁ, এই ক্ষেত্রেটি কোনও নির্দেশকে সারণীর মধ্যে সন্নিবেশকারী উপাদানকে নয়, অন্য নির্দেশকে সন্নিবেশ করা।
রাইসবল এলইই

এটি টেমপ্লেটের বাইরে করার পিছনে যুক্তি কী?
প্যাট্রিক

9
function addAttr(scope, el, attrName, attrValue) {
  el.replaceWith($compile(el.clone().attr(attrName, attrValue))(scope));
}

5

জোশ ডেভিড মিলার দ্বারা গৃহীত উত্তরটি দুর্দান্ত কাজ করে যদি আপনি গতিযুক্ত কোনও নির্দেশিকা যুক্ত করতে চেষ্টা করেন যা কোনও ইনলাইন ব্যবহার করে template। তবে আপনার নির্দেশটি যদি templateUrlতার উত্তরটি নেয় তবে তা কার্যকর হবে না। আমার জন্য যা কাজ করেছে তা এখানে:

.directive('helperModal', [, "$compile", "$timeout", function ($compile, $timeout) {
    return {
        restrict: 'E',
        replace: true,
        scope: {}, 
        templateUrl: "app/views/modal.html",
        link: function (scope, element, attrs) {
            scope.modalTitle = attrs.modaltitle;
            scope.modalContentDirective = attrs.modalcontentdirective;
        },
        controller: function ($scope, $element, $attrs) {
            if ($attrs.modalcontentdirective != undefined && $attrs.modalcontentdirective != '') {
                var el = $compile($attrs.modalcontentdirective)($scope);
                $timeout(function () {
                    $scope.$digest();
                    $element.find('.modal-body').append(el);
                }, 0);
            }
        }
    }
}]);

5

জোশ ডেভিড মিলার সঠিক।

পিসিওহেলো, আপনি যদি ভাবছেন যে $compileপর্দার আড়ালে কী ঘটে এবং কীভাবে এইচটিএমএল আউটপুট নির্দেশিকা থেকে উত্পন্ন হয়, দয়া করে নীচে একবার দেখুন

$compileসেবা এইচটিএমএল (এর টুকরা প্রনয়ন "< test text='n' >< / test >") যে নির্দেশ (একটি উপাদান হিসেবে "পরীক্ষা") রয়েছে এবং একটি ফাংশন উৎপন্ন হয়। এর পরে "নির্দেশের থেকে এইচটিএমএল আউটপুট" পাওয়ার সুযোগ নিয়ে এই ফাংশনটি কার্যকর করা যেতে পারে।

var compileFunction = $compile("< test text='n' > < / test >");
var HtmlOutputFromDirective = compileFunction($scope);

পূর্ণ কোডের নমুনাগুলির সাথে আরও বিশদ এখানে: http://www.learn-angularjs-apps-projects.com/AngularJs/dynamically-add-directives-in-angularjs


4

পূর্ববর্তী অনেক উত্তর থেকে অনুপ্রাণিত হয়ে আমি নিম্নলিখিত "স্ট্রোম্যান" নির্দেশিকা নিয়ে এসেছি যা অন্য কোনও নির্দেশের সাথে নিজেকে প্রতিস্থাপন করবে।

app.directive('stroman', function($compile) {
  return {
    link: function(scope, el, attrName) {
      var newElem = angular.element('<div></div>');
      // Copying all of the attributes
      for (let prop in attrName.$attr) {
        newElem.attr(prop, attrName[prop]);
      }
      el.replaceWith($compile(newElem)(scope)); // Replacing
    }
  };
});

গুরুত্বপূর্ণ: আপনি যে নির্দেশাবলীর সাথে ব্যবহার করতে চান তা নিবন্ধভুক্ত করুন restrict: 'C'। এটার মত:

app.directive('my-directive', function() {
  return {
    restrict: 'C',
    template: 'Hi there',
  };
});

আপনি এটির মতো ব্যবহার করতে পারেন:

<stroman class="my-directive other-class" randomProperty="8"></stroman>

এটি পেতে:

<div class="my-directive other-class" randomProperty="8">Hi there</div>

Protip। আপনি যদি ক্লাসের উপর ভিত্তি করে নির্দেশিকা ব্যবহার করতে না চান তবে আপনি নিজের পছন্দমতো '<div></div>'কিছুতে পরিবর্তন করতে পারেন। উদাহরণস্বরূপ একটি নির্দিষ্ট বৈশিষ্ট্য রয়েছে যার পরিবর্তে কাঙ্ক্ষিত নির্দেশিকার নাম রয়েছে class


অনুরূপ সমস্যাটির মুখোমুখি, আপনি কি আমাকে এখানে সহায়তা করতে পারবেন stackoverflow.com/questions/38821980/…
পান্ডু দাস

ঈশ্বর. এই took সংকলনটি খুঁজে পেতে 2 দিন সময় নিয়েছিল ... ধন্যবাদ বন্ধুরা .. এটি সবচেয়ে ভাল কাজ করে ... এজেএস আপনি রক করুন ....
শ্রীনিবাসন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.