2014-09-12 54 views
7

'u bir CSV dosyası yüklemeye yardımcı olan bir yönerge oluşturmama rağmen "$ apply devam ediyor" hatası alıyorum. Bunu yapmak için <input type="file" ng-hide="true"/> ve yerel JavaScript FileReader() kullanıyorum. Yerel input kullanarak dosyayı seçtiğimde her şey iyi çalışıyor, ancak kendi "Gözat" düğmesini kullanarak dosya denetimini özelleştirmeye çalıştım. Sorun şu ki, bu şekilde yapmaya çalıştığımda, $ uygulamamın halihazırda ilerleme hatası olduğunu anladım. Ben trigger('click') uploadControl için "Gözat" düğmesini kullandığınızda İşte

benim yönergesi

app.directive('skUploader', function ($timeout) { 
    return { 
     restrict: 'A', 
     replace: true, 
     template: '<div>\ 
        <input type="file" class="uploadControl" ng-hide="false" />\ 
        <input type="text" ng-model="selectedFile" />\ 
        <button type="button" class="btnPlain" ng-click="triggerBrowse()">Browse</button>\ 
        <button type="button" class="btnOrange fRight" ng-click="uploadCSV()">Upload</button>\ 
        <button type="button" class="btnPlain fRight" ng-click="cancel()">Cancel</button>\ 
        </div>', 
     link: function (scope, elem, attr, ctrl) { 

      var uploadControl = elem.find('input[type=file]'); 
      var payload = null; 

      var type = attr.skUploader; 
      scope.selectedFile = null; 

      scope.uploadCSV = function() { 
       $timeout(function() { 
        alert('Upload Successful'); 
       }, 3000); 
      } 

      scope.cancel = function() { 
       payload = null; 
       scope.selectedFile = null; 
       scope.model.showUploadPanel = false; 

      } 

      uploadControl.on('change',function() { 
       var fileHandle = uploadControl[0].files[0]; 
       var reader = new FileReader(); 
       var buffer; 

       scope.selectedFile = fileHandle.name; 

       reader.onload = function(){ 
        buffer = reader.result; 

        payload = parseCSV(buffer); 

        if (payload) { 
         // Make API call 
         if (type == 'mapping') { 
          console.log(payload); 
         } else { 

         } 
        } 
       } 

       if (fileHandle.name.indexOf('.csv') > 0) { 
        reader.readAsText(fileHandle); 
       } else { 

       } 

       }); 

      function parseCSV(buff){ 

       var entries = []; 
       entries = buff.split(/\n/); 

       var json = []; 


       if (type == 'mapping') { 
        var formatter = { 
         iRowNumber: null, 
         SourceName: null, 
         DestName: null 
        }; 
       } else if (type == 'passwords') { 
        var formatter = { 
         iRowNumber: null, 
         SourceCreds: { 
          EmailAddress: null, 
          Username: null, 
          Pwd: null 
         } 
        }; 
       } else { 
        return null; 
       } 


       for(var i = 1; i < entries.length - 1; i++){ 
        var split = entries[i].split(','); 

        var obj = angular.copy(formatter); 

        var j = 0; 
        angular.forEach(formatter, function (value, key) { 
         if (key == 'iRowNumber') { 
          obj[key] = i; 
         } else if (key == 'SourceCreds') { 
          obj[key] = { 
           EmailAddress: split[0], 
           Username: split[1], 
           Pwd: split[2] 
          }; 
         }else{ 
          obj[key] = split[j]; 
          j++; 
         } 
        }); 

        json.push(obj); 

       } 

       return json; 

      } 

      scope.triggerBrowse = function() { 
       uploadControl.trigger('click'); // THIS IS WHAT CAUSES THE ERROR 
      } 
     } 
    }; 
}); 

olduğunu Açısal hata

Error: [$rootScope:inprog] $apply already in progress 

tükürür Ama hiçbir yere yüzden yapamam scope.$apply() kullanmıyorum problemi çöz. OS yerli dosya gezgini getirmesi gereken <input type="file"/>'daki tıklama olayını tetiklemelidir.

Güncelleme

o this issue ilgili bir şey olabilir mi? vojta (çekirdek angularjs dev) bir $timeout olay sarmak gerekir diyerek yanıtladı Ben this Git issue buldum biraz daha araştırmadan sonra

Güncelleme 2

. Bunu yaptım ve aslında işe yaradı! Birisi bana bunun neden detaylı bir şekilde gerekli olduğunu açıklayabilir mi? Teşekkürler

+0

Lütfen kapsamı kullanmayı deneyebilirsiniz: $ apply (function() {// Burada kapsamı güncelleştiren fb wrap}) –

+0

$ Zaman aşımı kullandığınızda, dahili olarak $ https://groups.google.com/ adresine başvurun. forumu/#! msg/angular/KFEIbI9C-0Q/p_RLAm6SgPQJ –

+0

Tamam ama neden $ timeout kullanarak bu sorunu düzeltiyor –

cevap

24

Angular'ın işlevlerini kullanmadan kapsamda değişiklikler yaptığınızda (örneğin, ngClick yerine jQuery tıklama olay işleyicisi kullanarak) çok huysuz olur. Bazen değişikliklerinizi başka bir başvuruda bulunana kadar görmezden gelir ve bazen de diğer şeylerle meşgul olduğunda özellikle de çok tuhaf bir anda onu yakalarsınız ve size sahip olduğunuz hatayı verir.

Köşeli dost olmak için, kapsamı güncellemek üzere olay sistemini kullanmanız gerekir. Bunu yapamazsanız, değişiklik yaptığınızı söyleyebilmenin bir yolu vardır, böylece bu değişikliklerle kendi programında ilgilenebilir. Bu şekilde, $timeout - JavaScript'in timeout'un açısal dostu sürümü, güncelleme döngüsü ile entegre edilmiştir. Bir süre parametresi olmadan çağrı yapmak, "Bir dahaki sefer kapsamda değişiklik yapmaya hazır olduğunuzda, bu şeyleri yapıyor" anlamına gelir.

$apply numaralı telefonu aramanız iyi bir fikir değil, bu arada sadece $timeout numaralı telefonu kullanın.

+4

+1 doğru terminoloji kullanımı için "huysuz" :) –