【问题标题】:Making ul li dropdown filter制作ul li下拉过滤器
【发布时间】:2023-03-14 07:31:01
【问题描述】:

我有一个下拉菜单,现在尝试将其用作过滤器。当我单击菜单项开始过滤时传递一个值但是我在 Jquery 部分有点困惑。如何传递“名称”和“值”并开始过滤。重要的问题是当我单击一项并进行过滤时。之后,当我单击下一个项目时,我不希望它重新开始。我想保留旧的搜索历史。并将其添加到新过滤器中。

 var allOptions = $(".init").children('li');
  $("ul").on("click", function() {
      allOptions.removeClass('selected');
      $(this).addClass('selected');
      $("ul").children('.init').html($(this).html());
      allOptions.slideUp();
  });
#filter-wrapper
{
	margin-top:15px
}

#filter-wrapper ul
{
	list-style:none;
	position:relative;
	float:left;
	margin:0;
	padding:0
}

#filter-wrapper ul a
{
	display:block;
	color:#333;
	text-decoration:none;
	font-weight:700;
	font-size:12px;
	line-height:32px;
	padding:0 15px;
	font-family:"HelveticaNeue","Helvetica Neue",Helvetica,Arial,sans-serif
}

#filter-wrapper ul li
{
	position:relative;
	float:left;
	margin:0;
	padding:0
}

#filter-wrapper ul li.current-menu-item
{
	background:#ddd
}

#filter-wrapper ul li:hover
{
	background:#f6f6f6
}

#filter-wrapper ul ul
{
	display:none;
	position:absolute;
	top:100%;
	left:0;
	background:#fff;
	padding:0
}

#filter-wrapper ul ul li
{
	float:none;
	width:200px
}

#filter-wrapper ul ul a
{
	line-height:120%;
	padding:10px 15px
}

#filter-wrapper ul ul ul
{
	top:0;
	left:100%
}

#filter-wrapper ul li:hover > ul
{
	display:block
}
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>

<div id="filter-wrapper">
  <ul>
    <li name="sortbyprice" class="current-menu-item"><a href="#">Cheapest Cars</a></li>
    <li name="sortbyprice" class="current-menu-item"><a href="#">Newest Cars</a></li>

    <li><a href="#">Car Color</a>
      <ul class="init" name="sortbycolor">
        <li data-value="red"><a href="#">Red</a></li>
        <li data-value="black"><a href="#">Black</a></li>
        <li data-value="silver"><a href="#">Silver</a></li>
      </ul>
    </li>
  </ul>
</div>

例如,当我选择红色时,汽车颜色会随着红色而改变。

P.S:顺便说一下,我给的name="" 来自 Laravel 控制器。它包含数据。

这是我的旧过滤器。它正在处理这个问题。我可以过滤数据。

   <form>
     <select name="sortbyprice" class="custom-select custom-select-md" style="width: 100px;">
       <option value="asc">cheapest</option>
       <option value="desc">Expensive</option>
     </select>
     <select id="cars" name="cars" class="custom-select custom-select-md" style="width: 100px;">
      <option value="" disabled selected>car colors</option>
      <option value="red">red</option>
      <option value="blue">blue</option>
      <option value="black">black</option>
    </select>
    <button type="submit" name="button" class="btn btn-success" id="filter-btn">Filter</button>
  </form>

【问题讨论】:

  • 提交数据需要使用&lt;select&gt;&lt;option&gt;&lt;/option&gt;&lt;/select&gt;,而不是&lt;ul&gt;.
  • 这里我不想使用选择和选项。而不是我尝试将ul li 与jQuery 一起使用。
  • 所以要通过ajax提交数据?
  • 这里有多个错误。第一个数据值“red”等...缺少“=”符号...data-value =“red”...第二个.data 不是函数..
  • 您是否尝试在点击时获取“数据值”属性的值?

标签: javascript jquery


【解决方案1】:

不确定这是否是你想要的,但你可以试试下面的代码并告诉我你的想法

var mockData = [
    {
        make: 'a',
        color: 'red',
        price: 1000
    },
    {
        make: 'a',
        color: 'black',
        price: 2000
    },
    {
        make: 'b',
        color: 'red',
        price: 1
    },
    {
        make: 'a',
        color: 'silver',
        price: 3000
    },
    {
        make: 'c',
        color: 'black',
        price: 1500
    },
    {
        make: 'a',
        color: 'red',
        price: 1500
    }
];

var allOptions = $('.init').children('li');
// use an object to store the filter options selected by the user
// you can then use the information in this object to do the filtering
// by sending an AJAX request or just filter the already fetched data
var filterOptions = {
    sortbycolor: '',
    sortbymake: '',
    sortbyprice: ''
};

$(allOptions).on('click', function () {
    // get the items' data-value
    var value = $(this)[0].dataset.value;
    // select the corresponding <a> tag
    var button = $(this).parent()[0].previousElementSibling;
    // get the corresponding name attribute, e.g. sortbycolor
    var type = $($(this).parent()[0]).attr('name');

    // set the filterOptions
    filterOptions[type] = value;

    // change the displayed text of the filter when the user select something
    $(button).text(function (idx, content) {
        // here I choose using a colon ':' as the separator,
        // you can use whatever you want
        var colonIndex = content.indexOf(':');
        // example for baseContent is 'Car Color'
        var baseContent = content;

        if (colonIndex > -1) {
            baseContent = content.slice(0, colonIndex);
        }

        // e.g 'Car Color: red
        return baseContent + ': ' + value;
    });

    allOptions.slideUp();
    console.log('update filterOptions: ', filterOptions);

    // filter the already fetched data
    var filteredData = mockData.filter(function (val) {
        var isValid = true;

        if (isValid && filterOptions.sortbycolor) {
            isValid = val.color === filterOptions.sortbycolor;
        }

        if (isValid && filterOptions.sortbymake) {
            isValid = val.make === filterOptions.sortbymake;
        }

        return isValid;
    });

    // sort the data by price
    // hard-code the sorting direction here for simplicity,
    // you can set this dynamically with the onclick event
    filterOptions.sortbyprice = 'asc';

    if (filterOptions.sortbyprice === 'asc') {
        filteredData.sort(function (a, b) {
            return a.price - b.price;
        });
    } else if (filterOptions.sortbyprice === 'desc') {
        filteredData.sort(function (a, b) {
            return b.price - a.price;
        });
    }

    console.log('filteredData: ', filteredData);

    // or you can send an ajax request to the server,
    // and let the server handle the filtering for you
    
    // you have to set the keys and values inside
    // the 'data' youself, below is just an example
    // as I don't know what your server's API looks like
    $.get({
        url: 'url-to-your-server',
        data: {
            color: filterOptions.sortbycolor,
            make: filterOptions.sortbymake
        },
        success: function (response) {
            // do something with the response,
            // maybe it contains the filtered result
            // however, I am not sure how does your API look like
        }
    });
});

// to deal with the left over css style(display: none) introduced by .slideUp()
$('.dropdown').on('mouseenter', function () {
    allOptions.css('display', 'block');
});

console.log('initial filterOptions: ', filterOptions);
#filter-wrapper {
    margin-top: 15px
}

#filter-wrapper ul {
    list-style: none;
    position: relative;
    float: left;
    margin: 0;
    padding: 0
}

#filter-wrapper ul a {
    display: block;
    color: #333;
    text-decoration: none;
    font-weight: 700;
    font-size: 12px;
    line-height: 32px;
    padding: 0 15px;
    font-family: "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif
}

#filter-wrapper ul li {
    position: relative;
    float: left;
    margin: 0;
    padding: 0
}

#filter-wrapper ul li.current-menu-item {
    background: #ddd
}

#filter-wrapper ul li:hover {
    background: #f6f6f6
}

#filter-wrapper ul ul {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    background: #fff;
    padding: 0
}

#filter-wrapper ul ul li {
    float: none;
    width: 200px
}

#filter-wrapper ul ul a {
    line-height: 120%;
    padding: 10px 15px
}

#filter-wrapper ul ul ul {
    top: 0;
    left: 100%
}

#filter-wrapper ul li:hover>ul {
    display: block
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="filter-wrapper">
    <ul>
        <li name="sortbyprice" class="current-menu-item"><a href="#">Cheapest Cars</a></li>
        <li name="sortbyprice" class="current-menu-item"><a href="#">Newest Cars</a></li>

        <li class="dropdown">
            <a href="#" id="car-color">Car Color</a>
            <ul class="init" name="sortbycolor">
                <li data-value="red"><a href="#">Red</a></li>
                <li data-value="black"><a href="#">Black</a></li>
                <li data-value="silver"><a href="#">Silver</a></li>
            </ul>
        </li>

        <li class="dropdown">
            <a href="#" id="make">Make</a>
            <ul class="init" name="sortbymake">
                <li data-value="a"><a href="#">A</a></li>
                <li data-value="b"><a href="#">B</a></li>
                <li data-value="c"><a href="#">C</a></li>
            </ul>
        </li>
    </ul>
</div>

【讨论】:

  • 感谢您的付出,几乎是我想要的。实际上下拉菜单正在工作。但是过滤不起作用。我不知道为什么。当我传递名称并传递值但单击它时,它没有过滤。实际上,我用旧的 selectBox 更新了上面的代码。你能检查一下吗?
  • 还有一件事,当我尝试不是通过 Ajax 过滤(因为它不起作用)而是通过链接过滤时,它不会保留第一个过滤器历史记录。下一次点击是重新开始...例如,我过滤价格,然后过滤颜色。它忘记了 sortbyprice...等。
  • 如果您在实际代码中使用的&lt;a&gt; 标记中的链接不是“#”符号,而是指向另一个页面的实际链接,那么filterOptions 对象可能会被初始状态或因页面刷新而丢失。保留filterOptions 的一种方法是使用浏览器的sessionStoragelocalStorage。另一种方法是在用户单击下拉菜单项时阻止页面刷新。
  • 也许您可以将您的过滤逻辑发布到问题中,以便我们获得有关其工作原理的更多信息。
  • 其实我没有先给出链接/网址。 &lt;a&gt; 标签只包含“#”,但是当我单击 li 时,它仍然没有过滤...我在问题中发布了我早期的 selectBox。你可以检查一下。例如在数据库中,我有“汽车”列。每行都有一个像“red”,“blue”这样的项目,所以我用列来获取这些行。在 Laravel 控制器中。名称是 Column name="cars" 并且值是行中的项目...它与 selectBox 一起使用...但我不想使用 selectBox 尝试与ul li...
【解决方案2】:

我删除了你的 css,你只是对颜色值感兴趣 - 对吗?

<div id="filter-wrapper">
    <ul>
        <li name="sortbyprice" class="current-menu-item"><a href="#">Cheapest Cars</a></li>
        <li name="sortbyprice" class="current-menu-item"><a href="#">Newest Cars</a></li>

        <li><a href="#">Car Color</a>
            <ul class="init" name="sortbycolor">
                <li><a href="#" data-value="red">Red</a></li>
                <li><a href="#" data-value="black">Black</a></li>
                <li><a href="#" data-value="silver">Silver</a></li>
            </ul>
        </li>
    </ul>
</div>

<script>
    var allOptions = $(".init").children('li');

    // I think you are only interested in the html content of the a (anchor)

    $("li[data-value] > a").on("click", function(e) {
        e.preventDefault();

        allOptions.removeClass('selected');
        $(this).addClass('selected');

        let filterVal = $(this).data('value'); // do something with this ...
        let li = $('<li />').html( filterVal);
        $("ul.init").html('').append( li); // ul.init just has the value of the filter

        // allOptions.slideUp(); // superfluos
    });
</script>

【讨论】:

    猜你喜欢
    • 2015-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多