2013-06-05 16 views
13

पर निरंतर ऑब्जेक्ट को बाध्य करने के लिए मैंने "स्कोप" का उपयोग करके बाध्यकारी के साथ निर्देश बनाया है। कुछ मामलों में, मैं एक निरंतर वस्तु बांधना चाहता हूं।कोणीयजेएस: निर्देश

<div ng-controller="Ctrl"> 
    <greeting person="{firstName: 'Bob', lastName: 'Jones'}"></greeting> 
</div> 

और जावास्क्रिप्ट: उदाहरण के लिए, HTML के साथ के लिए

Error: 10 $digest() iterations reached. Aborting! 

(Fiddle demonstrating the problem)

क्या सही तरीका है:

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

app.controller("Ctrl", function($scope) { 

}); 

app.directive("greeting", function() { 
    return { 
     restrict: "E", 
     replace: true, 
     scope: { 
      person: "=" 
     }, 
     template: 
     '<p>Hello {{person.firstName}} {{person.lastName}}</p>' 
    }; 
}); 

हालांकि यह काम करता है, यह भी एक JavaScript त्रुटि का कारण बनता है त्रुटि उत्पन्न किए बिना निरंतर वस्तु को बांधने के लिए?

उत्तर

10

यहाँ समाधान मैं @ sh0ber के उत्तर के आधार पर के साथ आया था, है:

लागू एक कस्टम link कार्य करते हैं। यदि विशेषता वैध JSON है, तो यह निरंतर मान है, इसलिए हम केवल एक बार इसका मूल्यांकन करते हैं। अन्यथा, मान को सामान्य के रूप में देखें और अपडेट करें (दूसरे शब्दों में, = बाध्यकारी के रूप में व्यवहार करने का प्रयास करें)। यह सुनिश्चित करने के लिए कि निर्दिष्ट मूल्य केवल निर्देश के इस उदाहरण को प्रभावित करता है, scope को true पर सेट करने की आवश्यकता है।

(Example on jsFiddle)

HTML:

<div ng-controller="Ctrl"> 
    <greeting person='{"firstName": "Bob", "lastName": "Jones"}'></greeting> 
    <greeting person="jim"></greeting> 
</div> 

जावास्क्रिप्ट:

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

app.controller("Ctrl", function($scope) { 
    $scope.jim = {firstName: 'Jim', lastName: "Bloggs"}; 
}); 

app.directive("greeting", function() { 
    return { 
     restrict: "E", 
     replace: true, 
     scope: true, 
     link: function(scope, elements, attrs) { 
      try { 
       scope.person = JSON.parse(attrs.person); 
      } catch (e) { 
       scope.$watch(function() { 
        return scope.$parent.$eval(attrs.person); 
       }, function(newValue, oldValue) { 
        scope.person = newValue; 
       }); 
      } 
     }, 
     template: '<p>Hello {{person.firstName}} {{person.lastName}}</p>' 
    }; 
}); 
2

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

https://github.com/mgonto/angular.js/commit/09d19353a2ba0de8edcf625aa7a21464be830f02:

एक तरीका यह है कि दूर करने के लिए यहां दिए गए अनुसार के कोणीय स्रोत को संशोधित करने होंगे।

<div ng-controller="Ctrl"> 
    <greeting person="personObj"></greeting> 
</div> 

जे एस

app.controller("Ctrl", function($scope) 
{ 
    $scope.personObj = { firstName : 'Bob', lastName : 'Jones' }; 
}); 

फिर भी एक और

HTML:

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

<div ng-controller="Ctrl" ng-init="personObj = { firstName : 'Bob', lastName : 'Jones' }"> 
    <greeting person="personObj"></greeting> 
</div> 
6

क्योंकि कोणीय अभिव्यक्ति हर बार मूल्यांकन कर रही है आप उस त्रुटि हो रही है। '=' परिवर्तनीय नामों के लिए है।

त्रुटि के बिना एक ही विचार को प्राप्त करने के दो वैकल्पिक तरीके यहां दिए गए हैं।

पहले समाधान:

app.controller("Ctrl", function($scope) { 
    $scope.person = {firstName: 'Bob', lastName: 'Jones'}; 
}); 

app.directive("greeting", function() { 
    return { 
     restrict: "E", 
     replace: true, 
     scope: { 
      person: "=" 
     }, 
     template: 
     '<p>Hello {{person.firstName}} {{person.lastName}}</p>' 
    }; 
}); 

<greeting person="person"></greeting> 

दूसरा समाधान:

app.directive("greeting2", function() { 
    return { 
     restrict: "E", 
     replace: true, 
     scope: { 
      firstName: "@", 
      lastName: "@" 
     }, 
     template: 
     '<p>Hello {{firstName}} {{lastName}}</p>' 
    }; 
}); 

<greeting2 first-name="Bob" last-Name="Jones"></greeting2> 

http://jsfiddle.net/7bNAd/82/

+1

उत्तर के लिए धन्यवाद। दुर्भाग्य से, दूसरा समाधान संभव नहीं है क्योंकि मैं जिस वास्तविक डेटा का उपयोग कर रहा हूं वह गहराई से घोंसला है। पहला मामला संभव है लेकिन कुछ हद तक गन्दा है क्योंकि निर्देशों के निरंतर मानों के साथ उपयोग किए जाने वाले निर्देशों के कई उदाहरण हैं (वे सर्वर-साइड उत्पन्न होते हैं)। –

0

मैं नहीं विशेष रूप से eval() का उपयोग कर, लेकिन इस के साथ काम करने यदि आप वास्तव में प्राप्त करना चाहते हैं की तरह आपके द्वारा प्रदान किया गया HTML:

app.directive("greeting", function() { 
    return { 
     restrict: "E", 
     compile: function(element, attrs) { 
      eval("var person = " + attrs.person); 
      var htmlText = '<p>Hello ' + person.firstName + ' ' + person.lastName + '</p>'; 
      element.replaceWith(htmlText); 
     } 
    }; 
}); 
4

एक अन्य विकल्प:

app.directive("greeting", function() { 
    return { 
     restrict: "E", 
     link: function(scope,element,attrs){ 
      scope.person = scope.$eval(attrs.person); 
     }, 
     template: '<p>Hello {{person.firstName}} {{person.lastName}}</p>' 
    }; 
}); 
0

मैं एक ही समस्या थी, मैं संकलन चरण में json पार्स करने से इसे हल:

angular.module('foo', []). 
directive('myDirective', function() { 
    return { 
     scope: { 
      myData: '@' 
     }, 
     controller: function ($scope, $timeout) { 
      $timeout(function() { 
       console.log($scope.myData); 
      }); 
     }, 
     template: "{{myData | json}} a is {{myData.a}} b is {{myData.b}}", 
     compile: function (element, attrs) { 
      attrs['myData'] = angular.fromJson(attrs['myData']); 
     } 
    }; 
}); 

एक दोष यह है कि $scope प्रारंभ में आबादी नहीं है जब नियंत्रक पहले चलता है।

यहां इस कोड के साथ JSFiddle है।

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