javascript एक ui-bootstrap डेटपिकर के लिए कोणीयJs आवरण निर्देश कैसे बनाएं?




jquery angularjs (7)

मैं कुछ दिनांक फ़ील्ड प्रदर्शित करने के लिए ui.bootstrap.datepicker निर्देश का उपयोग कर रहा हूं। हालाँकि अधिकांश समय मुझे एक ही सेटअप की आवश्यकता होती है: मैं चाहता हूं कि यह पॉपअप और पॉपअप बटन के साथ आए और मुझे ग्रंथों के लिए जर्मन नाम भी चाहिए। यह बटन और ग्रंथों के लिए समान कोड बनाता है और बार-बार स्वरूपण करता है, इसलिए मैंने खुद को दोहराने से रोकने के लिए अपना निर्देश लिखा।

यहाँ मेरे निर्देश के साथ एक प्लंकर है । हालांकि मुझे यह गलत लग रहा है। यदि आप "तिथि 1" डेटपिकर का उपयोग करके तिथि पिकर के साथ एक तारीख चुनते हैं जो मेरे निर्देश का उपयोग नहीं करता है तो सब कुछ ठीक काम करता है। मुझे दिनांक 2 के लिए भी यही उम्मीद है, लेकिन इनपुट क्षेत्र में आपूर्ति किए गए टेम्पलेट (या किसी अन्य मूल्य जो मुझे उम्मीद थी) के अनुसार तारीख प्रदर्शित करने के बजाय यह .toString() दिनांक ऑब्जेक्ट (जैसे Fri Apr 03 2015 00:00:00 GMT+0200 (CEST) .toString() प्रतिनिधित्व प्रदर्शित करता है। Fri Apr 03 2015 00:00:00 GMT+0200 (CEST) )।

यहाँ मेरा निर्देश है:

angular.module('ui.bootstrap.demo').directive('myDatepicker', function($compile) {
  var controllerName = 'dateEditCtrl';
  return {
      restrict: 'A',
      require: '?ngModel',
      scope: true,
      link: function(scope, element) {
          var wrapper = angular.element(
              '<div class="input-group">' +
                '<span class="input-group-btn">' +
                  '<button type="button" class="btn btn-default" ng-click="' + controllerName + '.openPopup($event)"><i class="glyphicon glyphicon-calendar"></i></button>' +
                '</span>' +
              '</div>');

          function setAttributeIfNotExists(name, value) {
              var oldValue = element.attr(name);
              if (!angular.isDefined(oldValue) || oldValue === false) {
                  element.attr(name, value);
              }
          }
          setAttributeIfNotExists('type', 'text');
          setAttributeIfNotExists('is-open', controllerName + '.popupOpen');
          setAttributeIfNotExists('datepicker-popup', 'dd.MM.yyyy');
          setAttributeIfNotExists('close-text', 'Schließen');
          setAttributeIfNotExists('clear-text', 'Löschen');
          setAttributeIfNotExists('current-text', 'Heute');
          element.addClass('form-control');
          element.removeAttr('my-datepicker');

          element.after(wrapper);
          wrapper.prepend(element);
          $compile(wrapper)(scope);

          scope.$on('$destroy', function () {
              wrapper.after(element);
              wrapper.remove();
          });
      },
      controller: function() {
          this.popupOpen = false;
          this.openPopup = function($event) {
              $event.preventDefault();
              $event.stopPropagation();
              this.popupOpen = true;
          };
      },
      controllerAs: controllerName
  };
});

और यही मैं इसका उपयोग करता हूं:

<input my-datepicker="" type="text" ng-model="container.two" id="myDP" />

(संकल्पना इस उत्तर से प्रेरित थी)

मैं कोणीय १.३ का उपयोग कर रहा हूँ (प्लंकर १.२ पर है क्योंकि मैंने केवल प्लंकर को angular-ui-bootstrap डेटापिक दस्तावेज से कांटा है)। मुझे उम्मीद है कि इससे कोई फर्क नहीं पड़ेगा।

मेरे इनपुट में टेक्स्ट आउटपुट गलत क्यों है और इसे सही तरीके से कैसे किया जाता है?

अद्यतन करें

इस बीच मैंने थोड़ी प्रगति की। संकलन और लिंक के बारे में अधिक विवरण के बारे में पढ़ने के बाद, इस प्लंकर में मैं अपने डोम हेरफेर करने के लिए लिंक फ़ंक्शन के बजाय संकलन फ़ंक्शन का उपयोग करता हूं। मैं अभी भी डॉक्स के इस अंश से थोड़ा भ्रमित हूं:

नोट: यदि टेम्पलेट को क्लोन किया गया है तो टेम्पलेट का उदाहरण और लिंक का उदाहरण अलग-अलग ऑब्जेक्ट हो सकते हैं। इस कारण से यह डोम ट्रांसफॉर्मेशन के अलावा कुछ भी करने के लिए सुरक्षित नहीं है जो कि कंपाइल फंक्शन के भीतर सभी क्लोन डोम नोड्स पर लागू होता है। विशेष रूप से, डोम श्रोता पंजीकरण एक संकलन फ़ंक्शन के बजाय एक लिंकिंग फ़ंक्शन में किया जाना चाहिए।

विशेष रूप से मुझे आश्चर्य है कि "जो सभी क्लोन डोम नोड्स पर लागू होता है" के साथ क्या मतलब है। मैंने मूल रूप से इसका मतलब यह माना कि "यह DOM टेम्पलेट के सभी क्लोन पर लागू होता है" लेकिन ऐसा नहीं लगता है।

किसी भी तरह: मेरा नया संकलन संस्करण क्रोमियम में ठीक काम करता है। फ़ायरफ़ॉक्स में मुझे पहले डेट पिकर का उपयोग करके एक तिथि का चयन करना होगा और उसके बाद सब कुछ ठीक काम करता है (फ़ायरफ़ॉक्स के साथ समस्या स्वयं हल हो जाती है अगर मैं डेट पिकर के डेट पार्सर में अशक्त ( plunkr ) के लिए अपरिभाषित बदल देता हूं)। तो यह नवीनतम बात नहीं है। और इसके अलावा मैं ng-model2 ng-model बजाय ng-model करता हूं जिसे मैं संकलन के दौरान नाम देता हूं। अगर मैं ऐसा नहीं करता हूं तो भी सब कुछ टूट गया है। फिर भी पता नहीं क्यों।


मुझे लगता है कि @ omri-aharon से जवाब सबसे अच्छा है, लेकिन मैं कुछ सुधारों की ओर इशारा करना चाहता हूं जिनका यहां उल्लेख नहीं किया गया है:

अपडेट किया गया प्लंकर

आप अपने विकल्पों को समान रूप से सेट करने के लिए कॉन्फ़िगरेशन का उपयोग कर सकते हैं जैसे कि प्रारूप और पाठ विकल्प निम्नानुसार हैं:

angular.module('ui.bootstrap.demo', ['ui.bootstrap'])
.config(function (datepickerConfig, datepickerPopupConfig) {
  datepickerConfig.formatYear='yy';
  datepickerConfig.startingDay = 1;
  datepickerConfig.showWeeks = false;
  datepickerPopupConfig.datepickerPopup = "shortDate";
  datepickerPopupConfig.currentText = "Heute";
  datepickerPopupConfig.clearText = "Löschen";
  datepickerPopupConfig.closeText = "Schließen";
});

मुझे यह स्पष्ट और अपडेट करने में आसान लगता है। यह आपको निर्देश, टेम्पलेट और मार्कअप को बहुत सरल बनाने की अनुमति देता है।

कस्टम निर्देश

angular.module('ui.bootstrap.demo').directive('myDatepicker', function() {
  return {
      restrict: 'E',
      scope: {
          model: "=",
          myid: "@"
      },
      templateUrl: 'datepicker-template.html',
      link: function(scope, element) {
          scope.popupOpen = false;
          scope.openPopup = function($event) {
              $event.preventDefault();
              $event.stopPropagation();
              scope.popupOpen = true;
          };

          scope.open = function($event) {
            $event.preventDefault();
            $event.stopPropagation();
            scope.opened = true;
          };

      }
  };
});

खाका

<div class="row">
    <div class="col-md-6">
        <p class="input-group">
          <input type="text" class="form-control" id="{{myid}}" datepicker-popup ng-model="model" is-open="opened" ng-required="true"  />
          <span class="input-group-btn">
            <button type="button" class="btn btn-default" ng-click="open($event)"><i class="glyphicon glyphicon-calendar"></i></button>
          </span>
        </p>
    </div>
</div> 

इसे कैसे उपयोग करे

<my-datepicker model="some.model" myid="someid"></my-datepicker>

इसके अलावा, यदि आप जर्मन लोकेल फॉर्मेटिंग के उपयोग को लागू करना चाहते हैं, तो आप कोणीय-लोकेल_डे.जे जोड़ सकते हैं। यह 'shortDate' जैसे तारीखों के स्थिरांक के उपयोग में एकरूपता सुनिश्चित करता है और जर्मन महीने और दिन के नामों के उपयोग को 'shortDate' करता है।


यदि निर्देश बनाना एक विशेषता है, तो आप मूल इनपुट पर 2 निर्देश रख सकते हैं:

<input my-datepicker="" datepicker-popup="{{ format }}" type="text" ng-model="container.two" id="myDP" />

फिर स्कोप को बदलकर कई अलग-थलग स्कोप से बचें scope: true scope: false लिए scope: true scope: false myDatepicker निर्देश में scope: false

यह काम करता है और मुझे लगता है कि तारीख इनपुट को वांछित प्रारूप में बदलने के लिए एक और निर्देश बनाने के लिए बेहतर है:

http://plnkr.co/edit/23QJ0tjPy4zN16Sa7svB?p=preview

आप निर्देश के भीतर से विशेषता क्यों जोड़ रहे हैं, इस मुद्दे का मुझे कोई पता नहीं है, यह लगभग वैसा ही है जैसे आपके पास एक ही इनपुट पर 2 दिनांक-पिकर हों, एक आपके प्रारूप के साथ और दूसरा डिफ़ॉल्ट रूप से जिसके बाद आवेदन किया जाता है।


डेट टाइम फॉर्मेट के लिए पैटर्न का एक व्यापक सेट प्रदान करने के लिए निर्देश बनाने के लिए ui-बूटस्ट्रैप डेटपिकर घटक के साथ क्षणों का उपयोग करें। आप अलग-अलग दायरे में किसी भी समय प्रारूप को स्वीकार कर सकते हैं।


मैंने यह काम करने की कोशिश की है (कुछ हद तक हैक), जो कि आप जैसा चाहते हैं वैसा नहीं हो सकता है, बस कुछ मोटे विचार। इसलिए आपको अभी भी इसे थोड़ा छोटा करने की जरूरत है। प्लंकर है:

`http://plnkr.co/edit/aNiL2wFz4S0WPti3w1VG?p=preview'

असल में, मैंने निर्देशांक गुंजाइश को बदल दिया है, और गुंजाइश var कंटेनर के लिए घड़ी भी जोड़ें। दो।


जब आप इन २ पंक्तियों को अपनी निर्देशक परिभाषा में जोड़ते हैं तो आपका निर्देशन काम करेगा:

return {
    priority: 1,
    terminal: true,
    ...
 }

यह उस क्रम के साथ करना है जिसमें निर्देशों को निष्पादित किया जाता है।

तो आपके कोड में

<input my-datepicker="" type="text" ng-model="container.two" id="myDP" />

दो निर्देश हैं: ngModel और myDatepicker । प्राथमिकता के साथ आप ngModel करने से पहले अपने खुद के निर्देशन को अंजाम दे सकते हैं।


ईमानदार होने के लिए, मुझे यह पक्का पता नहीं है कि ऐसा क्यों होता है और इनपुट में इसे दिखाने से पहले आपकी तारीख "toString-ed" होने का कारण है।

हालाँकि, मुझे आपके निर्देश का पुनर्गठन करने के लिए जगह मिली, और बहुत सारे अनावश्यक कोड को हटा दिया गया, जैसे $compile सेवा, गुण परिवर्तन, गुंजाइश विरासत, निर्देश में require , आदि। मैंने अलग-अलग गुंजाइश का उपयोग किया, क्योंकि मुझे नहीं लगता कि हर निर्देश। अभिभावक के दायरे का उपयोग पता होना चाहिए क्योंकि इससे शातिर कीड़े आगे जा सकते हैं। यह मेरा बदला हुआ निर्देश है:

angular.module('ui.bootstrap.demo').directive('myDatepicker', function() {
  return {
      restrict: 'A',
      scope: {
          model: "=",
          format: "@",
          options: "=datepickerOptions",
          myid: "@"
      },
      templateUrl: 'datepicker-template.html',
      link: function(scope, element) {
          scope.popupOpen = false;
          scope.openPopup = function($event) {
              $event.preventDefault();
              $event.stopPropagation();
              scope.popupOpen = true;
          };

          scope.open = function($event) {
            $event.preventDefault();
            $event.stopPropagation();
            scope.opened = true;
          };

      }
  };
});

और आपका HTML उपयोग हो जाता है:

<div my-datepicker model="container.two" 
                   datepicker-options="dateOptions" 
                   format="{{format}}"  
                   myid="myDP">
</div>

संपादित करें : निर्देश के लिए id को एक पैरामीटर के रूप में जोड़ा गया। प्लंकर अपडेट किया गया है।

Plunker


अगर किसी को टाइपस्क्रिप्ट कार्यान्वयन में रुचि है (@ jme11 के कोड के आधार पर):

निर्देशक:

'use strict';

export class DatePickerDirective implements angular.IDirective {
    restrict = 'E';
    scope={
        model: "=",
        myid: "@"
    };
    template = require('../../templates/datepicker.tpl.html');

    link = function (scope, element) {
        scope.altInputFormats = ['M!/d!/yyyy', 'yyyy-M!-d!'];
        scope.popupOpen = false;
        scope.openPopup = function ($event) {
            $event.preventDefault();
            $event.stopPropagation();
            scope.popupOpen = true;
        };

        scope.open = function ($event) {
            $event.preventDefault();
            $event.stopPropagation();
            scope.opened = true;
        };
    };

    public static Factory() : angular.IDirectiveFactory {
        return () => new DatePickerDirective();
    }
}

angular.module('...').directive('datepicker', DatePickerDirective.Factory())

टेम्पलेट:

<p class="input-group">
    <input type="text" class="form-control" id="{{myid}}"
           uib-datepicker-popup="MM/dd/yyyy" model-view-value="true"
           ng-model="model" ng-model-options="{ getterSetter: true, updateOn: 'blur' }"
           close-text="Close" alt-input-formats="altInputFormats"
           is-open="opened" ng-required="true"/><span class="input-group-btn"><button type="button" class="btn btn-default" ng-click="open($event)"><i
        class="glyphicon glyphicon-calendar"></i></button>
          </span>
</p>

उपयोग:

<datepicker model="vm.FinishDate" myid="txtFinishDate"></datepicker>




angular-ui-bootstrap