एक कस्टम निर्देश के अंदर मूल्यांकन विशेषताओं को कैसे प्राप्त करें


363

मैं अपने कस्टम निर्देशन से एक मूल्यांकित विशेषता प्राप्त करने की कोशिश कर रहा हूँ , लेकिन मुझे इसे करने का सही तरीका नहीं मिल रहा है।

मैंने इस jsFiddle को विस्तृत करने के लिए बनाया है ।

<div ng-controller="MyCtrl">
    <input my-directive value="123">
    <input my-directive value="{{1+1}}">
</div>

myApp.directive('myDirective', function () {
    return function (scope, element, attr) {
        element.val("value = "+attr.value);
    }
});

मैं क्या खो रहा हूँ?


निर्देशों के बारे में बेहतर समझ के लिए आप नीचे दिए गए लिंक का अनुसरण कर सकते हैं। undefinednull.com/2014/02/11/…
प्रसन्ना सासने

जवाबों:


573

सूचना: मैं इस उत्तर को अपडेट करता हूं क्योंकि मुझे बेहतर समाधान मिलते हैं। जब तक वे संबंधित रहेंगे तब तक मैं भविष्य के संदर्भ के लिए पुराने उत्तर भी रखूंगा। नवीनतम और सबसे अच्छा जवाब पहले आता है।

बेहतर जवाब:

कोणीयज में निर्देश बहुत शक्तिशाली हैं, लेकिन यह समझने में समय लगता है कि कौन सी प्रक्रिया उनके पीछे पड़ी है।

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

बाध्यकारी प्रकार के 3 विकल्प हैं जिन्हें आप दायरे में परिभाषित कर सकते हैं और आप उन्हें उपसर्ग संबंधित विशेषता के रूप में लिख सकते हैं।

angular.module("myApp", []).directive("myDirective", function () {
    return {
        restrict: "A",
        scope: {
            text: "@myText",
            twoWayBind: "=myTwoWayBind",
            oneWayBind: "&myOneWayBind"
        }
    };
}).controller("myController", function ($scope) {
    $scope.foo = {name: "Umur"};
    $scope.bar = "qwe";
});

एचटीएमएल

<div ng-controller="myController">
    <div my-directive my-text="hello {{ bar }}" my-two-way-bind="foo" my-one-way-bind="bar">
    </div>
</div>

उस मामले में, निर्देश के दायरे में (चाहे वह लिंकिंग फ़ंक्शन या नियंत्रक में हो), हम इन गुणों को इस तरह एक्सेस कर सकते हैं:

/* Directive scope */

in: $scope.text
out: "hello qwe"
// this would automatically update the changes of value in digest
// this is always string as dom attributes values are always strings

in: $scope.twoWayBind
out: {name:"Umur"}
// this would automatically update the changes of value in digest
// changes in this will be reflected in parent scope

// in directive's scope
in: $scope.twoWayBind.name = "John"

//in parent scope
in: $scope.foo.name
out: "John"


in: $scope.oneWayBind() // notice the function call, this binding is read only
out: "qwe"
// any changes here will not reflect in parent, as this only a getter .

"फिर भी ठीक है" उत्तर:

चूंकि यह उत्तर स्वीकार कर लिया गया है, लेकिन कुछ मुद्दे हैं, मैं इसे बेहतर तरीके से अपडेट करने जा रहा हूं। जाहिरा तौर पर, $parseएक ऐसी सेवा है जो वर्तमान दायरे के गुणों में झूठ नहीं है, जिसका अर्थ है कि यह केवल कोणीय अभिव्यक्ति लेता है और गुंजाइश तक नहीं पहुंच सकता है। भावों को संकलित करते समय संकलित किया जाता है {{, }}जिसका अर्थ है कि जब हम अपने निर्देशों की postlinkपद्धति में उन्हें एक्सेस करने का प्रयास करते हैं, तो वे पहले से ही संकलित होते हैं। ( {{1+1}}है 2पहले से ही निर्देश में)।

यह आप कैसे उपयोग करना चाहते हैं:

var myApp = angular.module('myApp',[]);

myApp.directive('myDirective', function ($parse) {
    return function (scope, element, attr) {
        element.val("value=" + $parse(attr.myDirective)(scope));
    };
});

function MyCtrl($scope) {
    $scope.aaa = 3432;
}​

<div ng-controller="MyCtrl">
    <input my-directive="123">
    <input my-directive="1+1">
    <input my-directive="'1+1'">
    <input my-directive="aaa">
</div>​​​​​​​​

एक बात जो आपको यहाँ देखनी चाहिए वह यह है कि, यदि आप मान स्ट्रिंग सेट करना चाहते हैं, तो आपको इसे उद्धरणों में लपेटना चाहिए। (तीसरा इनपुट देखें)

यहाँ खेलने के लिए पहेली है : http://jsfiddle.net/neuTA/6/

पुराना उत्तर:

मैं उन लोगों के लिए इसे नहीं हटा रहा हूं जिन्हें मेरी तरह गुमराह किया जा सकता है, ध्यान दें कि इसका उपयोग करने $evalका सही तरीका बिल्कुल ठीक है, लेकिन $parseएक अलग व्यवहार है, आपको ज्यादातर मामलों में उपयोग करने के लिए संभवतः इसकी आवश्यकता नहीं होगी।

इसे करने का तरीका, एक बार फिर से, का उपयोग करना है scope.$eval। न केवल यह कोणीय अभिव्यक्ति को संकलित करता है, इसमें वर्तमान क्षेत्र के गुणों तक भी पहुंच है।

var myApp = angular.module('myApp',[]);

myApp.directive('myDirective', function () {
    return function (scope, element, attr) {
        element.val("value = "+ scope.$eval(attr.value));
    }
});

function MyCtrl($scope) {

}​

आप जो याद कर रहे थे वह था $eval

http://docs.angularjs.org/api/ng.$rootScope.Scope#$eval

परिणाम लौटाने वाले मौजूदा दायरे पर अभिव्यक्ति का निष्पादन करता है। अभिव्यक्ति में कोई भी अपवाद प्रचारित (अनकैप्ड) है। कोणीय अभिव्यक्तियों का मूल्यांकन करते समय यह उपयोगी है।


उत्तर के लिए धन्यवाद, हालांकि यह समाधान नहीं है। मैंने आपके कोड के साथ फिडेल को अपडेट किया है। jsfiddle.net/neuTA/3
श्लोमी श्वार्ट्ज

Chrome में मुझे यह त्रुटि तब आती है जब स्कोप का उपयोग करने की कोशिश की जाती है। $ parse: Object # <Object> का कोई तरीका '$ parse' नहीं है। अगर मैं $ पार्स सर्विस - फंक्शन ($ parse) {रिटर्न फंक्शन (स्कोप ... - तो कोशिश करूँ: "value =" + $ parse (attr.value) - कि मेरे लिए काम नहीं लगता या तो।
मार्क रजक

@ आप सही हैं, अजीब है यह फेल्ड उदाहरण ( jsfiddle.net/neuTA/4 ) में काम करता है, लेकिन मेरे पास कोड में नहीं ... कोणीय संस्करण?
श्लोमी श्वार्ट्ज

2
"बेहतर उत्तर" अनुभाग $scope.textमें, लिंकिंग फ़ंक्शन में अपरिभाषित किया जाएगा। वर्तमान में जिस तरह से उत्तर दिया गया है, ऐसा लगता है कि यह अपरिभाषित नहीं होगा। आपको अन्तर्निर्मित मूल्य को देखने के लिए एसिंक्रोनस रूप से $ अवलोकन () (या $ वॉच () वास्तव में यहां भी काम करेगा) का उपयोग करना होगा। मेरा जवाब देखें और साथ ही stackoverflow.com/questions/14876112/…
मार्क राजकोक

1
में "फिर भी ठीक है" उत्तर ऐसा लगता है $parseसेवा इंजेक्ट किया जाता है और फिर इस्तेमाल कभी नहीं किया। क्या मैं कुछ भूल रहा हूँ?
सुपरजोस

83

एक विशेषता मान के लिए एक निर्देश में प्रक्षेपित होने की आवश्यकता होती है जो एक अलग दायरे का उपयोग नहीं कर रहा है, जैसे;

<input my-directive value="{{1+1}}">

गुण का उपयोग करें $observe:

myApp.directive('myDirective', function () {
  return function (scope, element, attr) {
    attr.$observe('value', function(actual_value) {
      element.val("value = "+ actual_value);
    })
 }
});

से निर्देश पेज,

प्रक्षेपित विशेषताओं का अवलोकन: उन विशेषताओं $observeके मूल्य परिवर्तनों का निरीक्षण करने के लिए उपयोग करें , जिनमें प्रक्षेप (जैसे src="{{bar}}") हैं। न केवल यह बहुत कुशल है, बल्कि वास्तविक मूल्य को आसानी से प्राप्त करने का एकमात्र तरीका है क्योंकि लिंकिंग चरण के दौरान प्रक्षेप का मूल्यांकन अभी तक नहीं किया गया है और इसलिए इस समय मूल्य निर्धारित है undefined

यदि विशेषता मान सिर्फ एक स्थिर है, उदाहरण के लिए,

<input my-directive value="123">

यदि मूल्य एक संख्या या बूलियन है, और आप सही प्रकार चाहते हैं, तो आप $ eval का उपयोग कर सकते हैं :

return function (scope, element, attr) {
   var number = scope.$eval(attr.value);
   console.log(number, number + 1);
});

यदि विशेषता मान एक स्ट्रिंग स्थिर है, या आप अपने निर्देश में स्ट्रिंग प्रकार होना चाहते हैं, तो आप इसे सीधे एक्सेस कर सकते हैं:

return function (scope, element, attr) {
   var str = attr.value;
   console.log(str, str + " more");
});

हालांकि, आपके मामले में, चूंकि आप प्रक्षेपित मूल्यों और स्थिरांक का समर्थन करना चाहते हैं, उपयोग करें $observe


क्या यह एकमात्र समाधान था जो आपने पाया?
श्लोमी श्वार्ट्ज

4
हां, और चूंकि निर्देश पृष्ठ इस दृष्टिकोण की सिफारिश करता है, यह है कि मैं यह कैसे करूंगा।
मार्क राजकोक

7
+1, यह सबसे अच्छा उत्तर IMO है क्योंकि यह निर्देश पर एक गुंजाइश को बाध्य नहीं करता है और $ अवलोकन के साथ विशेषता परिवर्तनों को भी शामिल करता है
BiAiB

4

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

my-directive-name="['string1', 'string2']"

उस स्थिति में, आप पीछा कर सकते हैं और बस एक अच्छे मूल का उपयोग कर सकते हैं angular.$eval(attr.attrName)

element.val("value = "+angular.$eval(attr.value));

वर्किंग फिडल


मुझे नहीं पता कि आपने एक पुराने कोणीय संस्करण का उपयोग किया है या नहीं, लेकिन आपके सभी कोड नमूने या तो अमान्य जावास्क्रिप्ट (मेरे निर्देश-नाम =) या अमान्य कोणीय (कोणीय। $ eval मौजूद नहीं है), इसलिए -1।
BiAiB

उम्म्म्म ... यह देखते हुए कि यह पद एक वर्ष से अधिक पुराना है, यह सब आश्चर्यचकित नहीं होगा यदि कुछ पदावनत किए गए थे। हालाँकि, 10-सेकंड की Google खोज से आपको $ eval पर बहुत सारी सामग्री मिल जाएगी, जिसमें SO पर यहीं शामिल है । और आपके द्वारा उद्धृत अन्य उदाहरण HTML में एक आह्वान है, जावास्क्रिप्ट नहीं।
एक्सएमएल

$ गुंजाइश। $ eval (attr.val) कोणीय 1.4 में काम करता है। निर्देश लिंक फ़ंक्शन में इंजेक्ट होने के लिए $ गुंजाइश की आवश्यकता होती है।
मार्टिन कॉनेल

4

उसी समाधान के लिए मैं देख रहा था Angularjs directive with ng-Model
यहाँ कोड है जो समस्या को हल करता है।

    myApp.directive('zipcodeformatter', function () {
    return {
        restrict: 'A', // only activate on element attribute
        require: '?ngModel', // get a hold of NgModelController
        link: function (scope, element, attrs, ngModel) {

            scope.$watch(attrs.ngModel, function (v) {
                if (v) {
                    console.log('value changed, new value is: ' + v + ' ' + v.length);
                    if (v.length > 5) {
                        var newzip = v.replace("-", '');
                        var str = newzip.substring(0, 5) + '-' + newzip.substring(5, newzip.length);
                        element.val(str);

                    } else {
                        element.val(v);
                    }

                }

            });

        }
    };
});


HTML DOM

<input maxlength="10" zipcodeformatter onkeypress="return isNumberKey(event)" placeholder="Zipcode" type="text" ng-readonly="!checked" name="zipcode" id="postal_code" class="form-control input-sm" ng-model="patient.shippingZipcode" required ng-required="true">


मेरा परिणाम है:

92108-2223

2
var myApp = angular.module('myApp',[]);

myApp .directive('myDirective', function ($timeout) {
    return function (scope, element, attr) {
        $timeout(function(){
            element.val("value = "+attr.value);
        });

    }
});

function MyCtrl($scope) {

}

$ Timeout का उपयोग करें क्योंकि डोम लोड के बाद निर्देश कॉल ताकि आपके परिवर्तन लागू न हों

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.