2013-02-18 18 views
6

मूल रूप से मेरे ऐप में, मैंने यूआरएल ($ रूट पैराम्स) से ऑब्जेक्ट की आईडी प्राप्त करके संसाधन प्राप्त करने के लिए बहुत ही बुनियादी $ http कॉल के साथ नियंत्रक बनाए। Ng-repeat परिणाम सही ढंग से प्रदर्शित करते हैं।सेवा से डेटा के साथ AngularJS ng-repeat

हालांकि, मैंने देखा कि बाद के दृश्य में रीफ्रेशिंग (विभिन्न नियंत्रक) ने डेटा मिटा दिया और पृष्ठ तोड़ दिया। इसलिए, मैंने यह जांचने के लिए कि डेटा उपलब्ध है या नहीं, इस पर प्रतिक्रिया करने के लिए मैंने कई नियंत्रकों में उपयोग की जाने वाली सेवा पर एक फ़ंक्शन बनाया है:

1) यदि संसाधन परिभाषित किया गया है, तो इसे वापस करें (कोई एपीआई कॉल नहीं) 2) यदि संसाधन परिभाषित नहीं किया गया है, तो आईडी को यूआरएल से प्राप्त करें और इसे एपीआई से प्राप्त करें 3) यदि संसाधन & परिभाषित नहीं किया गया है तो आप आईडी नहीं प्राप्त कर सकते हैं, बस झूठी वापसी करें।

हालांकि, इसने कोड तोड़ दिया: सेवा से पहले प्रस्तुत टेम्पलेट डेटा लौटा, और एनजी-दोहराना अद्यतन नहीं हुआ। कोड इस तरह दिखता है:

angular.module('myApp', ['ngCookies']) 
    .config(...) 
    .service('myService', ['$cookies', '$http', function($cookies, $http) { 
     myData = {}; 

     return { 
      getData:function(dataID) { 
       if(myData.name) {return myData); 
       else if (dataID && dataID !== '') { 
        $http.get('/api/data/' + dataID) 
         .success(function(data) { 
          myData = data.object; 
          $cookies.dataID = data.object.id; 
          return myData; 
         } 
       } 
       else { return false; } 
      } 
     } 
    }]); 

function myCtrl($scope, $http, $routeParams, myService) { 
    $scope.data = myService.getData($routeParams.dataID); 

    ... 
} 

और यहां टेम्पलेट है। यह जेड में है, जिसका अर्थ है कोण ब्रैकेट्स के बजाय, आप केवल तत्व को ब्रांड्स के साथ पैरामीटर के साथ सूचीबद्ध करते हैं, और ब्रांड्स के बाद सामग्री।

h2 My heading 
ul 
    li(ng-repeat='option in data') 
     a(href="#", ng-click='someFuncInCtrl(option.name)') {{ option.name }} 

जब नियंत्रक $ http.get ही है, एनजी-दोहराने ठीक काम किया क्योंकि $ गुंजाइश ".success" कॉलबैक में अद्यतन किया गया था था। अब एक ऐसी सेवा है जो थोड़ी देर के बाद डेटा लौटाती है, "$ scope.data" अभी अपरिभाषित है, एनजी-दोहराना सूची खाली है।

मैंने "myData वापस लौटने" से पहले myData को ठीक करने के लिए एक कंसोल.लॉग का उपयोग किया, और मेरा डेटा काम कर रहा है, यह समय पर वापस नहीं आया है, और किसी भी कारण से जब भी $ स्कोप प्राप्त नहीं होता है तो सूची अपडेट नहीं हो रही है आँकड़े।

मैंने $ रूटप्रोवाइडर का हल करने का उपयोग किया ... लेकिन यह यूआरएल चुनौतीपूर्ण से आईडी प्राप्त कर रहा है, क्योंकि संकल्प ऑब्जेक्ट को रूट मार्ग तक पहुंच नहीं लगती है। मुझे पता है कि $ गुंजाइश है। $ लागू होता है जब यह बाहरी कार्यों द्वारा बदला जाता है तो स्कोप को अपडेट करने में मदद करता है ... लेकिन मुझे कोई संकेत नहीं है कि इसे कहां रखा जाए। एसओ पर most similar problem ने सेवा का उपयोग नहीं किया था।

मैंने कोशिश की:

$scope.$apply($scope.data = myService.getData($routeParams.dataID)); 

और

$scope.$apply(function() { 
    $scope.data = myService($routeParams.dataID); 
}); 

दोनों बार मैं केवल त्रुटि मिला: $ पहले से प्रगति को पचाने।

+0

कोणीय डॉक्स साइट पर ट्यूटोरियल में 'शोकहारा service' दृष्टिकोण की कोशिश करना चाहते हो सकता है। एक वादा देता है। http://docs.angularjs.org/tutorial/step_11 – charlietfl

उत्तर

11

समस्या जिस तरह से आप सेवा के साथ बातचीत करते हैं। चूंकि आपका getData फ़ंक्शन दोनों सिंक्रोनस और/या एसिंक्रोनस जानकारी लौटा सकता है, इसलिए आप सामान्य return (ओं) का उपयोग नहीं कर सकते हैं।

$http.get('/api/data/' + dataID) 
    .success(function(data) { 
     myData = data.object; 
     $cookies.dataID = data.object.id; 
     return myData; 
    }); 

return ऊपर टुकड़ा getData से कुछ भी वापस नहीं होगा, क्योंकि यह (और नहीं getData कॉल स्टैक पर) $http.get सफलता कॉलबैक के संदर्भ पर निष्पादित किया जाएगा पर।

सिंक और एसिंक सेवा अनुरोधों को संभालने के लिए सबसे अच्छा तरीका promises का उपयोग करना है।

आपका getData समारोह कुछ इस तरह दिखना चाहिए:

getData:function(dataID) { 
    var deferred = $q.defer(); 
    if(myData.name) { 
     deferred.resolve(myData); 
    } else if (dataID && dataID !== '') { 
     $http.get('/api/data/' + dataID) 
      .success(function(data) { 
       myData = data.object; 
       $cookies.dataID = data.object.id; 
       deferred.resolve(myData); 
       // update angular's scopes 
       $rootScope.$$phase || $rootScope.$apply(); 
      }); 
    } else { 
     deferred.reject(); 
    } 

    return deferred.promise; 
} 

ध्यान दें: आप अपनी सेवा पर $rootScope इंजेक्षन की जरूरत है।

और अपने नियंत्रक पर:

function myCtrl($scope, $http, $routeParams, myService) { 
    myService.getData($routeParams.dataID).then(function(data) { 
     // request was successful 
     $scope.data = data;   
    }, function() { 
     // request failed (same as your 'return false') 
     $scope.data = undefined; 
    }); 
} 
+0

धन्यवाद एक टन। सेवा में $ q इंजेक्शन भी लगाया। एक जादू की तरह काम किया। – ansorensen

+0

धन्यवाद, धन्यवाद! मुझे अपनी स्थगित करने के बाद कोणीय के स्कॉप्स को अपडेट करने के लिए मेरी सेवा में $ रूटस्कोप इंजेक्ट करने की आवश्यकता है ($ रूटस्कोप के माध्यम से। $$ चरण || $ rootScope। $ लागू करें()) – remi

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