2014-07-11 12 views
25

ngModel (और बाद में सत्यापन) को अद्यतन करने के लिए डिफ़ॉल्ट व्यवहार पर बदलें; मैं इसे धुंध पर बदलना चाहता हूं। docs केवल यह बताएं कि केस-दर-मामले आधार पर इसे कैसे करें: <ANY ng-model-options="{ updateOn: 'blur' }"></ANY>। मैं स्रोत कोड के माध्यम से देखने के लिए अब तक गया था, लेकिन किसी भी तरह न तो ngModelOptions और न ही एनजी-मॉडल-विकल्प पाया गया है (दस्तावेज में होने वाले दोनों के बावजूद, जो स्रोत कोड से स्क्रैप किया गया है)।कोणीयजेएस सेट वैश्विक ngModelOptions

+0

जब भी मैं इस तरह की चीजें चलाता हूं, तो मैं अपना खुद का निर्देश बनाता हूं जो विभिन्न गुणों के साथ टेम्पलेट देता है – charlietfl

+0

@charlietfl, मैंने इसके बारे में सोचा, लेकिन यह एक कामकाज है। यदि संभव हो, तो मैं एक उचित समाधान पसंद करूंगा। फिर भी सुझाव के लिए धन्यवाद। – jacob

+1

इनपुट.जेएस में कोणीय स्रोत में: https://github.com/angular/angular.js/blob/master/src/ng/directive/input.js#L2657 – pixelbits

उत्तर

12

यह वास्तव में एक अच्छा सवाल है इसलिए मैंने blog article about this और अधिक indepth लिखा है। ऐसा करने का एकमात्र असली सामान्य तरीका यह है कि मैं ngModel निर्देश को सजाने के लिए है क्योंकि यह निर्देश है जो वास्तव में ngModelOptions का उपयोग करता है।

यदि आप ngModel निर्देश के लिए कोणीय स्रोत को देखते हैं तो यह संपत्ति $ विकल्पों के उपयोग के माध्यम से ngModelController पर ngModelOptions को प्रभावी ढंग से स्थापित करने के लिए एक पूर्व लिंक फ़ंक्शन है। ध्यान दें कि $ विकल्प ngModelOptionsDirective में बनाया गया है जो एनजी-मॉडल-विकल्प विशेषता पर प्रभावी रूप से $ eval है।

हमारे एनजी मॉडल डीक्टरेटर में हमें क्या करने की ज़रूरत है, इस प्री लिंक फ़ंक्शन के बाद यह $ विकल्प संपत्ति के लिए डिफ़ॉल्ट मान जोड़ता है, यदि यह अपरिभाषित है। मैं यहां मान रहा हूं कि अगर डेवलपर ने आपके प्रोजेक्ट में ngModelOptions को स्पष्ट रूप से सेट किया है, तो वे नहीं चाहते हैं कि यह जादुई रूप से बदल जाए! इसलिए यदि हम $ विकल्प संपत्ति को अपरिभाषित करते हैं तो हम केवल डिफ़ॉल्ट सेट करेंगे।

(function (angular) { 
'use strict'; 

angular.module('myAppOverridesModule').config(['$provide', 
    function ($provide) { 
     $provide.decorator('ngModelDirective', [ 
      '$delegate', 
      function ($delegate) { 
       var directive = $delegate[0], 
        link = directive.link, 
        shouldSetBlurUpdateEvent = function (nodeName, inputType) { 
         // The blur event is only really applicable to input controls so 
         // we want to stick with the default events for selects, checkboxes & radio buttons 
         return nodeName.toLowerCase() === 'textarea' || 
           (nodeName.toLowerCase() === 'input' && 
           inputType.toLowerCase() !== 'checkbox' && 
           inputType.toLowerCase() !== 'radio'); 
        }; 

       directive.compile = function() { 
        return function (scope, element, attrs, ctrls) { 
         var ngModelCtrl = ctrls[0]; 
         link.pre.apply(this, arguments); 

         // if ngModelOptions is specified leave it unmodified as developer is explicitly setting it. 
         if (ngModelCtrl.$options === undefined && shouldSetBlurUpdateEvent(element[0].nodeName, element[0].type)) { 
          console.log('set'); 
          ngModelCtrl.$options = { 
           updateOn: 'blur', 
           updateOnDefault: false 
          }; 
         } 

         link.post.apply(this, arguments); 
        }; 
       }; 

       return $delegate; 
      } 
     ]); 
    } 
]); 
}(angular)); 

अद्यतन:

यहाँ कोड है मैं चयन, चेक बॉक्स & रेडियो बटन को अनदेखा करने के रूप में कलंक घटना उनके लिए इष्टतम अद्यतन घटना नहीं है कोड नवीनीकृत किया है।

+0

मीठे, धन्यवाद जैसे बहस का उपयोग करें! यह ठोस दिखता है - मैं इसे आज़माउंगा। – jacob

+0

कूल - मुझे बताएं कि इसके साथ कुछ भी अपेक्षित काम नहीं कर रहा है :-) – Jon

+0

ओह डर्न-मुझे अभी एहसास हुआ कि 'एनजी मॉडेलऑप्शन' अभी भी बीटा में है :( – jacob

5

मैंने जॉन सैमवेल के जवाब को संशोधित किया क्योंकि मैं अब और काम नहीं कर सका।

यह इसके संदर्भ को संग्रहीत करके ngModelDirective के संकलन फ़ंक्शन को ओवरराइड करता है, फिर पूर्व/पोस्टलिंक फ़ंक्शन w/कॉल को उनके मूल के साथ-साथ हमारे अतिरिक्त ओवरराइड कोड पर वापस लौटाता है।

आनंद लें!

app.config(function($provide) { 

    $provide.decorator('ngModelDirective', function($delegate) { 
     var directive = $delegate[0], 
      link = directive.link, 
      shouldSetBlurUpdateEvent = function (nodeName, inputType) { 
       // The blur event is only really applicable to input controls so 
       // we want to stick with the default events for selects, checkboxes & radio buttons 
       return nodeName.toLowerCase() === 'textarea' || 
        (nodeName.toLowerCase() === 'input' && 
        inputType.toLowerCase() !== 'checkbox' && 
        inputType.toLowerCase() !== 'radio'); 
       }; 

     // save a reference to the original compile function 
     var compileFn = directive.compile; 

     directive.compile = function() { 

      var link = compileFn.apply(this, arguments); 

      return { 
       pre: function ngModelPostLink(scope, element, attr, ctrls) { 

        if(!ctrls[2]) { 
         ctrls[2] = {}; 
        } 

        var ngModelOptions = ctrls[2]; 

        if (ngModelOptions.$options === undefined && shouldSetBlurUpdateEvent(element[0].nodeName, element[0].type)) { 
         ngModelOptions.$options = { 
          updateOn: 'blur', 
          updateOnDefault: false 
         }; 
        } 

        link.pre.apply(this, arguments); 
       }, 
       post: link.post 
      }; 
     }; 

     return $delegate; 
    }); 

}); 
24

ngModel सज्जाकार जॉन द्वारा लिखित/जॉन दृश्य समाधान के पीछे एक अच्छा प्रदान करते हैं, एक भी पता है कि एलान के तौर पर, ngModelOptions व्यक्ति इनपुट क्षेत्र स्तर पर घोषित होने की जरूरत नहीं की जरूरत है, लेकिन कम से घोषित किया जा सकता होना चाहिए मॉड्यूल स्तर।

<body ng-app = "myApp" ng-model-options="{ updateOn: 'blur' }"> 

कर ऊपर myApp मॉड्यूल में सभी इनपुट क्षेत्रों के लिए होता है एनजी मॉडल-विकल्पों के वारिस। यदि आवश्यक हो तो इन्हें विशिष्ट इनपुट फ़ील्ड में ओवरराइड किया जा सकता है (उदाहरण के लिए खोज फ़िल्टर)।

यह plunker को दर्शाता है: http://plnkr.co/edit/2L1arGgHJwK82xVucJ4p?p=preview

+0

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

+2

हमारी टीम के लिए, हम 'allowInvalid' के लिए 'झूठी' के डिफ़ॉल्ट विकल्प से लगातार जलाते हैं। इसे एप्लिकेशन स्तर पर सेट करना बहुत सारे मुद्दों को बचाता है जब हम अप्रत्याशित रूप से अमान्य रूप से निर्धारित किए गए मॉडल गुणों को 'अपरिभाषित' पर सेट करते हैं (जो हमें अंतर्ज्ञानी नहीं लगता है)। – wintondeshong

+0

देखें कि मुझे AngularJS में मॉडल अमान्यता समस्या के बारे में पता है, लेकिन किसी भी तरह से यह नहीं पता था कि ngModelOptions इसे संभालने की अनुमति देता है। टिप्पणी करने के लिए धन्यवाद। और मैं पूरी तरह से सहमत हूं कि इसके अनजान - एंगुलरजेएस गिट मुद्दे [यहां] (https://github.com/angular/angular.js/issues/2743#issuecomment-61847365) में इसके बारे में अधिक बात की गई है। । – Angad

23

@Angad आप किसी भी तत्व पर एनजी मॉडल-विकल्प सेट कर सकते हैं, और यह अपने सभी सन्तान करने के लिए लागू किया जाएगा उल्लेख के रूप में।

<body ng-app="myApp" ng-model-options="{ updateOn: 'blur' }"> 

यह updateOn करने के लिए change और click जोड़कर धोखा दिया जा सकता:

<body ng-app="myApp" ng-model-options="{ updateOn: 'change click blur' }"> 

हालांकि, इस के साथ समस्या यह है कि आप इसे इस तरह से सेट करते हैं, रेडियो और चेक बॉक्स काम करना बंद कर के रूप में उम्मीद है आप भी इस्तेमाल कर सकते हैं निम्नलिखित आप टाइप करने के बाद एक निश्चित विलंब के बाद अद्यतन करना चाहते हैं, तो:

<body ng-app="myApp" ng-model-options="{ updateOn: 'keyup change click blur', debounce: { keyup: 500, click: 0, change: 0, blur: 0 } }"> 

मैं में इन तकनीकों का परीक्षण किया फ़ायरफ़ॉक्स, क्रोम, इंटरनेट एक्सप्लोरर (10, 11) और सफारी। यदि आप अन्य घटनाओं का उपयोग करते हैं, तो इन्हें क्रॉस ब्राउज़र का परीक्षण करना सुनिश्चित करें, उदाहरण के लिए रेडियो को आग के बाद change सीधे क्लिक करने के बाद, आईई को छोड़कर सभी ब्राउज़रों पर क्लिक करें।

+0

ध्यान देने योग्य भी: आप मूल तत्व की कॉन्फ़िगरेशन को ओवरराइड करने के लिए किसी विशिष्ट तत्व पर 'ng-model-options' सेट भी कर सकते हैं। तो आप सामान्य पर वापस लाने के लिए चेकबॉक्स पर 'ng-model-options =" ​​{updateOn: 'default'} "' सेट कर सकते हैं। (कम से कम क्रोम में) – Joao

2
इसके बजाय

ng-model-options="{ updateOn: 'blur' } 

का उपयोग करने का

आप

ng-model-options="{ debounce : { default : 500 } }" 

का उपयोग करें और इस तरह के एक कंटेनर div के रूप में डोम, में एक माता पिता तत्व करने के लिए इसे लागू हो सकते हैं। उपरोक्त debounce सेटिंग एंगुलर को गतिविधि के 500 मिलीसेकंड के बाद सत्यापन नियमों का मूल्यांकन करने के लिए कहती है।

debounce का उपयोग करके blur का उपयोग करने के लिए यह तरीका बेहतर है क्योंकि ब्लर पूरे फॉर्म पर लागू होने पर रेडियो और चेकबॉक्स के लिए समस्याएं पैदा करता है।

डिबॉन्स विकल्प एक पूर्णांक मान है जो मॉडल अद्यतन को मिलीसेकंड की पूर्णांक संख्या में देरी का कारण बनता है। यह $digest चक्रों की आवृत्ति को कम करता है, जो जेएस अनुप्रयोग को कम संसाधनों का उपभोग करने के साथ-साथ सत्यापन नियम लागू होने से पहले उपयोगकर्ता को टाइप करने की इजाजत देता है।

YearOfMoo.com कलंक और debounce का उपयोग कर एक साथ इस

ng-model-options="{ debounce : { default : 500, blur : 0 } }" 

अब मॉडल मूल्य की तरह की सिफारिश और सत्यापन के बाद उपयोगकर्ता क्षेत्र से बाहर blurs तुरंत लागू होते हैं। यह धुंध घटना के लिए 0 एमएस का प्रतीक्षा समय निर्धारित करता है। ब्लर डिफ़ॉल्ट मान ओवरराइड करता है।

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