2015-10-23 9 views
2

У меня есть выбор, который выглядит следующим образомAngularJS фильтр Выберите массиву

<select 
    class="form-control" 
    ng-model="vm.transaction.location_from" 
    ng-options="l.name for l in vm.locations"> 
</select> 

с vm.locations источников из следующего JSON:

[ 
    { 
    "id": "c0d916d7-caea-42f9-a87f-a3a1f318f35e", 
    "name": "Location 1" 
    }, 
    { 
    "id": "d8a299a3-7f4b-4d32-884f-efe25af3b4d2", 
    "name": "Location 2" 
    } 
] 

Кроме того, у меня есть другой выбор, который выглядит следующим образом:

<select 
    class="form-control" 
    ng-model="vm.transaction.item" 
    ng-options="i.name for i in vm.items"> 
</select> 

с vm.items источник от следующих JSON:

[ 
    { 
    "id": "9f582e58-45dd-4341-97a6-82fe637d769e", 
    "name": "20oz Soft Drink Cup", 
    "locations": [ 
     { 
     "inventory_id": "9d5aa667-4a64-4317-a890-9b9291799b11", 
     "location_id": "c0d916d7-caea-42f9-a87f-a3a1f318f35e" 
     }, 
     { 
     "inventory_id": "9d5aa667-4a64-4317-a890-9b9291799b11", 
     "location_id": "d8a299a3-7f4b-4d32-884f-efe25af3b4d2" 
     } 
    ], 
    } 
] 

Я хочу, об изменении ng-mode="vm.transaction.item" выбора, имеют ng-model="vm.transaction.location_from" быть отфильтрованы, чтобы показывать только значения, которые соответствуют с locations массива. Я знаю, что могу использовать | filter: { }, но я не уверен, как должен выглядеть этот фильтр.

ответ

0

var app = angular.module("Test", []); 
 
app.controller("Ctrl1", function($scope) { 
 
    $scope.location_fromArr = 
 
    [{ 
 
     "id": "9f582e58-45dd-4341-97a6-82fe637d769e", 
 
     "name": "20oz Soft Drink Cup", 
 
     "locations": [{ 
 
      "inventory_id": "9d5aa667-4a64-4317-a890-9b9291799b11", 
 
      "location_id": "c0d916d7-caea-42f9-a87f-a3a1f318f35e" 
 
     },{ 
 
      "inventory_id": "9d5aa667-4a64-4317-a890-9b9291799b11", 
 
      "location_id": "d8a299a3-7f4b-4d32-884f-efe25af3b4d2" 
 
     }], 
 
    }]; 
 

 
    $scope.itemArr = 
 
    [{ 
 
     "id": "c0d916d7-caea-42f9-a87f-a3a1f318f35e", 
 
     "name": "Location 1" 
 
     },{ 
 
     "id": "d8a299a3-7f4b-4d32-884f-efe25af3b4d2", 
 
     "name": "Location 2" 
 
    }]; 
 
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> 
 

 
<div ng-app="Test" ng-controller="Ctrl1"> 
 
Item 
 
<select 
 
    class="form-control" 
 
    ng-model="item" 
 
    ng-options="i.name for i in itemArr"> 
 
</select> 
 
Location 
 
<select 
 
    class="form-control" 
 
    ng-model="location_from" 
 
    ng-options="l.name for l in location_fromArr | filter:{l.id: location_from.location_id}"> 
 
</select> 
 
</div>

+0

К сожалению, это не работает:/ –

+0

Почему бы не начать работу? ? –

+0

Хотел бы я знать: http://jsfiddle.net/km0jten2/ –

0

Один из способов сделать это, чтобы обеспечить функцию фильтра для фильтрации местоположения. Что-то вроде:

vm.filterFun = function(selectedLocations) { 
    return function (location) { 
    var n; 
    if (!selectedLocations) { 
     return true; 
    } 
    for(n=0;n<selectedLocations.length;n += 1) { 
     if (selectedLocations[n].location_id === location.id) { 
     return true; 
     } 
    } 
    return false; 
    } 
} 

Это фактически функция, возвращающая функцию фильтра на основе выбранного элемента.

Затем в вашем отборном применить фильтр с:

<select 
     class="form-control" 
     ng-model="vm.transaction.location_from" 
     ng-options="l as l.name for l in vm.locations | filter:vm.filterFun(vm.transaction.item.locations)"> 
</select> 

См plunker here.

1

Надеюсь, что это ваши ожидаемые результаты. Ниже представлены два варианта, которые я пробовал ... demo | http://embed.plnkr.co/689OQztgu8F800YjBB2L/

Ref: underscorejs | angular-filter | everything-about-custom-filters-in-angular-js

// 1. filter items collection by location 
angular.module('demo').filter('withLocation', function() { 
return function (items, selectedLocation) { 
    function isLocationInLocations (elem) { return selectedLocation && elem.location_id === selectedLocation.id; } 
     function itemHasLocation (elm){ return (elm.locations && elm.locations.filter(isLocationInLocations).length > 0); } 
     return items.filter(itemHasLocation); 
}}); 

// 2. filter function to check if option can be rendered .... 
vm._filters.selectableItems = function(selectedLocation) { 
    return function(item) { 
     var locationsHasLocation = function(elem) { return selectedLocation && elem.location_id === selectedLocation.id; } 
     return (item.locations && item.locations.filter(locationsHasLocation).length > 0); 
    } 
} 
+1

Мне пришлось немного изменить его, чтобы работать в другом направлении (мне нужно было отфильтровать местоположения на основе выбранного элемента), но первым фильтром является тот, который мне нужен. Спасибо. –

0

Я бы отказаться от угловых фильтров и использовать getterSetter вариант ngModelOptions.

Это может выглядеть примерно так:

var selectedItem, selectedLocation; 

var items = []; 
var locations = []; 

vm._items = items; // Static, always allow all items to be selected. 
vm.locations = function() { 
    // Return differing results based on selectedItem.locations. 
}; 

vm._transaction = { 
    location: function (v) { 
    /** 
    * If v is null, it is not present in the selectedItem.locations array. 
    * The extra check will ensure that we don't persist a filtered out location when 
    * selecting another item. 
    */ 
    return (v || v === null) ? (selectedLocation = v) : selectedLocation; 
    }, 
    item: function (v) { 
    return v ? (selectedItem = v) : selectedItem; 
    } 
}; 

Вот plunker демонстрирует поведение.

Не так просто/прямолинейный как фильтр, но я бы поставил (по крайней мере, в случае piped filter), что вы, возможно, увидеть прирост производительности небольшого происходит с этим подходом.

У меня нет номеров для резервного копирования вышеуказанного утверждения, и оно обычно сводится к размеру вашего набора данных в любом случае. Песчинка соли.

Если вам это нужно действовать наоборот, вы могли бы писать дополнительный фильтр, как, например:

function superFilter2 (arr) { 
    // If no location is selected, we can safely return the entire set. 
    if (!selectedLocation) { 
    return arr; 
    } 

    // Grab the current location ID. 
    var id = selectedLocation.id; 

    // Return the items that are present in the selected location. 
    return arr.filter(function (item) { 
    return item.locations.map(function (l) { 
     return l.location_id; 
    }).indexOf(id); 
    }); 
} 

С, что и фильтр в комплект поставки plunker, есть некоторые общие черты, которые могли бы быть перешел в функции более высокого порядка. В конце концов, с некоторым функциональным соусом вы, вероятно, могли бы получить одну божественную функцию, которая будет работать в обоих направлениях.

0

вы можете сделать это:

<select 
    class="form-control" 
    ng-model="vm.transaction.item" 
    ng-change="itemCahngedFn()" 
    ng-options="i.name for i in vm.items"> 
</select> 

var itemChangedFn = function(){ 
    var filtredItems = []; 
    angular.forEach(vm.locations, function(item){ 
     if(item.name == vm.transaction.item){ 
      filtredItems .push(item.location); 
     } 
    }); 

    vm.locations= filtredItems ; 
} 
0

я думаю filter:{ id : item.locations[0].location_id } должен сделать трюк. вот jsfiddle

Как вы думаете?