99

model dizisinden eklendiğinde güncelleştirilmez İki denetleyicim var ve bir uygulama işleviyle aralarında veri paylaşıyorum.AngularJS: ng yineleme listesi, bir model öğesi

İlk denetleyici, bağlantı tıklandığında model dizisine (eklentilerDisplayed) bir widget ekler. eklendi (bu dizi içeriğini göstermek için ng tekrar kullanır) görünümüne dizi içine itilir ve bu değişiklik, yansıtılan:

<div ng-repeat="pluginD in pluginsDisplayed"> 
    <div k2plugin pluginname="{{pluginD.name}}" pluginid="{{pluginD.id}}"></div> 
</div> 

eklendi çıkarın ve yeniden boyutlandırma, üç direktifler k2plugin üzerine inşa edilmiştir. Kaldırma yönergesi, k2plugin yönergesinin şablonuna bir açıklık ekler. Söz konusu açıklık tıklandığında, paylaşılan diziye doğru eleman Array.splice() ile silinir. Paylaşılan dizi doğru şekilde güncelleştirildi, ancak değişiklik, görünümde yansıtılan değil . Ancak, başka bir öğe eklendiğinde, kaldırıldıktan sonra görünüm doğru şekilde yenilenir ve önceden silinmiş öğe gösterilmez.

Neyi yanlış anlayacağım? Bunun neden işe yaramadığını açıklar mısınız? AngularJS ile yapmaya çalıştığım şeyi yapmanın daha iyi bir yolu var mı?

<!doctype html> 
<html> 
    <head> 
     <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.min.js"> 
     </script> 
     <script src="main.js"></script> 
    </head> 
    <body> 
     <div ng-app="livePlugins"> 
      <div ng-controller="pluginlistctrl"> 
       <span>Add one of {{pluginList.length}} plugins</span> 
       <li ng-repeat="plugin in pluginList"> 
        <span><a href="" ng-click="add()">{{plugin.name}}</a></span> 
       </li> 
      </div> 
      <div ng-controller="k2ctrl"> 
       <div ng-repeat="pluginD in pluginsDisplayed"> 
        <div k2plugin pluginname="{{pluginD.name}}" pluginid="{{pluginD.id}}"></div> 
       </div> 
      </div> 
     </div> 
    </body> 
</html> 

Bu benim main.js geçerli::

Bu

benim index.html olan

var app = angular.module ("livePlugins",[]); 

app.factory('Data', function() { 
    return {pluginsDisplayed: []}; 
}); 

app.controller ("pluginlistctrl", function ($scope, Data) { 
    $scope.pluginList = [{name: "plugin1"}, {name:"plugin2"}, {name:"plugin3"}]; 
    $scope.add = function() { 
     console.log ("Called add on", this.plugin.name, this.pluginList); 
     var newPlugin = {}; 
     newPlugin.id = this.plugin.name + '_' + (new Date()).getTime(); 
     newPlugin.name = this.plugin.name; 
     Data.pluginsDisplayed.push (newPlugin); 
    } 
}) 

app.controller ("k2ctrl", function ($scope, Data) { 
    $scope.pluginsDisplayed = Data.pluginsDisplayed; 

    $scope.remove = function (element) { 
     console.log ("Called remove on ", this.pluginid, element); 

     var len = $scope.pluginsDisplayed.length; 
     var index = -1; 

     // Find the element in the array 
     for (var i = 0; i < len; i += 1) { 
      if ($scope.pluginsDisplayed[i].id === this.pluginid) { 
       index = i; 
       break; 
      } 
     } 

     // Remove the element 
     if (index !== -1) { 
      console.log ("removing the element from the array, index: ", index); 
      $scope.pluginsDisplayed.splice(index,1); 
     } 

    } 
    $scope.resize = function() { 
     console.log ("Called resize on ", this.pluginid); 
    } 
}) 

app.directive("k2plugin", function() { 
    return { 
     restrict: "A", 
     scope: true, 
     link: function (scope, elements, attrs) { 
      console.log ("creating plugin"); 

      // This won't work immediately. Attribute pluginname will be undefined 
      // as soon as this is called. 
      scope.pluginname = "Loading..."; 
      scope.pluginid = attrs.pluginid; 

      // Observe changes to interpolated attribute 
      attrs.$observe('pluginname', function(value) { 
       console.log('pluginname has changed value to ' + value); 
       scope.pluginname = attrs.pluginname; 
      }); 

      // Observe changes to interpolated attribute 
      attrs.$observe('pluginid', function(value) { 
       console.log('pluginid has changed value to ' + value); 
       scope.pluginid = attrs.pluginid; 
      }); 
     }, 
     template: "<div>{{pluginname}} <span resize>_</span> <span remove>X</span>" + 
         "<div>Plugin DIV</div>" + 
        "</div>", 
     replace: true 
    }; 
}); 

app.directive("remove", function() { 
    return function (scope, element, attrs) { 
     element.bind ("mousedown", function() { 
      scope.remove(element); 
     }) 
    }; 

}); 

app.directive("resize", function() { 
    return function (scope, element, attrs) { 
     element.bind ("mousedown", function() { 
      scope.resize(element); 
     }) 
    }; 
}); 

cevap

130

böyle bir Ajax arama yapıyor olarak angularjs, dış operasyon yapmak faydalı zaman jQuery veya bir olayı bir öğeye bağladığınız gibi burada AngularJS'in kendini güncellemesini bilmeniz gerekir. Eğer $scope.pluginsDisplayed.splice(index,1); o zaman çalışan bir $scope.$apply(); hemen sonra eklerseniz https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$apply

+4

Kapsamı uygulayabileceğinizi göz önünde bulundurun: scope.remove (öğe) ve scope.resize (öğe) $ ifadesine geçirilen bir ifade/işlev içinde hareket et. –

+1

@ PerHornshøj-Schierbeck Katılıyorum, aksi takdirde Angular meydana geldiğinde hataların farkında olmayacaktır. –

+2

dikkatli ol! normalde, Açısal döngü gerektiğinde digest döngüsünü çağırır ve $ apply elle çağırır. Genellikle elle çağırmak kötü bir uygulamadır, çünkü optimizasyon hataları yapabiliriz ve kaynak tüketebilir. – Alex

53

: Burada

app.directive("remove", function() { 
    return function (scope, element, attrs) { 
     element.bind ("mousedown", function() { 
      scope.remove(element); 
      scope.$apply(); 
     }) 
    }; 

}); 

app.directive("resize", function() { 
    return function (scope, element, attrs) { 
     element.bind ("mousedown", function() { 
      scope.resize(element); 
      scope.$apply(); 
     }) 
    }; 
}); 

üzerine dokümantasyon edilir: Burada yapmanız gereken kod değişikliğidir.

Bunun neden olduğundan emin değilim, ancak AngularJS, $ kapsamının değiştiğini bilmediğinde temel olarak $ manuel olarak başvurması gerekir. Ben de AngularJS için yeni değilim, bu daha iyi açıklayamıyorum. Daha fazla bakmam lazım.

Oldukça düzgün açıklayan this awesome article buldum. Not: "mousedown" öğesine bağlanmak yerine ng-click (docs) kullanmak daha iyi olabileceğini düşünüyorum. Ben AngularJS dayalı basit bir uygulama (http://avinash.me/losh, kaynak http://github.com/hardfire/losh) yazdım. Çok temiz değil, ama yardımcı olabilir.

7

Aynı sorunu yaşadım. Sorun, 'ng-controller' iki kez tanımlandı (yönlendirme ve HTML'de) idi.

0

Bunu yapmanın kolay bir yolu var. Çok kolay. Ben

$scope.yourModel = []; 

clonedObjects güncellenecektir bu

function deleteAnObjectByKey(objects, key) { 
    var clonedObjects = Object.assign({}, objects); 

    for (var x in clonedObjects) 
     if (clonedObjects.hasOwnProperty(x)) 
      if (clonedObjects[x].id == key) 
       delete clonedObjects[x]; 

    $scope.yourModel = clonedObjects; 
} 

$ scope.yourModel gibi yapabileceğimiz $ scope.yourModel dizi listesi kaldırır fark beri.

Bu yardımcı olur umarım.

İlgili konular