2016-05-05 6 views
0

Wenn ich versuche, eine materializecss Javascript-Dropdown (http://materializecss.com/dropdown.html) innerhalb Code, der dynamisch durch eine knockoutjs foreach Bindung generiert wird, die Dropdown-Optionen nicht angezeigt, wenn der Dropdown-Trigger angeklickt wird.knockoutjs und materializecss Javascript dropdown

<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 sagt der Dropdown muss mit

$(".dropdown-button").dropdown(); 

jedoch initialisiert werden, dies scheint keine Wirkung zu haben.

Jede Hilfe wäre willkommen. Ich war nicht in der Lage, Hilfe in Knockoutjs Foren oder anderswo zu finden.

EDIT - ein komplettes Arbeitsmodell

<!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> 
+0

Ihre * Frage * ist technisch nicht ein Betrogener, aber ich hätte fast wörtlich Wiederholung [diese Antwort, die ich vor einiger Zeit schrieb] (http://stackoverflow.com/a/34394679/419956). – Jeroen

+0

Danke Jeroen. Ja, bevor ich diese Frage gepostet habe, habe ich deine Antwort studiert und ich habe einfach Fede's Custom Binding versucht, aber es schien nicht zu helfen. Der Schlüssel zum Verknüpfen des Auslösers mit dem Inhalt ist die Datenaktivierungsbindung für den Auslöser und die ID-Bindung für das Ziel. Die Werte müssen gleich sein. Ich denke, ich setze diese richtig auf. –

+0

Die Verwendung einer benutzerdefinierten Bindung für die Integration dieses UI-Plugins ist fast obligatorisch. Wenn ich es initialisiere, werde ich, soweit ich es schätze, nie wirklich funktionieren. In jedem Fall (mit oder ohne Custom-Binding) wäre es hilfreich, wenn Sie den Code der Frage in ein [mcve] erweitern könnten. – Jeroen

Antwort

1

Ich denke, dass Sie, was hier brauchen ein custom binding ist. Was ich glaube, ist, dass, wenn $(".dropdown-button").dropdown(); aufgerufen wird, die foreach Bindung möglicherweise nicht ausgeführt wurde, und die Werte des Dropdowns sind noch nicht verfügbar.

Ich würde die für die Dropdown-Struktur vor dem a Tag des Dropdown-Triggers verschieben, um sicher zu sein, dass jede Bindung in der Struktur vor den Bindungen im Trigger ausgeführt wird. Fügen Sie dann Ihre benutzerdefinierte Bindung dem Trigger hinzu, der bei der Ausführung .dropdown() auf dem Ziel ausführt.

EDIT

Hier ist eine Probe der vorgeschlagenen individuelle Bindung:

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

Und dann könnte die html wie folgt sein.

<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> 

Hoffe, dass hilft.

+0

Danke Fede - Nur um darauf hinzuweisen, dass running $ (". Dropdown-button"). Dropdown(); ist ein Initialisierungsschritt - keine Methode, um das Drop-down auszulösen. Daher sehe ich keine Notwendigkeit für eine benutzerdefinierte Bindung. Stattdessen klicke ich als Test nach dem Rendern der Seite auf einen Link, auf dem $ (". Dropdown-button") ausgeführt wird. Dropdown(); um alle Dropdowns zu initialisieren. Dies scheint jedoch keinen Einfluss zu haben. Vielleicht verstehe ich die Verwendung von benutzerdefinierten Bindungen falsch. –

+0

Ich bearbeite meine Antwort mit einem Beispiel, aber wenn Sie bereits den '$ (". Dropdown-Button "). Dropdown();' manuell nach Bindings ausführen, dann habe ich keine Ideen mehr. Ich werde meine Antwort trotzdem nur der Vollständigkeit halber aktualisieren. – Fede

+0

Danke Fede für die Mühe, den Beispielcode aufzunehmen. Leider schien die Verwendung einer benutzerdefinierten Bindung keinen Unterschied zu machen. –