淘汰三个级联下拉列表

时间:2016-11-25 11:56:15

标签: jquery knockout.js data-binding yii2

我真的很喜欢cartEditor中的实例。这就是我需要的。好吧,几乎如果我想添加另一个下拉列表。例如,如果我想将另一个字段country添加到现有示例中。场景如下:我选择国家,车辆类别,并根据此选择车辆本身。如何将两个下拉列表绑定到第三个?

数据库中关于此类的表:

表车

id name countryId categoryId

表类别

id name

表国家/地区

id name

实例的文件位于knockoutjs.com

3 个答案:

答案 0 :(得分:2)

你会继续遵循同样的原则:

  • 在数组或普通对象中定义数据
  • 构建使数据可呈现且可选择的视图模型
  • 根据用户输入创建选择数据子集的ko.pureComputed属性。

例如,假设您的商品同时包含categorycountry

var products = [
  { 
    name: "Cheese",
    country: "The Netherlands",
    category: "Dairy"
  }
]

现在,如果您有两个可观察对象,则绑定到您的UI:

this.selectedCountry = ko.observable();
this.selectedCategory = ko.observable();

您可以创建ko.pureComputed,以选择符合要求的产品:

this.selectedProducts = ko.pureComputed(function() {
  return products.filter(function(product) {
    return product.category === this.selectedCategory() &&
           product.country === this.selectedCountry();
  });
}, this);

示例:

var products = [
  {
    name: "Gouda Cheese",
    country: "The Netherlands",
    category: "Dairy"
  },
  {
    name: "Camambert",
    country: "France",
    category: "Dairy"
  },
  {
    name: "Red Wine",
    country: "France",
    category: "Alcoholic beverages"
  }
  
];

var ViewModel = function() {
  // These will be bound to your dropdowns' selections
  this.selectedCountry = ko.observable();
  this.selectedCategory = ko.observable();

  // This computed calculates which products from your data
  // meet the requirements whenever one of the selections changes
  this.selectedProducts = ko.pureComputed(function() {
    return products.filter(function(product) {
      return product.category === this.selectedCategory() &&
        product.country === this.selectedCountry();
    }.bind(this));
  }, this);
  
  // Here, we create a list of countries that appear in your data,
  // this list is used to fill the dropdown's options
  this.countries = getKeyUniques(products, "country");

  // Do the same for categories
  this.categories = getKeyUniques(products, "category");

};

ko.applyBindings(new ViewModel());
  
// Utils
function getKeyUniques(arr, key) {
    return Object.keys(arr.reduce(function(map, item) {
      map[item[key]] = true;
      return map
    }, {}));
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

<select data-bind="options: countries, value: selectedCountry"></select>
<select data-bind="options: categories, value: selectedCategory"></select>

<ul data-bind="foreach: selectedProducts">
  <li data-bind="text: name"></li>
</ul>

答案 1 :(得分:2)

我的解决方案如下。我想根据ID进行过滤。计划从服务器获取国家/地区列表,然后从服务器接收已过滤的产品列表。非常感谢用户。在您的帮助下,借助网站http://knockoutjs.com/examples/cartEditor.html上的示例,我解决了我的问题。 在这里发布我的解决方案:

var countries = [
    {
        "id": 1,
        "name": "Russia"
    },
    {
        "id": 2,
        "name": "USA"
    },
    {
        "id": 3,
        "name": "Great Britain"
    }
];

var categories = [
    {
        "id": 1,
        "name": "Classic Cars"
    },
    {
        "id": 2,
        "name": "Motorcycles"
    },
    {
        "id": 3,
        "name": "Planes"
    }
];

var products = [
    {
        "name": "P-51-D Mustang",
        "countryId": 2,
        "categoryId": 3,
        "price": 12.42
    },
    {
        "name": "1997 BMW R 1100 S",
        "countryId": 2,
        "categoryId": 2,
        "price": 60.87
    },
    {
        "name": "2002 Chevy Corvette",
        "countryId": 2,
        "categoryId": 1,
        "price": 100.87
    },
    {
        "name": "1998 Chrysler Plymouth Prowler",
        "countryId": 1,
        "categoryId": 1,
        "price": 150.87
    }
];

var CartLine = function () {
    var self = this;
    self.countries = ko.observableArray(countries);
    self.categories = ko.observableArray(categories);
    self.quantity = ko.observable(1);
    self.selectedCountry = ko.observable();
    self.selectedCategory = ko.observable();
    self.selectedProduct = ko.observable();
    self.subtotal = ko.pureComputed(function () {
        return self.selectedProduct() ? (self.selectedProduct().price * self.quantity()) : "yet";
    });
    self.products = ko.pureComputed(function () {
        return $.grep(products, function (item) {
            return (self.selectedCountry() && self.selectedCategory() && item.countryId === self.selectedCountry().id && item.categoryId === self.selectedCategory().id);
        });
    });
};

var Cart = function () {
    var self = this;
    self.lines = ko.observableArray([new CartLine()]);
    self.lines2 = ko.observableArray([new CartLine()]);
    self.grandTotal = ko.pureComputed(function () {
        var total = 0;
        $.each(self.lines(), function () {
            total += this.subtotal();
        });
        return total;
    });

    // Operations
    self.addLine = function () {
        self.lines.push(new CartLine());
    };
    self.removeLine = function (line) {
        self.lines.remove(line);
    };
};

ko.applyBindings(new Cart());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
    <head>
        <title>TODO supply a title</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="stylesheet" href="stl.css" />
    </head>
    <body>
            <div class='liveExample'>
                <table width='50%'>
                    <thead>
                        <tr>
                            <th width='25%'>Country</th>
                            <th width='25%'>Category</th>
                            <th class='price' width='15%'>Product</th>
                            <th class='price' width='15%'>Price</th>
                            <th class='quantity' width='10%'>Quantity</th>
                            <th class='price' width='15%'>Subtotal</th>
                            <th width='10%'></th>
                        </tr>
                    </thead>
                    <tbody data-bind='foreach: lines'>
                        <tr>
                            <td>
                                <select data-bind='options: countries, optionsText: "name", optionsCaption: "Select...", value: selectedCountry'> </select>
                            </td>
                            <td>
                                <select data-bind='options: categories, optionsText: "name", optionsCaption: "Select...", value: selectedCategory'> </select>
                            </td>
                            <td>
                                <select data-bind='visible: (selectedCountry() && selectedCategory()), options: products, optionsText: "name", optionsCaption: "Select...", value: selectedProduct'> </select>    
                            </td>
                            <td>
                                <span data-bind='text: selectedProduct() ? selectedProduct().price : 0'> </span>
                            </td>
                            <td class='quantity'>
                                <input data-bind='value: quantity, valueUpdate: "afterkeydown"' />
                            </td>
                            <td class='price'>
                                <span data-bind='text: subtotal()'> </span>
                            </td>
                            <td>
                                <a href='#' data-bind='click: $root.removeLine'>Remove</a>
                            </td>
                        </tr>
                    </tbody>
                </table>
                <p class='grandTotal'>
                    Total value: <span data-bind='text: grandTotal()'> </span>
                </p>
                <button data-bind='click: addLine'>Add product</button>
            </div>
        <script src="knockout-3.4.1.js" type="text/javascript"></script>
        <script src="jquery-3.1.1.min.js" type="text/javascript"></script>
        <script src="app.js" type="text/javascript"></script>
    </body>
</html>

答案 2 :(得分:0)

我根据以下方法做了你要求的事情 -

  • 根据countryfiltering
  • 跟踪车辆阵列中类别和countryId以及categoryId下拉菜单中所选值的跟踪

为此,我对subscribedcountry的所选值category,所以当其中任何一个发生变化时,我会调用过滤器来更新所选的车辆,以便它是在第三次下拉列表中更新。

它还包括视图模型定义末尾的一些测试结果。

P.S。 - 让我为数据的糟糕组合而烦恼,但我想我的努力足以让你得到它的要点; - )

以下是fiddle