AngularJS — шаблон проектирования для возврата подмножества данных из службы и привязки к набору?

У меня есть служба, которая управляет набором данных. Служба достаточно вежлива, чтобы предоставить варианты для возврата подмножества указанных данных на основе (какой бы логики она ни была, в этом примере она просто будет искать определенное значение атрибута данных). Сервис вернет массив совпадений. На мой взгляд, я хочу привязываться к этому набору совпадений. Однако, поскольку служба возвращает новый объект массива каждый раз при вызове функции фильтра, это не работает. Мое представление привязано к ранее возвращенному объекту массива.

Попробуйте эту скрипку:

http://jsfiddle.net/FdWeK/1/

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

app.factory('MrData', function() {
    var allData = [
        {name: 'Adam', type: 'boy'},
        {name: 'Kassidy', type: 'girl'},
        {name: 'Justin', type: 'boy'},
        {name: 'Chloe', type: 'cat'},
        {name: 'D The P', type: 'dog'},
    ];

    return {
        add: function(thing) {
            allData.push(thing);
        },
        fetchAll: function() {
            return allData;
        },
        fetchForType: function(type) {
            var some = [];

            for (var i = 0; i < allData.length; i++) {
                if (allData[i].type == type)
                    some.push(allData[i]);
            }

            return some;
        }
    }
});

app.controller('SomeCtrl', function($scope, MrData) {
    $scope.showSome = MrData.fetchForType('boy');
    $scope.showAll = MrData.fetchAll();

    $scope.addBoy = function() {
        MrData.add({name: 'TED!', type: 'boy'});
    }

    $scope.addOther = function() {
        MrData.add({name: 'Other', type: 'Other'});
    }
});

и вид:

<div ng-app="app">
    <div ng-controller="SomeCtrl">
        <button ng-click="addBoy()">Add Boy</button>
        <button ng-click="addOther()">Add Other</button>

        <h2>Boys</h2>
        <ol>
            <li ng-repeat="thing in showSome">
                {{ thing.type }}
                {{ thing.name }}
            </li>
        </ol>

        <h2>All</h2>
        <ol>
            <li ng-repeat="thing in showAll">
                {{ thing.type }}
                {{ thing.name }}
            </li>
        </ol>
    </div>
</div>

Вы можете видеть, что список мальчиков не обновляется, когда вы нажимаете «Добавить мальчика». И я понимаю, почему, но я не понимаю, как это исправить! Должен быть простой шаблон проектирования или функция, о которой я просто не знаю или не могу понять самостоятельно.

Заранее спасибо, Адам


person OakBehringer    schedule 26.07.2014    source источник


Ответы (2)


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

Вам следует использовать фильтр https://docs.angularjs.org/api/ng/filter/filter

Например, этот простой ng-repeat должен работать:

<li ng-repeat="thing in showAll | filter:{type: 'boy'}">

Также обновлена ​​скрипка.

person Matt Way    schedule 26.07.2014

Вам нужно повторно применить фильтры, потому что связанные массивы не изменились, когда вы вызываете addBoy() или addOther().

Один из способов обойти это — вызывать фильтр после каждого вызова:

function applyFilter(){
        $scope.showSome = MrData.fetchForType('boy');
        $scope.showAll = MrData.fetchAll();
}

$scope.addBoy = function() {
    MrData.add({name: 'TED!', type: 'boy'});
    applyFilter();
}

$scope.addOther = function() {
    MrData.add({name: 'Other', type: 'Other'});
    applyFilter();
}

Я бы показал, как это можно сделать с угловыми фильтрами, но, кажется, кто-то уже это сделал.

person pixelbits    schedule 26.07.2014
comment
Хотя это, безусловно, работает, я думаю, что это вводит в заблуждение, так как это плохой выбор дизайна. Если была какая-то конкретная причина для хранения отдельного списка и отфильтрованного списка, вы должны по крайней мере абстрагировать отфильтрованные списки в какой-то кеш, который внутренне обновляется такими функциями, как .add() - person Matt Way; 26.07.2014