【问题标题】:knockoutjs and materializecss javascript dropdownknockoutjs 和 materializecss javascript 下拉列表
【发布时间】:2016-08-31 15:20:32
【问题描述】:

当我尝试在由 knockoutjs foreach 绑定动态生成的代码中使用 materializecss javascript 下拉菜单 (http://materializecss.com/dropdown.html) 时,单击下拉触发器时不会显示下拉选项。

<ul class="list" data-bind="foreach: items">
  <li>
    <!-- Dropdown Trigger -->
    <a class='dropdown-button btn' href='#' 
             data-bind="attr: {'data-activates': 'dropdown' + $index()}">Drop Me!</a>
    <!-- Dropdown Structure -->
    <ul data-bind="attr: {id: 'dropdown' + $index()}" class='dropdown-content'>
      <li><a href="#!">one</a></li>
      <li><a href="#!">two</a></li>
      <li><a href="#!">three</a></li>
    </ul>
  </li>
</ul>

Materializecss 说下拉菜单必须用

初始化
$(".dropdown-button").dropdown();

但是,这似乎没有效果。

任何帮助将不胜感激。我无法在 knockoutjs 论坛或其他地方找到帮助。

EDIT - 一个完整的工作模型

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <!--Import Google Icon Font-->
    <link href="http://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.6/css/materialize.min.css">
</head>
<body>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.6/js/materialize.min.js"></script>

    <script  >
        function ItemsViewModel() {
            var that = this;

            function collectionItem(root, title) {
                var self = this;
                self.title = ko.observable(title);
            };

            that.items = ko.observableArray();
            that.loadItems = function () {
                for (var i = 0, j = 5; i < j; i++) {
                   that.items.push(new collectionItem(that,"title"+ i.toString()));
                }
            };
        };

        ko.bindingHandlers.materializeDropdown = {
            init: function (element, valueAccessor) {
                $(element).dropdown();
            },
            update: function (element, valueAccessor, allBindings) {
            }
        };

        var itemsViewModel;

        $(document).ready(function () {
            itemsViewModel = new ItemsViewModel();

            ko.applyBindings(itemsViewModel,      $("#divForItemsViewModel").get(0));
            itemsViewModel.loadItems();
        });
    </script>
    <div id="divForItemsViewModel">
         <ul class="list" data-bind="foreach: items">
            <li>
                <div data-bind="text:title"></div>
                <!-- Dropdown Trigger -->
                <a class='dropdown-button btn' href='#'
                   data-bind="attr: {'data-activates': 'dropdown' + $index()}, materializeDropdown">Drop Me!</a>
                <!-- Dropdown Structure -->
                <ul data-bind="attr: {id: 'dropdown' + $index()}" class='dropdown-content'>
                    <li><a href="#!">one</a></li>
                    <li><a href="#!">two</a></li>
                    <li><a href="#!">three</a></li>
                </ul>
            </li>
        </ul>
        <a class='dropdown-button btn' href='#'
       data-activates="dropdownx">Drop Me THIS WORKS</a>
        <ul id="dropdownx" class='dropdown-content'>
            <li><a href="#!">one</a></li>
            <li><a href="#!">two</a></li>
            <li><a href="#!">three</a></li>
        </ul>
    </div>
</body>
</html>

【问题讨论】:

  • 您的 question 在技术上不是骗人的,但我几乎要逐字重复this answer I wrote some time ago。
  • 谢谢杰罗恩。是的,在发布这个问题之前,我研究了你的答案,我只是尝试了 Fede 的自定义绑定,但它似乎没有帮助。将触发器链接到内容的关键是触发器上的 data-activates 绑定和目标上的 id 绑定。值必须相同。我认为我设置正确。
  • 使用自定义绑定来集成这个 UI 插件几乎是强制性的。据我所知,像你一样初始化它永远不会真正起作用。无论哪种情况(有或没有自定义绑定),如果您可以将问题的代码扩展为minimal reproducible example,将会很有帮助。
  • 谢谢 Jeroen 我已经添加了一个例子。

标签: knockout.js materialize


【解决方案1】:

我认为您需要的是custom binding。我认为正在发生的是,当调用 $(".dropdown-button").dropdown(); 时,foreach 绑定可能尚未执行,因此下拉列表的值尚不可用。

我会将下拉结构的ul 移动到下拉触发器的a 标记之前,以确保结构中的任何绑定在触发器中的绑定之前运行。然后将您的自定义绑定添加到触发器,当调用该触发器时会在目标上执行 .dropdown()。

编辑

以下是建议的自定义绑定示例:

ko.bindingHandlers.materializeDropdown = {
    init: function(element, valueAccessor) {
        $(element).dropdown();
    },
    update: function(element, valueAccessor, allBindings) {
    }
};

然后html可以如下。

<ul class="list" data-bind="foreach: items">
  <li>
    <!-- Dropdown Structure -->
    <ul data-bind="attr: {id: 'dropdown' + $index()}" class='dropdown-content'>
      <li><a href="#!">one</a></li>
      <li><a href="#!">two</a></li>
      <li><a href="#!">three</a></li>
    </ul>
    <!-- Dropdown Trigger -->
    <a class='dropdown-button btn' href='#' 
             data-bind="attr: {'data-activates': 'dropdown' + $index()}, materializeDropdown">Drop Me!</a>
  </li>
</ul>

希望对您有所帮助。

【讨论】:

  • 感谢 Fede - 只是指出运行 $(".dropdown-button").dropdown();是一个初始化步骤 - 不是触发下拉菜单的方法,所以我真的不认为需要自定义绑定。相反,作为测试,在呈现页面后,我单击一个运行 $(".dropdown-button").dropdown(); 的链接。初始化任何下拉菜单。但是,这似乎没有影响。也许我误解了自定义绑定的使用。
  • 我将使用示例编辑我的答案,但如果您已经在绑定后手动运行$(".dropdown-button").dropdown();,那么我没有想法。为了完整起见,无论如何我都会更新我的答案。
  • 感谢 Fede 不厌其烦地包含示例代码。遗憾的是,使用自定义绑定似乎没有任何区别。
猜你喜欢
  • 2015-01-20
  • 1970-01-01
  • 2015-12-11
  • 2013-07-13
  • 2015-11-27
  • 2013-06-14
  • 1970-01-01
  • 2017-05-09
  • 1970-01-01
相关资源
最近更新 更多