একটি নির্দেশকের মধ্যে টেমপ্লেটটি কাস্টমাইজ করা


98

আমার একটি ফর্ম রয়েছে যা নীচের মত বুটস্ট্র্যাপ থেকে মার্কআপ ব্যবহার করছে:

<form class="form-horizontal">
  <fieldset>
    <legend>Legend text</legend>
    <div class="control-group">
      <label class="control-label" for="nameInput">Name</label>
      <div class="controls">
        <input type="text" class="input-xlarge" id="nameInput">
        <p class="help-block">Supporting help text</p>
      </div>
    </div>
  </fieldset>
</form>

সেখানে অনেকগুলি বয়লারপ্লেট কোড রয়েছে, যে আমি একটি নতুন নির্দেশকে হ্রাস করতে চাই - ফর্ম-ইনপুট, নীচের মত:

<form-input label="Name" form-id="nameInput"></form-input>

উত্পন্ন:

   <div class="control-group">
      <label class="control-label" for="nameInput">Name</label>
      <div class="controls">
        <input type="text" class="input-xlarge" id="nameInput">
      </div>
    </div>

আমি একটি সাধারণ টেম্পলেট মাধ্যমে এই অনেক কাজ।

angular.module('formComponents', [])
    .directive('formInput', function() {
        return {
            restrict: 'E',
            scope: {
                label: 'bind',
                formId: 'bind'
            },
            template:   '<div class="control-group">' +
                            '<label class="control-label" for="{{formId}}">{{label}}</label>' +
                            '<div class="controls">' +
                                '<input type="text" class="input-xlarge" id="{{formId}}" name="{{formId}}">' +
                            '</div>' +
                        '</div>'

        }
    })

যাইহোক এটি যখন আমি আরও উন্নত কার্যকারিতা যুক্ত করতে আসি যা আমি আটকে যাচ্ছি।

আমি কীভাবে টেমপ্লেটে ডিফল্ট মানগুলি সমর্থন করতে পারি?

আমি আমার নির্দেশের উপর একটি typeচ্ছিক বৈশিষ্ট্য হিসাবে "টাইপ" পরামিতিটি প্রকাশ করতে চাই, যেমন:

<form-input label="Password" form-id="password" type="password"/></form-input>
<form-input label="Email address" form-id="emailAddress" type="email" /></form-input>

যাইহোক, যদি কিছু নির্দিষ্ট না করা হয় তবে আমি ডিফল্ট করতে চাই "text"। আমি কীভাবে এটি সমর্থন করতে পারি?

বৈশিষ্ট্যের উপস্থিতি / অনুপস্থিতির ভিত্তিতে আমি কীভাবে টেমপ্লেটটি কাস্টমাইজ করতে পারি?

আমি উপস্থিত থাকলে "প্রয়োজনীয়" বৈশিষ্ট্যটি সমর্থন করতে সক্ষম হতে চাই। যেমন:

<form-input label="Email address" form-id="emailAddress" type="email" required/></form-input>

যদি requiredনির্দেশে উপস্থিত থাকে তবে আমি এটিকে <input />আউটপুটটিতে উত্পন্ন উত্সে যুক্ত করতে চাই এবং অন্যথায় এড়িয়ে যাব । আমি কীভাবে এটি অর্জন করব তা নিশ্চিত নই।

আমি সন্দেহ করি যে এই প্রয়োজনীয়তাগুলি একটি সাধারণ টেম্পলেট ছাড়িয়ে গেছে এবং প্রাক-সংকলন পর্যায়গুলি ব্যবহার করতে শুরু করেছে, তবে আমি যেখানে শুরু করব সেখানেই আমার ক্ষতি হচ্ছে।


আমি কি কেবলমাত্র সেই ঘরে হাতিটিকে দেখছি :) -> typeবাঁধাইয়ের মাধ্যমে যদি গতিশীল সেট করা হয় তবে কী হবে । type="{{ $ctrl.myForm.myField.type}}"? আমি নীচে সমস্ত পদ্ধতি পরীক্ষা করে দেখেছি এবং এই দৃশ্যে কাজ করবে এমন কোনও সমাধান খুঁজে পাইনি। দেখে মনে হচ্ছে টেমপ্লেট ফাংশন যেমন বৈশিষ্ট্যগুলির আক্ষরিক মান দেখতে পাবে । tAttr['type'] == '{{ $ctrl.myForm.myField.type }}'পরিবর্তে tAttr['type'] == 'password'। আমি হতভম্ব.
দিমিত্রি কে

উত্তর:


211
angular.module('formComponents', [])
  .directive('formInput', function() {
    return {
        restrict: 'E',
        compile: function(element, attrs) {
            var type = attrs.type || 'text';
            var required = attrs.hasOwnProperty('required') ? "required='required'" : "";
            var htmlText = '<div class="control-group">' +
                '<label class="control-label" for="' + attrs.formId + '">' + attrs.label + '</label>' +
                    '<div class="controls">' +
                    '<input type="' + type + '" class="input-xlarge" id="' + attrs.formId + '" name="' + attrs.formId + '" ' + required + '>' +
                    '</div>' +
                '</div>';
            element.replaceWith(htmlText);
        }
    };
})

6
এটি কিছুটা দেরি হয়ে গেছে, তবে আপনি যদি অন্য কোথাও htmlTextযুক্ত হন ng-clickতবে কেবলমাত্র পরিবর্তনের সাথে প্রতিস্থাপন element.replaceWith(htmlText)করা হবে element.replaceWith($compile(htmlText))?
jclancy

@ মিসকো, আপনি সুযোগ থেকে মুক্তি পাওয়ার জন্য উল্লেখ করেছেন। কেন? আমি একটি নির্দেশিকা করেছি যা বিচ্ছিন্ন সুযোগের সাথে ব্যবহার করার সময় সংকলন করে না।
সিয়াম

4
htmlTextকোনও এনজি-ট্রান্সক্লুড ডায়রেক্টিভ থাকলে এটি কাজ করে না
Alp

4
দুর্ভাগ্যক্রমে আমি খুঁজে পেয়েছি যে ফর্মের বৈধতা এটির সাথে কাজ করে না বলে মনে হচ্ছে, $errorinputোকানো ইনপুটটিতে পতাকা কখনও সেট হয় না। আমাকে একটি নির্দেশিকার লিঙ্কের সম্পত্তিটির $compile(htmlText)(scope,function(_el){ element.replaceWith(_el); });মধ্যে এটি করতে হয়েছিল: ফর্মটির নিয়ামকটির সদ্য গঠিত অস্তিত্বকে স্বীকৃতি দেওয়ার জন্য এবং এটি বৈধতার সাথে অন্তর্ভুক্ত করার জন্য। আমি এটি কোনও নির্দেশিকার সংকলনের সম্পত্তিতে কাজ করতে পারি না।
মেকনরোয়

5
ঠিক আছে, এটি ২০১৫ এর বাইরে এবং আমি নিশ্চিত যে স্ক্রিপ্টগুলিতে ম্যানুয়ালি মার্কআপ তৈরির ক্ষেত্রে ভীষণরকম কিছু আছে ।
বোরিসকুনসকি

38

মিসকো প্রস্তাবিত সমাধানটি ব্যবহার করার চেষ্টা করেছিলেন, কিন্তু আমার পরিস্থিতিতে কিছু বৈশিষ্ট্য, যা আমার টেমপ্লেট এইচটিএমএলে একত্রীকরণের প্রয়োজন ছিল, সেগুলি নিজেই নির্দেশ ছিল।

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

সমাধানটি কোডটি সরিয়ে নেওয়া হয়েছিল, যা এইচটিএমএল তৈরি করে, টেমপ্লেট ফাংশনে সংকলন থেকে এইচটিএমএল তৈরি করে। উপরের কোডের ভিত্তিতে উদাহরণ:

    angular.module('formComponents', [])
  .directive('formInput', function() {
    return {
        restrict: 'E',
        template: function(element, attrs) {
           var type = attrs.type || 'text';
            var required = attrs.hasOwnProperty('required') ? "required='required'" : "";
            var htmlText = '<div class="control-group">' +
                '<label class="control-label" for="' + attrs.formId + '">' + attrs.label + '</label>' +
                    '<div class="controls">' +
                    '<input type="' + type + '" class="input-xlarge" id="' + attrs.formId + '" name="' + attrs.formId + '" ' + required + '>' +
                    '</div>' +
                '</div>';
             return htmlText;
        }
        compile: function(element, attrs)
        {
           //do whatever else is necessary
        }
    }
})

এটি টেমপ্লেটে এম্বেড করা এনজি-ক্লিক দিয়ে আমার সমস্যার সমাধান করেছে
জোশকমলে

ধন্যবাদ, এটি আমার জন্যও কাজ করেছিল। কিছু ডিফল্ট বৈশিষ্ট্য প্রয়োগ করার জন্য কোনও নির্দেশ মোড়তে চেয়েছিল।
মার্টিনোস

4
ধন্যবাদ, আমি এমনকি টেমপ্লেট একটি ফাংশন গ্রহণ যে অবগত ছিল না!
জন তুষার

4
এটি কোনও কর্মক্ষেত্র নয়। এটি ওপি-র সঠিক উত্তর। শর্তসাপেক্ষে উপাদানটির বৈশিষ্ট্যের উপর নির্ভর করে একটি টেম্পলেট তৈরি করা হ'ল নির্দেশ / উপাদান টেম্পলেট ফাংশনের সঠিক উদ্দেশ্য। এর জন্য আপনার কম্পাইল ব্যবহার করা উচিত নয়। কৌণিক দলটি এই স্টাইলের কোডিং (কম্পাইল ফাংশনটি ব্যবহার না করে) প্রচন্ডভাবে উত্সাহিত করছে।
jose.angel.jimenez

এটি সঠিক উত্তর হওয়া উচিত, এমনকি আমি সচেতন ছিলাম না যে টেমপ্লেট কোনও ফাংশন নেয় :)
নেভারজিভআপ 161

5

উপরের উত্তরগুলি দুর্ভাগ্যক্রমে কার্যকরভাবে কাজ করে না। বিশেষত, সংকলন পর্যায়ে স্কোপের অ্যাক্সেস নেই, তাই আপনি গতিশীল বৈশিষ্ট্যের উপর ভিত্তি করে ক্ষেত্রটি কাস্টমাইজ করতে পারবেন না। লিঙ্কিং স্টেজটি ব্যবহার করা সর্বাধিক নমনীয়তার প্রস্তাব দেয় (সংবিধানস্বরূপ ডোম তৈরির ক্ষেত্রে) নীচের পদ্ধতির ঠিকানা যা:

<!-- Usage: -->
<form>
  <form-field ng-model="formModel[field.attr]" field="field" ng-repeat="field in fields">
</form>
// directive
angular.module('app')
.directive('formField', function($compile, $parse) {
  return { 
    restrict: 'E', 
    compile: function(element, attrs) {
      var fieldGetter = $parse(attrs.field);

      return function (scope, element, attrs) {
        var template, field, id;
        field = fieldGetter(scope);
        template = '..your dom structure here...'
        element.replaceWith($compile(template)(scope));
      }
    }
  }
})

আমি আরও সম্পূর্ণ কোড এবং পদ্ধতির একটি লিখনআপ সহ একটি গিস্ট তৈরি করেছি ।


সুন্দর পদ্ধতির দুর্ভাগ্যবশত যখন ngTransclude এর মাধ্যমে ব্যবহার আমি নিম্নলিখিত ত্রুটির পাবেন:Error: [ngTransclude:orphan] Illegal use of ngTransclude directive in the template! No parent directive that requires a transclusion found.
আল্প

এবং কেন 'ফিল্ড: "="' দিয়ে বিচ্ছিন্ন সুযোগ ব্যবহার করবেন না?
IttayD

খুব সুন্দর ধন্যবাদ! দুর্ভাগ্যক্রমে আপনার লিখিত পদ্ধতিটি অফলাইনে রয়েছে :(
মিশিগেল

গিস্ট এবং রাইটআপ উভয়ই মৃত লিঙ্ক।
বিনকি

4

এখানে আমি ব্যবহার করে কি শেষ করেছি।

আমি অ্যাঙ্গুলারজেএস-এ খুব নতুন, তাই আরও ভাল / বিকল্প সমাধান দেখতে ভাল লাগবে।

angular.module('formComponents', [])
    .directive('formInput', function() {
        return {
            restrict: 'E',
            scope: {},
            link: function(scope, element, attrs)
            {
                var type = attrs.type || 'text';
                var required = attrs.hasOwnProperty('required') ? "required='required'" : "";
                var htmlText = '<div class="control-group">' +
                    '<label class="control-label" for="' + attrs.formId + '">' + attrs.label + '</label>' +
                        '<div class="controls">' +
                        '<input type="' + type + '" class="input-xlarge" id="' + attrs.formId + '" name="' + attrs.formId + '" ' + required + '>' +
                        '</div>' +
                    '</div>';
                element.html(htmlText);
            }
        }
    })

ব্যবহারের উদাহরণ:

<form-input label="Application Name" form-id="appName" required/></form-input>
<form-input type="email" label="Email address" form-id="emailAddress" required/></form-input>
<form-input type="password" label="Password" form-id="password" /></form-input>

10
আরও ভাল সমাধান হ'ল: (1) ফাংশন সংযোগের পরিবর্তে একটি সংকলন ফাংশন ব্যবহার করুন এবং প্রতিস্থাপনটি সেখানে করুন। আপনি এটি কাস্টমাইজ করতে চান বলে টেমপ্লেটটি আপনার ক্ষেত্রে কাজ করবে না। (২) সুযোগ থেকে মুক্তি পান:
মিসকো হেভারি

@ মেসকোহোরি প্রতিবেদনের জন্য ধন্যবাদ - আপনি এখানে একটি লিঙ্ক ফাংশন কেন একটি সংকলন ফাংশন সমর্থন করা হয় তা ব্যাখ্যা করতে আপত্তি হবে?
মার্টি পিট

4
আমি মনে করি এটি ডকস.অঙ্গুলারজেএস.আর.জি.আউইউ / গাইড / ডাইরেক্টিভের উত্তর : "নির্দেশের উদাহরণের মধ্যে [যেমন, টেমপ্লেট ডিওএম রূপান্তরকরণ] এর মধ্যে ভাগ করা যায় এমন কোনও ক্রিয়াকলাপ পারফরম্যান্সের কারণে কম্পাইল ফাংশনে স্থানান্তরিত করা উচিত" "
রাজকোক

@ মার্টি আপনি কি এখনও কোনও মডেলের সাথে আপনার কাস্টম ইনপুটগুলিকে বাঁধতে সক্ষম হন? (উদা। <form-input ng-model="appName" label="Application Name" form-id="appName" required/></form-input>)
জোনাথন উইলসন

4
ওরিলির "অ্যাঙ্গুলারজেএস" বইটি থেকে @ মার্টিপিট: "সুতরাং আমরা compileপর্বটি পেয়েছি , যা টেমপ্লেটটি রূপান্তর করার বিষয়ে আলোচনা করে, এবং linkপর্যায়টি, যা ভিউতে ডেটা পরিবর্তন করার বিষয়টি নিয়ে কাজ করে these এই লাইনের পাশাপাশি, প্রাথমিক পার্থক্যের মধ্যে compileএবং linkনির্দেশাবলীর কাজগুলি হ'ল compileফাংশনগুলি নিজেই টেমপ্লেটটি রূপান্তরিত করে, এবং linkফাংশনগুলি মডেল এবং দৃশ্যের মধ্যে একটি গতিশীল সংযোগ তৈরির বিষয়টি নিয়ে কাজ করে। এটি দ্বিতীয় পর্যায়ে স্কোপগুলি সংকলিত linkফাংশনগুলির সাথে সংযুক্ত করা হয় , এবং নির্দেশিকা ডেটা বাইন্ডিংয়ের মাধ্যমে লাইভ হয়ে যায় data "
জুলিয়ান
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.