Knockoutjs: how to filter foreach binding without using if

Is there a way to implement the below instructions using a custom binding to eliminate the if-binding:

<div data-bind="foreach: $root.customersVM.customers">
    @Html.Partial("_Customer")
    <div data-bind="foreach: $root.ordersVM.orders">
        <!-- ko if: customer() == $parent.id() -->
        @Html.Partial("_Order")
        <!-- /ko -->
    </div>
</div>

      

Or put another way: does anyone know Method 2 in the Knockout.js foreach answer : but only when the comparison is true ?

+3


source to share


2 answers


How about creating another computed or function that does filtering and that you can iterate over instead of iterating over orders?

Html

<div data-bind="with: filteredCustomers('smith')">
    <span data-bind="text: name"></span>
</div>

<div data-bind="foreach: customers">
    <span data-bind="text: name"></span>
</div>

<div data-bind="foreach: filteredOrders(4)">
    <span data-bind="text: id"></span>
</div>

<div data-bind="foreach: orders">
    <span data-bind="text: id"></span>
</div>

<button data-bind="click: function() {customers.push({name:'Smith'});}">Add customer</button>
<button data-bind="click: function() {orders.push({id:4});}">Add order</button>

      



JavaScript:

var vm = {
    customers: ko.observableArray([
        {name: 'Smith'}, {name: 'Williams'}, {name: 'Brown'}, {name: 'Miller'}
    ]),
    orders: ko.observableArray([
        {id: 1}, {id: 2}, {id: 3}, {id: 4}, {id: 4}
    ])
};

// return first hit (unique ID)
vm.filteredCustomers = function(name) {
   return ko.utils.arrayFirst(this.customers(), function(customer) {
      return (customer.name.toLowerCase() === name.toLowerCase());
   });
};

// return all hits
vm.filteredOrders = function(id) {
   return ko.utils.arrayFilter(this.orders(), function(order) {
      return (order.id === id);
   });
};

ko.applyBindings(vm);

      

+10


source


I find it best to use data from two different databases and combine them into the same view model. For example, in your viewmodel in javascript, take clients first. Then grab the orders. Add an orders property to each customer and add orders to it.

Your view model is meant to be used in a view. So your best bet is to take the data, however it's a sin, and make it work for the presentation. As you say, "if" is likely to be a problem. Also, if you use foreach in a function, as you suggest in your comment, then without having to iterate over the elements when the observable arrays change. I prefer to get my view model first and then the user experience is fast.



2 cents :)

+1


source







All Articles