javascript - spipr - squelette spip




déplacer vers le haut et vers le bas des éléments dans une sélection multiple ne fonctionne pas (2)

Démo

Vous devez mettre à jour votre implémentation swapIf afin qu'elle permute le modèle, et non les options de la vue:

function swapIf(sel,i1,i2) {
    if ( ! select[i1].selected && select[i2].selected) {

        var obj1 = $scope.peoples[i1];
        var obj2 = $scope.peoples[i2];
        $scope.peoples[i2] = obj1;
        $scope.peoples[i1] = obj2;
        select[i1].selected = true;
        select[i2].selected = false;
    }
}

En outre, supprimez orderBy dans la vue et initialisez la commande dans le contrôleur à l'aide du service $filter . La raison pour laquelle vous devez le faire est que la liste est réorganisée chaque fois que l'utilisateur clique sur le bouton haut / bas.

J'ai créé une application angularjs avec plusieurs sélection sur lequel je suis en haut et en bas du bouton, dans lequel lorsque je clique sur le bouton haut et bas le mouvement correspondant des éléments doit être fait dans le multiple sélectionner, j'ai un exemple de choses qui a été fait avec javascript normal qui fait la chose similaire correctement comme montré dans ce violon , mais quand j'ai essayé d'implémenter la même chose dans AngularJS son ne fonctionne pas correctement

Quelqu'un peut-il s'il vous plaît me dire une solution pour cette

Mon code est comme indiqué ci-dessous

JSFiddle

html

<div ng-app='myApp' ng-controller="ArrayController">
    <select id="select" size="9" ng-model="persons" ng-options="item as item.name for item in peoples | orderBy:'name'" multiple></select>
    <br/>
    <button ng-click="moveUp()">Up</button>
    <br/>
    <button ng-click="moveDown()">Down</button>
    <br/>
</div>

scénario

var app = angular.module('myApp', []);
app.controller('ArrayController', function ($scope) {
    $scope.peoples = [{
        name: 'Jacob'
    }, {
        name: 'Sunny'
    }, {
        name: 'Lenu'
    }, {
        name: 'Mathew'
    }, {
        name: 'Ferix'
    }, {
        name: 'Kitex'
    }];

    $scope.moveUp = function () {
        var select = document.getElementById("select");
        var i1=0, i2=1;
        while (i2 < select.options.length) {
            swapIf(select,i1++,i2++);
        }
    };

    $scope.moveDown = function () {
        var select = document.getElementById("select");
        var i1=select.options.length-1, i2=i1-1;
        while (i1 > 0) {
            swapIf(select,i1--,i2--);
        }
    };

    var swapVar = '';
    function swapIf(sel,i1,i2) {
        if ( ! select[i1].selected && select[i2].selected) {
            swapVar = select[i2].text;
            select[i2].text = select[i1].text;
            select[i1].text = swapVar;
            swapVar = select[i2].value;
            select[i2].value = select[i1].value;
            select[i1].value = swapVar;
            select[i1].selected = true;
            select[i2].selected = false;
        }
    }
});

persons retourneront un tableau de tous les éléments sélectionnés dans la liste. Une solution consiste à créer une boucle for qui récupère l' indexOf de chaque élément dans le tableau persons . splice éléments hors du tableau des peoples , incrémentez / décrémentez l'index et splice le au tableau peoples .

Voici une nouvelle fonction moveUp() qui peut déplacer plusieurs éléments sélectionnés:

   $scope.moveUp = function () {
        for(var i = 0; i < $scope.persons.length; i++) {
            var idx = $scope.peoples.indexOf($scope.persons[i])
            console.log(idx);
            if (idx > 0) {
                var itemToMove = $scope.peoples.splice(idx, 1)
                console.log(itemToMove[0])
                $scope.peoples.splice(idx-1, 0, itemToMove[0]);

            }
        }
    };

Voici la fonction moveDown() mise à jour:

   $scope.moveDown = function () {
        for(var i = 0; i < $scope.persons.length; i++) {
            var idx = $scope.peoples.indexOf($scope.persons[i])
            console.log(idx);
            if (idx < $scope.peoples.length) {
                var itemToMove = $scope.peoples.splice(idx, 1)
                console.log(itemToMove[0])
                $scope.peoples.splice(idx+2, 0, itemToMove[0]);

            }
        }
    };    

Voici la démo de travail (Ne fonctionne pas si bien, juste gardé pour référence - voir ci-dessous)

Cette solution maintient également la séparation entre la vue et le contrôleur. Le contrôleur a la tâche de manipuler les données, la vue affiche ces données. De cette façon, nous pouvons éviter tout enchevêtrement involontaire. Les manipulations DOM à partir du contrôleur sont incroyablement difficiles à tester.

EDIT après un peu de bricolage: Donc, ma solution précédente a fonctionné dans certains cas, mais fonctionnerait bizarrement avec différentes combinaisons de sélection. Après quelques recherches, j'ai trouvé nécessaire d'ajouter:

<select id="select" size="9" ng-model="persons" ng-options="item as item.name for item in peoples track by item.name" multiple>

Il semble que le select renverrait l'objet persons avec des ordres de sélection arbitraires et que cela chamboulait les choses, surtout après que vous ayez cliqué quelques fois, cela semblait devenir confus quant à l'emplacement des choses.

En outre, je devais cloner et inverser le tableau de personnes lorsque je déplaçais des éléments, car lorsque track by item.name il track by item.name les éléments dans l'ordre, mais si vous essayez de parcourir le tableau, vous risquez d'avoir un impact sur le emplacement des autres éléments dans le tableau (produisant un comportement imprévisible). Nous devons donc commencer par le bas et remonter la pente lorsque nous déplaçons plusieurs objets.

Voici une solution dans laquelle je semble avoir éliminé tout comportement imprévisible en faisant plusieurs sélections arbitraires:

Démonstration de travail

EDIT: Un bug que j'ai trouvé est que des choses étranges se produisent lorsque vous déplacez plusieurs éléments sélectionnés vers le haut ou vers le bas, puis essayez de déplacer cette direction une fois de plus. Tout autre mouvement sans resélection produit des résultats imprévisibles.

EDIT: Le comportement imprévisible mentionné dans l'édition précédente était parce que les fonctions voyaient que, bien que le premier élément était dans sa position finale, les deuxième, troisième, quatrième, etc. articles n'étaient pas dans une position finale, et donc il a essayé de déplacez-les qui a conduit à la réorganisation fou des éléments qui ont déjà été poussés tous vers le haut ou le bas. Afin de résoudre ce problème, j'ai mis un var qui permettrait de suivre la position de l'élément précédemment déplacé. Si l'élément actuel se trouvait dans la position adjacente, il le laisserait simplement là et passerait à autre chose.

Les fonctions finales ressemblent à ceci:

$scope.moveUp = function () {
        var prevIdx = -1;
        var person = $scope.persons.concat();
        console.log($scope.persons);
        for(var i = 0; i < $scope.persons.length; i++) {
            var idx = $scope.peoples.indexOf($scope.persons[i])
            console.log(idx);
            if (idx-1 === prevIdx) {
                prevIdx = idx
            } else if (idx > 0) {
                var itemToMove = $scope.peoples.splice(idx, 1)
                console.log(itemToMove[0])
                $scope.peoples.splice(idx-1, 0, itemToMove[0]);

            }
        }
    };

(Espérons) Final Demo

EDIT: J'ai aimé ce problème et je voulais avoir une meilleure solution dans le cas où il y avait des éléments de liste en double. Cela a été assez facile à résoudre en donnant à chaque objet du tableau une clé id unique, puis en changeant track by item.name pour track by item.id , et tout fonctionne comme avant.

Démonstration de travail pour les doublons





dropdownbox