AngularJS: повторно рандомизировать ng-повтор при каждом ng-клике

#javascript #angularjs

#javascript #angularjs

Вопрос:

Я знакомлюсь с AngularJS и собираю простое приложение для случайного рисования. У меня есть четыре кнопки, позволяющие вам «вытянуть» одну или две карты из любой из двух колод (представленных двумя отдельными файлами JSON). В готовом виде мой образец приложения в основном работает, но рандомизация не происходит, если нажать кнопку для отображаемой в данный момент колоды (вы получаете те же точные данные в том же точном порядке)… повторная рандомизация выполняется только в том случае, если вы нажимаете, чтобы взять из другой колоды, а затем возвращаетесь обратно.

Я все еще сбит с толку некоторой «магией» Angular, и я вижу, что фильтр срабатывает при каждом нажатии … Так что я остаюсь ломать голову над этим.

Вот HTML…

 <div ng-controller="Cards">

    <p>
        <button ng-click="whichDeck=franchises;qty=1;shuffle=undefined">DRAW FRANCHISE</button><button ng-click="whichDeck=franchises;qty=2">X2</button>
    </p>

    <p>
        <button ng-click="whichDeck=twists;qty=1">DRAW TWIST</button><button ng-click="whichDeck=twists;qty=2">X2</button>
    </p>

    <ul class="cards">
        <li class="card" ng-repeat="card in whichDeck | shuffle | limitTo:qty"> <!-- filter:query -->
            <h2>{{card.Title}}</h2>
            <h3 ng-show="card.Origin">{{card.Origin}}</h3>
            <p>{{card.Description}}</p>
        </li>
    </ul>
</div>
  

Вот JS…

 var app = angular.module('myApp',['Shuffle']);

app.controller('Cards', ['$scope', '$http', function($scope, $http) {

    var controller = this;

    $scope.franchises = [];
    $scope.twists = [];
    $scope.deck = '';

    $http.get('js/franchises.json').success(function(data){
        $scope.franchises = data;
    });
    $http.get('js/twists.json').success(function(data){
        $scope.twists = data;
    });

}]);

var shuffle = angular.module('Shuffle', []);

shuffle.filter('shuffle', function() {    
    var shuffledArr = [],
        shuffledLength = 0;
    return function(arr) {
        if (typeof(arr)==='undefined')
            arr = [];
        var o = arr.slice(0, arr.length);
        if (shuffledLength == arr.length) return shuffledArr;
        for(var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
        shuffledArr = o;
        shuffledLength = o.length;
        return o;
    };
});
  

Комментарии:

1. Две вещи … во-первых, оказывается, что фильтр shuffle, который я использовал (из другого потока StackOverflow), предназначен для ТОГО, чтобы НЕ обновляться. Причина этого в том, что Angular будет выдавать ошибки дайджеста как сумасшедший, когда вы выполняете такого рода сложную операцию в фильтре (фильтры выполняются ЧАСТО и, следовательно, имеют ограничения). Второе: извлекая перемешивание из фильтра и помещая его в контроллер, вы избегаете проблемы с ошибкой дайджеста и получаете новое перемешивание при каждом нажатии. Спасибо, Мошо!

Ответ №1:

Вот пример того, как этого можно достичь, я думаю, вы слишком все усложняете.

HTML:

 <div ng-app="" ng-controller="Ctrl"> 
    <button ng-click="shuffle(obj)">shuffle</button>
   <div ng-repeat="o in obj">
       {{o}}
    </div>   
</div>
  

JS:

 function Ctrl($scope) {
    $scope.obj = [1,2,3,4,5,6,7,8,9]

    //generic shuffling function
    $scope.shuffle = function(o){ 
        for(var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
        return o;
    };
};
  

ng-repeat используется порядок массива, и изменения в массиве в области видимости будут автоматически отражены в представлении.

скрипка