如何在 Pug 表单中添加过滤器?

How to add filter in a Pug form?

这是我的数据库的一个例子

我正在使用 nodejs、MongoDB 和 pug 制作一个网站。我已将这些数据以哈巴狗形式显示在 select 框中。像这样但是在哈巴狗中使用 for 循环和所有数据-

<!DOCTYPE html>
<html>
  <body>
    <form>
      <select name="Type">
        <option value="Electronic">Electronic</option>
      </select>
         
      <select name="Brands">
        <option value="Apple">Apple</option>
        <option value="Dell">Dell</option>
        <option value="Samsung">Samsung</option>
      </select>
      
      <select name="Products">
        <option value="Macbook Pro">Macbook Pro</option>
        <option value="Inspioren">Inspioren</option>
        <option value="Galaxy S20">Galaxy S20</option>
      </select>
    </form>
  </body>
</html>

我想要做的是,根据用户在其他 select 选项中 select 编辑的内容更改 select 框选项。

例如:- 如果用户 selects "Type: "Electronic", and "Brand: Apple",我想仅显示 Apple 产品作为选项。 或者,如果用户 selects "Type: "Electronic" 它应该自动在品牌的 select 框中显示品牌列表。

将从数据库添加数据(不会硬编码)。

一种可能是修改您的 Pug 视图以包含 select 标签 ID,并将下游选择留空,然后在视图末尾添加一个脚本以添加事件侦听器并执行一些操作 DOM 在加载视图后使用 JQuery 或仅 javascript 进行操作。然后,事件处理程序将允许您根据您在当前标签中选择的内容有条件地填写下一个 select 标签。

大致如下:

script.
  document.addEventListener("DOMContentLoaded", 
  function(e) {
    const typeSelect = document.getElementById('type')
    typeSelect.onchange = function(e) {
      const brandSelect = document.getElementById('brand')
      if (typeSelect.options[typeSelect.selectedIndex].text === 'Apple') {
        ['MacBook Pro', 'MacBook Air', 'MacBook Mini'].forEach(function(product) {
          let newOption = createElement('option')
          newOption.textContent = product
          brandSelect.appendChild(newOption
       }
       else if ( // etc... ) {}
       else {
       // functionality to clear out the downstream select tags.
       }
    }

    const brandSelect = document.getElementById('brand')
    brandSelect.onchange = // etc, etc....

  })

服务器端代码,带有一些测试数据:

app.get("/avi", (req, res) => {
  res.render("avi", { Types: [ "Electronic"], data: 
    [ { Type: "Electronic", Brand: "Apple", Products: [ "MacBook Pro", "MacBook Air", "Mac Mini"]}, 
      { Type: "Electronic", Brand: "Dell", Products: [ "Inspioren", "Latitude"]},
      { Type: "Electronic", Brand: "Samsung", Products: [ "Galaxy S20", "Galaxy S10"]}
    ]
  });
});

您应该包括一个类型列表,否则您的 Pug 脚本将必须通过原始数据来识别唯一类型的数量。

avi.pug:

html
  head
  body 
    p Linked Dropdowns
    form
      p Type: 
        select#types(onchange="typeChanged()")
          option(value="") Select Type
          each item of Types 
            option(value=item)=item
      p Brand:
        select#brands(onchange="brandChanged()")
          option(value="") Select Brand
      p Product:
        select#products()
          option(value="") Select Product

  script.
    const data = JSON.parse(`!{JSON.stringify(data)}`);
    const types = document.getElementById("types")
    const brands = document.getElementById("brands")
    const products = document.getElementById("products")

    const typeChanged = () => {
      clearBrands(); clearProducts();
      if (types.selectedIndex!==0) {
        const selectedType = types.options[types.selectedIndex].text;
        data.forEach(d => {
          if (d.Type===selectedType) {
            const newBrand = document.createElement("option")
            newBrand.value = newBrand.innerText = d.Brand;
            brands.appendChild(newBrand);
          }
        });
      }
    }
    const brandChanged = () => {
      clearProducts();
      if (brands.selectedIndex!==0) {
        const selectedType = types.options[types.selectedIndex].text;
        const selectedBrand = brands.options[brands.selectedIndex].text;
        data.forEach(d => {
          if (d.Type===selectedType && d.Brand===selectedBrand) {
            d.Products.forEach(p => {
              const newProd = document.createElement("option")
              newProd.value = newProd.innerText = p;
              products.appendChild(newProd);
            });
          }
        })
      }
    }

    const clearBrands = () => {
      const item0 = brands.childNodes[0];
      brands.textContent = ""; 
      brands.appendChild(item0);
    }
    const clearProducts = () => {
      const item0 = products.childNodes[0];
      products.textContent = ""; 
      products.appendChild(item0);
    }

服务器data被注入客户端Javascript

const data = JSON.parse(`!{JSON.stringify(data)}`);

这个方法不是很稳健。如果数据中任何地方有反引号 ` 字符,就会出现问题。

我在这里回答我自己的问题。我所做的是在 Type select 框中添加 onchange 函数。并在我的文件中创建了一个脚本,代码如下-

function change() {
                    var Type_name = document.getElementById("type").value;
                    var Brand= document.getElementById('brands');
                    var Product = document.getElementById('products');
                    Brand.options.length = 0;
                    Product.options.length = 0;

                    var DefaultBrand = new Option("Brand", "Null");
                    var DefaultProduct = new Option ("Product", "Null");
                    Brand.add(DefaultBrand, undefined);
                    Product.add(DefaultProduct, undefined);

                    var product_master = !{JSON.stringify(product_names)};

                    for (const brands of product_master) {
                        if (brands.Type == Type_name){
                            const BrandOption = new Option(brands.Brand, brands.Brand);
                            Brand.add(BrandOption, undefined);
                        }

                    }
                

还有一个类似于此的添加产品的功能。

这对我有用。但是如果有人想改进这段代码,我将不胜感激。