2012-08-10 14 views
21

मैं सरल यूई-डेटटाइम निर्देश बना रहा हूं। यह जावास्क्रिप्ट दिनांक वस्तु को _date, _hours और _minutes भागों में विभाजित करता है। _date jquery ui डेटपिकर, _hours और _minutes - संख्या इनपुट का उपयोग करता है।क्या मैं अलग-अलग क्षेत्र के साथ एनजी-मॉडल का उपयोग कर सकता हूं?

angular.module("ExperimentsModule", []) 
    .directive("uiDatetime", function() { 
    return { 
     restrict: 'EA', 
     replace: true, 
     template: '<div class="ui-datetime">' + 
      '<input type="text" ng-model="_date" class="date">' + 
      '<input type="number" ng-model="_hours" min="0" max="23" class="hours">' + 
      '<input type="number" ng-model="_minutes" min="0" max="59" class="minutes">' + 
      '<br />Child datetime1: {{datetime1}}' + 
      '</div>', 
     require: 'ngModel', 
     scope: true, 
     link: function (scope, element, attrs, ngModelCtrl) { 
      var elDate = element.find('input.date'); 

      ngModelCtrl.$render = function() { 
       var date = new Date(ngModelCtrl.$viewValue); 
       var fillNull = function (num) { 
        if (num < 10) return '0' + num; 
        return num; 
       }; 
       scope._date = fillNull(date.getDate()) + '.' + fillNull(date.getMonth() + 1) + '.' + date.getFullYear(); 
       scope._hours = date.getHours(); 
       scope._minutes = date.getMinutes(); 
      }; 

      elDate.datepicker({ 
       dateFormat: 'dd.mm.yy', 
       onSelect: function (value, picker) { 
        scope._date = value; 
        scope.$apply(); 
       } 
      }); 

      var watchExpr = function() { 
       var res = scope.$eval('_date').split('.'); 
       if (res.length == 3) return new Date(res[2], res[1] - 1, res[0], scope.$eval('_hours'), scope.$eval('_minutes')); 
       return 0; 
      }; 
      scope.$watch(watchExpr, function (newValue) { 
       ngModelCtrl.$setViewValue(newValue); 
      }, true); 
     } 
    }; 
}); 

function TestController($scope) { 
    $scope.datetime1 = new Date(); 
} 

jsfiddle

GitHub पर: https://github.com/andreev-artem/angular_experiments/tree/master/ui-datetime

जहां तक ​​मैं समझता हूँ - सबसे अच्छा अभ्यास है जब आप बनाने के लिए एक नया घटक अलग गुंजाइश उपयोग करने के लिए है।

जब मैंने अलग-अलग दायरे का उपयोग करने की कोशिश की - कुछ भी काम नहीं करता है। ngModel। $ viewValue === अपरिभाषित।

जब मैंने नए दायरे का उपयोग करने की कोशिश की (मेरा उदाहरण, इतना अच्छा संस्करण नहीं है) - ngModel नए बनाए गए दायरे पर मूल्य का उपयोग करता है।

बेशक मैं अलग-अलग दायरे के साथ निर्देश बना सकता हूं और "= अभिव्यक्ति" (example) के माध्यम से ngModel मान के साथ काम कर सकता हूं। लेकिन मुझे लगता है कि ngModelController के साथ काम करना एक बेहतर अभ्यास है।

मेरे सवालों का:

  1. मैं अलग गुंजाइश के साथ ngModelController का उपयोग कर सकते हैं?
  2. यदि यह संभव नहीं है कि इस तरह के घटक बनाने के लिए कौन सा समाधान बेहतर है?

उत्तर

2

अपना निर्देश ngModel की तुलना में उच्च प्राथमिकता पर चलाएं और अपने अलग-अलग दायरे के लिए मॉडल बाध्यकारी को सही करें। मैंने '100' की प्राथमिकता चुना है जो इनपुट निर्देश के समान स्तर है, उच्च प्राथमिकता टेम्पलेट मैनिप्लेशंस जैसे ngRepeat के बाद, लेकिन 0 के डिफ़ॉल्ट से पहले, जो ngModel उपयोग करता है।

myDirective = function() { 
    return { 
    compile: function(tElement, tAttrs, transclude) { 
     // Correct ngModel for isolate scope 
     if (tAttrs.ngModel) { 
     tAttrs.$set('model', tAttrs.ngModel, false); 
     tAttrs.$set('ngModel', 'model', false); 
     } 

     return { 
     post: function(scope, iElement, iAttrs, controller) { 
      // Optionally hook up formatters and parsers 
      controller.$formatters.push(function(value) { 
      // ... 
      }) 

      // Render 
      return controller.$render = function() { 
      if (!controller.$viewValue) { 
       return; 
      } 
      angular.extend(scope, controller.$viewValue); 
      }; 
     } 
     }; 
    }, 
    priority: 100, 
    require: '^ngModel', 
    scope: { 
     model: '=' 
    }, 
    }; 
} 

संकलन के दौरान यह निर्देश चेकों ngModel विशेषता मौजूद है या नहीं:

यहाँ उदाहरण कोड है। यह जांच कोणीय के Attributes का उपयोग करके सामान्यीकृत मान पर काम करती है। यदि विशेषता मौजूद है, तो इसे 'मॉडल' ('ngModel' नहीं) के साथ प्रतिस्थापित किया गया है, जिसका नाम हमारे पृथक में डेटा-बाध्य है। हालांकि, हमें एक विशेषता भी बनाना चाहिए ताकि कोणीय हमारे लिए डेटा बाध्यकारी कर सके। दोनों गुण (आपके विकल्प पर) false पैरामीटर के साथ संशोधित हो सकते हैं जो डोम को अपरिवर्तित छोड़ देता है।

+2

समाधान के रूप में लगता है

यहाँ मेरी निर्देश, गैर जरूरी कोड के साथ छीन लिया है। लेकिन कामकाज के लिए मैं 'स्कोप: सत्य' और 'एनजी-मॉडल = "कुछ ओबीजे.ओमप्रॉप" ' –

19

scope: true को scope: { datetime1: '=ngModel'} के साथ scope: { datetime1: '=ngModel'} के साथ बदलकर ठीक काम करने लगता है - fiddle। दुर्भाग्यवश, आपके "उदाहरण" पहेली का लिंक टूटा हुआ है, इसलिए मुझे यकीन नहीं है कि आपने वहां क्या प्रयास किया था।

तो, ऐसा लगता है कि ngModelController को एक अलग दायरे के साथ उपयोग किया जा सकता है।

यहां एक छोटा सा पहेली है जो एचटीएमएल/व्यू में एनजी-मॉडल का उपयोग करता है, एक अलग गुंजाइश है, और लिंक फ़ंक्शन में $ setViewValue: fiddle

अद्यतन: मैं बस कुछ बल्कि दिलचस्प खोज की: अगर अलग गुंजाइश संपत्ति एक अलग नाम दिया जाता है - जैसे, datetime1 के बजाय DT1 कहते हैं - scope: { dt1: '=ngModel'} - यह अब काम करता है! मुझे लगता है कि (जैसे कि, एनजी मॉडल विशेषता मान) अलग गुंजाइश पर एक संपत्ति बनाने के लिए जब हम require: 'ngModel', ngModelController HTML/ध्यान में रखते हुए नाम का उपयोग करता अनुमान लगा रहा हूँ।तो अगर हम ऑब्जेक्ट हैश में एक ही नाम निर्दिष्ट करते हैं, तो सब ठीक है। लेकिन अगर हम एक अलग नाम निर्दिष्ट करते हैं, तो उस नई स्कोप प्रॉपर्टी (उदा।, डीटी 1) हमें आवश्यक ngModelController से संबद्ध नहीं है।

यहां एक updated fiddle है।

+1

ऐसा लगता है कि ngModelController [उपयोग] (https://github.com/angular/angular.js/blob/v1.0.1 /src/ng/directive/input.js#L873) और [घड़ियों] (https://github.com/angular/angular.js/blob/v1.0.1/src/ng/directive/input.js#L998) ngModel पर आधारित है। इसलिए हमें विभिन्न कामकाज का भी उपयोग करना चाहिए। –

+0

क्या यह एक बग @MarkRajcok है? – finishingmove

+0

@finishingmove, मुझे नहीं पता। मुझे लगता है कि अगर हम एक ही नाम का उपयोग करते हैं तो हमें बस "भाग्यशाली" मिलता है (लेकिन मुझे यह भी नहीं पता कि वह भाग्य निर्देश के अंदर कहीं भी टूट सकता है)। कोणीय उदाहरणों में से कोई भी अलग-अलग दायरे का उपयोग नहीं करता है जब उन्हें 'ngModel' की आवश्यकता होती है, इसलिए मैं इसे साफ़ कर दूंगा। –

1

मुझे लगता है कि मुझे एक ही समस्या थी, और मुझे आंशिक अभी तक उपयोग करने योग्य समाधान मिला।

तो, समस्या कई भाग हैं:

  1. अपने कस्टम निर्देश, कुछ निजी संपत्तियों चाहता है यानी अलग गुंजाइश
  2. डोम नोड केवल एक दायरे में हो सकता है, सभी निर्देशों इसे साझा
  3. ngModel = " कुछ कुछ "है कि साझा (पृथक) दायरे में" को बांधता है ", और यह वास्तविक समस्या

तो, मेरा पहला कदमउपयोग करने के लिए मेरी निर्देश के पुनर्लेखन के लिए किया गया है scope:{...} के बजाय 210 (वास्तव में, यह एक आवश्यकता थी, क्योंकि मैं अपने निर्देश की निष्कासित सामग्री के भीतर कुछ वैश्विक दायरे गुणों का उपयोग करना चाहता था): attrs.$observe(), $scope.$parent.$watch() आदि जैसी चीजें मदद मिलीं।

फिर compile() में मैंने ngModel को मूल दायरे की संपत्ति में फिर से बाध्य किया: attrs.$set('ngModel', '$parent.' + attrs.ngModel, false)। और बस यही।

angular.module('App', []).directive('dir', function() { 
    return { 
     /* This one is important: */ 
     scope:true, 
     compile:function (element, attrs, transclude) { 
      /* The trick is here: */ 
      if (attrs.ngModel) { 
       attrs.$set('ngModel', '$parent.' + attrs.ngModel, false); 
      } 

      return function ($scope, element, attrs, ngModel) { 
       // link function body 
      }; 
     } 
    }; 
}); 
+2

का उपयोग भी नहीं तोड़ता है आप बस 'स्कोप: सत्य' और 'एनजी- मॉडल = "someObj.someProp" आपकी चाल के बजाय। 'Ng-model'' के लिए 'someObj.someProp" 'का प्रयोग किया जाता है। –

+1

हां, आपका समाधान भी काम करता है, इंगित करने के लिए धन्यवाद। हालांकि, मेरा कोड निर्देश के सभी उदाहरणों के लिए समस्या को हल करता है, और आपको प्रत्येक उदाहरण के लिए अलग कोड समायोजन की आवश्यकता होती है। मैंने एक डेमो संकलित किया है जहां आप कुछ कोड के बिना कार्रवाई में अपना कोड देख सकते हैं (यानी $ scope.someProp): http://jsbin.com/ejozow/1/edit। बीटीडब्लू, क्या आप सिफारिशों के बारे में पढ़ने के लिए एक लिंक पोस्ट कर सकते हैं? आधिकारिक दस्तावेज़ सामान्य रूप से काफी दुर्लभ प्रतीत होते हैं। – alx

+0

https://plus.google.com/118090665492423851447/posts/KKiLKLCF4Xa - मिस्को हेवरी टिप्पणी देखें। यह अनिवार्य नहीं है लेकिन अनुशंसित है। –

0

इस का एक संस्करण का प्रयास करें::

.directive('myDir', function() { 
    return { 
     restrict: 'EA', 
     scope: { 
        YYY: '=ngModel' 
        }, 
     require: 'ngModel', 
     replace: true, 
     template: function render(element, attrs) { 
      var type = attrs.type || 'text'; 
      var required = attrs.hasOwnProperty('required') ? " required='required'" : ""; 
      return "<input ng-model='YYY' type="' + type + '" + required + ' />'; 
        } 
    }; 
}); 
संबंधित मुद्दे

 संबंधित मुद्दे