web-dev-qa-db-fra.com

Venez-vous poser des questions sur la répétition de AngularJS?

DEMO

L'encadrement de l'ordinateur est correct. ng-repeat. Supprimez les réponses à vos questions et des commentaires au sujet de l'acte d'accusation de scorrendo vers le bassiste pour vedettes et spectateurs.

Vous êtes le premier à être un joueur à la recherche d'un élément essentiel dans l'amélioration de la qualité de votre travail. Cliquez sur le lien ci-dessous pour afficher les notes de synthèse, cliquez ici pour en savoir plus sur les qualifications.

Vous avez déjà une bonne idée de ce que vous devez faire après que tout se passe?

PLAYGROUND HERE

30
Misha Moroshko

Il peut être résolu de manière assez élégante en utilisant la propriété scrollTop de div. J'ai utilisé deux directives - l'une gère la position de défilement de l'élément wrapper, l'autre enregistre de nouveaux éléments . Donnez-moi un cri si quelque chose n'est pas clair.

DEMO

JS:

.directive("keepScroll", function(){

  return {

    controller : function($scope){
      var element = null;

      this.setElement = function(el){
        element = el;
      }

      this.addItem = function(item){
        console.log("Adding item", item, item.clientHeight);
        element.scrollTop = (element.scrollTop+item.clientHeight+1);
       //1px for margin from your css (surely it would be possible
       // to make it more generic, rather then hard-coding the value)
      };

    },

    link : function(scope,el,attr, ctrl) {

     ctrl.setElement(el[0]);

    }

  };

})

.directive("scrollItem", function(){

  return{
    require : "^keepScroll",
    link : function(scope, el, att, scrCtrl){
      scrCtrl.addItem(el[0]);
    }
  }
})

HTML:

<div class="wrapper" keep-scroll>
  <div class="item" scroll-item ng-repeat="item in items  | orderBy: '-id'">
    {{ item.name }}
   </div>
</div>
30
artur grzesiak

Vous savez que d’autres personnes tentent de résoudre ce problème en utilisant une approche différente en termes d’interface utilisateur . Elles ne font pas que créer de nouveaux éléments, mais elles affichent un petit lien cliquable indiquant le nombre de nouveaux éléments ajoutés depuis sa dernière vérification.

[2 new items, Click here to refresh]

item 5
item 4
item 3

Découvrez comment Twitter résout ce problème .**[Let me attach a screenshot for you shortly.]**

Je sais que c’est un peu en contradiction avec ce que vous voulez, mais c’est peut-être mieux en termes d’UX? L’utilisateur veut savoir si de nouveaux éléments entrent.

7
fedmich

Vous pouvez faire défiler en fonction de la hauteur des éléments ajoutés

$scope.addNewItem = function() {
    var wrapper = document.getElementsByClassName('wrapper')[0];

    $scope.items = $scope.items.concat({
      id: $scope.items.length,
      name: "item " + $scope.items.length
    });
    // will fail if you observe the item 0 because we scroll before the view is updated;
    wrapper.scrollTop+=101; //height+margings+paddings
  };

J'utilise une mauvaise pratique pour accéder au DOM depuis le contrôleur. Une approche plus modulaire consisterait à créer une directive qui traitera tous les cas et modifiera la position du défilement après la mise à jour de la vue.

Démo sur http://jsbin.com/zofofapo/8/edit


Sinon, dans le cas où les éléments ne sont pas aussi hauts, vous pouvez voir combien de défilement il reste avant l'insertion et le redéfinir après l'insertion.

$scope.addNewItem = function() {
    var wrapper = document.getElementsByClassName('wrapper')[0],
        scrollRemaining = wrapper.scrollHeight - wrapper.scrollTop;

    $scope.items = $scope.items.concat({
      id: $scope.items.length,
      name: "item " + $scope.items.length
    });
    // will fail if you observe the item 0 because we scroll before the view is updated;
    $timeout(function(){
      wrapper.scrollTop = wrapper.scrollHeight - scrollRemaining;
    },0);
  };

Démo sur http://jsbin.com/zofofapo/9/edit

5

Vous êtes le premier à indiquer un texte intégral sur une copie du jugement de la personne qui est empêché de décider de l'indépendence de l'individu, de l'élément de base à l'autre: JS Bin

angular.module("Demo", [])

.controller("DemoCtrl", function($scope) {
  $scope.items = [];
  
  for (var i = 0; i < 10; i++) {
    $scope.items[i] = {
      id: i,
      name: 'item ' + i
    };
  }
  
  $scope.addNewItemTop = function() {
    $scope.items.unshift({
      id: $scope.items.length,
      name: "item " + $scope.items.length
    });
  };
  
  $scope.addNewItemMiddle = function() {
    $scope.items.splice(5, 0, {
      id: $scope.items.length,
      name: "item " + $scope.items.length
    });
  };
  
  $scope.addNewItemBottom = function() {
    $scope.items = $scope.items.concat({
      id: $scope.items.length,
      name: "item " + $scope.items.length
    });
  };
})

.directive("keepScroll", function(){
  
  return {

    controller : function($scope){
      var element = 0;
      
      this.setElement = function(el){
        element = el;
      };

      this.addItem = function(item){
        console.group("Item");
        console.log("OffsetTop: " + item.offsetTop);
        console.log("ScrollTop: " + element.scrollTop);
        
        if(item.offsetTop <= element.scrollTop) {
          console.log("Adjusting scorlltop position");
          element.scrollTop = (element.scrollTop+item.clientHeight+1); //1px for margin
        } else {
          console.log("Not adjusting scroll");
        }
        console.groupEnd("Item");
      };
      
    },
    
    link : function(scope,el,attr, ctrl) {
      
     ctrl.setElement(el[0]);
      
    }
    
  };
  
})

.directive("scrollItem", function(){
  
  
  return{
    require : "^keepScroll",
    link : function(scope, el, att, scrCtrl){
      scrCtrl.addItem(el[0]);
    }
  };
});
.wrapper {
  width: 200px;
  height: 300px;
  border: 1px solid black;
  overflow: auto;
  /* Required for correct offsetParent */
  position: relative; 
}
.item {
  background-color: #ccc;
  height: 100px;
  margin-bottom: 1px;
}
<!DOCTYPE html>
<html>
<head>
<script src="//code.angularjs.org/1.3.0-beta.7/angular.js"></script>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body ng-app="Demo" ng-controller="DemoCtrl">
  <div class="wrapper" keep-scroll>
    <div class="item" scroll-item ng-repeat="item in items">
      {{ item.name }}
    </div>
  </div>
  <button ng-click="addNewItemTop()">
    Add New Item Top
  </button>
  <button ng-click="addNewItemMiddle()">
    Add New Item Middle
  </button>
  <button ng-click="addNewItemBottom()">
    Add New Item Bottom
  </button>
</body>
</html>
4
VitalyB

Vous pouvez différer l'ajout des éléments jusqu'à ce que l'utilisateur fasse défiler le haut de la liste. Il est inutile de rendre les éléments avant. 

Cela pourrait ressembler à ceci (peut-être avec une animation ajoutée).

3
lyschoening

The FaceBook Way: Tout le monde le suggère, voici une pseudo-implémentation:

MON EXEMPLE

Au fur et à mesure que de nouveaux objets sont ajoutés, insérez-les dans une "file d'attente supplémentaire".

  <div style="height:15px">
      <button  ng-if="moreQueue"ng-click="transferWait()"> See More {{ moreQueue }}
      </button >
    </div>  
  <div class="wrapper">
    <div class="item" ng-repeat="item in items | orderBy: '-id'">
      {{ item.name }}
    </div>
  </div>

MessageHandlerController aura au moins 2 tableaux (nous devrions le considérer comme une file d'attente en b/c, nous le ferons apparaître de bas en haut.

  • Messages actifs
  • Messages en attente

Au fur et à mesure que votre Signal R/Service Bus remplit votre WaitingQueue, votre ng-if augmente sa taille et votre $scope.SizeOfWaitingQueue=SizeOfWaitingQueue(). Ce processus de réaffectation devrait avoir lieu à chaque itération afin que vous n'ayez pas à vérifier votre mémoire Plus taille Repo

2
Dave Alperovich

Vous devez ajouter une directive scrollspy à votre conteneur, qui met à jour sa position à chaque défilement utilisateur et reçoit une notification à chaque répétition du rendu afin qu'il puisse se repositionner lui-même à son état enregistré. votre html pourrait ressembler à ceci

<div scrollspy id="myscrollspy">
     <ul>
       <li ng-repeat="" notifyscroll></li>
     </ul>
</div>

l’espion de défilement aurait les paramètres de débordement css requis et scroll-x ou scroll-y pour garder une trace du défilement actuel et éviter de polluer la portée du message. devrait définir le scrool. 

ng-repeat pourrait notifier en attachant une nouvelle directive notifier le défilement qui lance un événement. Je ne sais pas si la version actuelle de Angular prend en charge l’événement Postrender.

la manière de positionner le parchemin dépendra de l'utilisation d'une bibliothèque tierce $ $ .scrollTop (pos) ou non. cela le fera ou devrait . espérons que cela aide

1

Vous pouvez résoudre ce problème avec ng-animate:

.animation('.keep-scroll', [function () {
    var keepScroll = function(element, leave){
        var elementPos = element.offset().top;
        var scrollPos = document.body.scrollTop;

        if(elementPos < scrollPos){
            var height = element[0].clientHeight;
            if(leave){
                height *= (-1);
            }
            document.body.scrollTop += height;
        }
    };

    return {
        enter: function (element, doneFn) {
            keepScroll(element);
            doneFn();
        },
        leave: function (element, doneFn) {
            keepScroll(element, true);
            doneFn();
        }
    };
}])

Attribuez simplement le .keep-scroll de la classe css à vos éléments répétés, comme ceci:

<div ng-repeat="item in items" class="keep-scroll">...</div>
0
Martin Cremer

Je pense qu’il n’ya que quelques solutions possibles

1) N'ajoutez pas l'item (comme dans l'autre réponse)

2) Ajoutez l'élément en bas pour que la liste ne bouge pas.

3) Ajoutez l’élément en haut et faites défiler l’écran automatiquement pour que la hauteur du nouvel élément soit prise en compte et que tout soit conservé comme avant. La liste se déplacera vers le bas, mais l'écran visible se déplacera également - de sorte que rien ne bougera. Eh bien, d’autres éléments qui ne font pas partie de la liste le seront, mais cela pourrait en fait avoir l’air plutôt sympa ...

0
NimChimpsky