2016-11-13 4 views
0

Ich muss ein observableArray jedes Mal aktualisieren, wenn eine separate Auswahlbox verwendet wird. Das Problem ist mit den Hefen ..., wenn der Benutzer „Danstar“ als Kategorie für eine Hefe nimmt, sollte die „Hefe Variety“ erst jetzt zeigtupdate observableArray basierend auf anderen beobachtbaren knockoutjs

Danstar 
    Danstar 1 
    Danstar 2 

wo „Danstar“ die optgroup ist. Meine Idee war, nur

{category: 'Danstar', yeasts: ['Danstar 1', 'Danstar 2']} 

nur greifen und ihn auf den yeast_groups_individual. Ich brauche jedes Paar von "Yeast Brand Filter" und "Yeast Variety", um unabhängig zu arbeiten. Ich habe bisher:

 ko.observableArray.fn.countVisible = function(){ 
 
      return ko.computed(function(){ 
 
       var items = this(); 
 

 
       if (items === undefined || items.length === undefined){ 
 
        return 0; 
 
       } 
 

 
       var visibleCount = 0; 
 

 
       for (var index = 0; index < items.length; index++){ 
 
        if (items[index]._destroy != true){ 
 
         visibleCount++; 
 
        } 
 
       } 
 

 
       return visibleCount; 
 
      }, this)(); 
 
     }; 
 

 
     function Hop(data) { 
 
      this.name = ko.observable(data.name || ""); 
 
      this.amount = ko.observable(data.amount || ""); 
 
      this.time = ko.observable(data.time || ""); 
 
      this.use = ko.observable(data.use || "Boil"); 
 
     } 
 

 
     function Fermentable(data) { 
 
      this.name = ko.observable(data.name || ""); 
 
      this.pounds = ko.observable(data.pounds || ""); 
 
      this.ounces = ko.observable(data.ounces || ""); 
 
      this.weight_unit = ko.observable(data.weight_unit || "oz"); 
 
      this.milling_preference = ko.observable(data.milling_preference || "Milled"); 
 
     } 
 

 
     function Yeast(data){ 
 
      var self = this; 
 
      self.name = ko.observable(data.name || "White Wine"); 
 
      self.current_filter = ko.observable("-Any-"); 
 
      var yeast_options = [ 
 
       {category: 'Danstar', yeasts: ['Danstar 1', 'Danstar 2']}, 
 
       {category: 'Fermentis', yeasts: ['West Coast', 'American Saison', 'White Wine']}, 
 
       {category: 'White Labs', yeasts: ['White 1', 'White Saison']}, 
 
      ]; 
 
      self.yeast_groups_individual = ko.observableArray(); 
 
      ko.computed(function(){ 
 
       if (self.current_filter() !== "-Any-"){ 
 
        var options = _.filter(yeast_options, function(option){ 
 
         return option.category === self.current_filter(); 
 
        }) 
 
       } else{ 
 
         self.yeast_groups_individual(yeast_options); 
 
        } 
 
       } 
 
      ); 
 
      self.yeast_categories = ko.observableArray(); 
 
      ko.computed(function(){ 
 
       var starter_list = ['-Any-']; 
 
       var categories = _.pluck(self.yeast_groups_individual(), 'category'); 
 
       var final = starter_list.concat(categories); 
 
       self.yeast_categories(final); 
 
      }) 
 
     } 
 

 
     function TaskListViewModel() { 
 
      var self = this; 
 

 
      self.recipe_name = ko.observable(""); 
 
      self.hops = ko.observableArray([new Hop({}), new Hop({})]); 
 
      self.fermentables = ko.observableArray([new Fermentable({name: 'test'}), new Fermentable({})]); 
 
      self.yeasts = ko.observableArray([new Yeast({})]); 
 
      self.hops_uses = ko.observableArray(['Boil', 'Dry Hop']); 
 
      self.weight_units = ko.observableArray(['oz', 'lb']); 
 
      self.milling_preferences = ko.observableArray(['Milled', 'Unmilled']); 
 

 
      self.addFermentable = function(){ 
 
       self.fermentables.push(new Fermentable({})) 
 
      } 
 

 
      self.addYeast = function(){ 
 
       self.yeasts.push(new Yeast({})); 
 
      } 
 

 
      self.addHop = function(){ 
 
       self.hops.push(new Hop({})); 
 
      } 
 

 
      self.removeFermentable = function(fermentable){ 
 
       self.fermentables.destroy(fermentable); 
 
      } 
 

 
      self.removeYeast = function(yeast){ 
 
       self.yeasts.destroy(yeast); 
 
      } 
 

 
      self.removeHop = function(hop){ 
 
       self.hops.destroy(hop); 
 
      } 
 

 
      self.removeItem = function(item, name){ 
 
       name.remove(function(hop){ 
 
        return hop.name === item.name; 
 
       }); 
 
       console.log(name()); 
 
       console.log(self.hops()); 
 
      } 
 

 
      self.prepareJSON = function(){ 
 
       object = { 
 
        fermentables: self.fermentables(), 
 
        hops: self.hops(), 
 
        yeasts: self.yeasts(), 
 
       } 
 
       return object 
 
      } 
 

 
      self.saveRecipeData = function(){ 
 
       var data_to_send = ko.toJSON(self); 
 
       var recipe_data = ko.toJSON(self.prepareJSON()); 
 
       alert("This is the data you're sending (universal Javascript object notation):\n\n" + recipe_data) 
 
       $.ajax({ 
 
        url: "http://127.0.0.1:5000/receive-recipe", 
 
        headers: { 
 
         "Content-Type": "application/json" 
 
        }, 
 
        method: "POST", 
 
        dataType: "json", 
 
        data: data_to_send, 
 
        success: function(data){ 
 
         console.log("Success! Saved the recipe"); 
 
        } 
 
       }); 
 
      } 
 
     } 
 
     ko.applyBindings(new TaskListViewModel());
<style> 
 
     .setuprow label { 
 
      margin: 8px 0 0; 
 
      display: block; 
 
      clear: both; 
 
     } 
 
    </style> 
 
    <script type='text/javascript' src='https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.1/knockout-min.js'></script> 
 
    <script type='text/javascript' src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js'></script> 
 
    <script type='text/javascript' src='https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js'></script> 
 
<div class="setuprow"> 
 
     <label>Recipe Name:</label> 
 
     <input type="text" data-bind="value: recipe_name" maxlength="250" class="recipeSetupText" /> 
 
    </div> 
 
    <div class="setuprow"> 
 
     <label>Brew Method:</label> 
 
     <select class="recipeSetupSelect"> 
 
      <option value="extract" selected>Extract</option> 
 
      <option value="partialmash">Mini-Mash</option> 
 
      <option value="allgrain">All Grain</option> 
 
      <option value="biab">Brew-in-a-bag</option> 
 
     </select> 
 
    </div> 
 

 
    <div class="setuprow"> 
 
     <label>Batch Size:</label> 
 
     <input type="text" value="5" maxlength="6" style="width: 60px" /> <span class="unit">(gallons)</span> 
 
    </div> 
 

 
    <div class="setuprow"> 
 
     <label>Style:</label> 
 
     <select class="recipeSetupSelect"> 
 
      <option value="--">--</option> 
 
      <option value="Standard American Beer">1. Standard American Beer</option> 
 
      <option value="International Lager">2. International Lager</option> 
 
      <option value="Czech Lager">3. Czech Lager</option> 
 
      <option value="Pale Malty European Lager">4. Pale Malty European Lager</option> 
 
      <option value="Pale Bitter European Beer">5. Pale Bitter European Beer</option> 
 
      <option value="Amber Malty European Lager">6. Amber Malty European Lager</option> 
 
      <option value="Amber Bitter European Lager">7. Amber Bitter European Lager</option> 
 
      <option value="Dark European Lager">8. Dark European Lager</option> 
 
     </select> 
 
    </div> 
 

 
    <div> 
 
     <label>Boil Time:</label> 
 
     <input type="text" value="60" maxlength="3" style="width: 60px" /> <span class="unit">(minutes)</span> 
 
    </div> 
 

 
    <div class="row"> 
 
     <h2>Fermentables</h2> 
 
     <div data-bind="foreach: fermentables"> 
 
      <label>Name:</label> 
 
      <input type="text" data-bind="value: name"/> 
 
      <label>Amount:</label> 
 
      <input style="width: 45px;" type="number" min="0" data-bind="value: pounds"/> lb 
 
      <input style="width: 55px;" type="number" min="0" data-bind="value: ounces"/> oz 
 
      <label>Milling preference: </label> 
 
      <select data-bind="options: $root.milling_preferences, value: weight_unit"> 
 
      </select> 
 
      <a href="#" data-bind="click: $root.removeFermentable, visible: $root.fermentables.countVisible() > 1"> 
 
       Delete 
 
      </a> 
 
      <br><br> 
 
     </div> 
 

 
     <input data-bind="click: addFermentable" type="button" value="Add Fermentable" /> 
 
    </div> 
 

 
    <div class="row"> 
 
     <h2 class="">Yeast</h2> 
 
     <div data-bind="foreach: yeasts"> 
 
      <span>Yeast Brand Filter:</span> 
 
      <select data-bind="options: yeast_categories, value: current_filter" id="yeast-brand-select"> 
 
      </select> 
 
      <br/> 
 
      <span>Yeast Variety:</span> 
 
      <select id="yeast-variety-select" style="width:325px" data-bind="value: name"> 
 
       <option value="-"> - </option> 
 
        <!-- ko foreach: yeast_groups_individual --> 
 
        <optgroup data-bind="attr: {label: category}"> 
 
         <!-- ko foreach: yeasts --> 
 
          <option data-bind="value: $data, text: $data"></option> 
 
         <!-- /ko --> 
 
        </optgroup> 
 
       <!-- /ko --> 
 
      </select> 
 
      <a href="#" data-bind="click: $root.removeYeast, visible: $root.yeasts.countVisible() > 1">Delete</a> 
 
      <br><br> 
 
     </div> 
 
     <br> 
 
     <input data-bind="click: addYeast" type="button" value="Add Yeast"/> 
 
    </div> 
 

 
    <div class="row"> 
 
     <h2 class="">Hops</h2> 
 
     <div data-bind='foreach: hops'> 
 
      <label>Hop:</label> <input type="text" data-bind="value: name" > 
 
      <label>Amount:</label> 
 
      <input type="number" data-bind="value: amount" maxlength="6"> oz 
 

 
      Time: <input type="text" data-bind="value: time" > 
 
      Min. 
 
      Use: <select data-bind="options: $root.hops_uses, value: use"></select> 
 

 
      <a href="#" data-bind="click: function() { $root.removeItem($data, $root.hops) }, visible: $root.hops.countVisible() > 1">Delete</a> 
 

 
      <br><br> 
 
     </div> 
 

 
     <br> 
 

 
     <input data-bind="click: addHop" type="button" value="Add Hop" /> 
 
    </div> 
 

 
    <p> 
 
     <button data-bind="click: saveRecipeData">Save recipe</button> 
 
    </p>

Wie kann ich die yeast_groups_individual beobachtbaren Array-Update machen, wenn die current_filter geändert wird? Danke

Antwort

0

Die beste Antwort, die ich bis jetzt gefunden habe, ist, das Hauptarray dauerhaft an das ViewModel angeschlossen zu haben, und eine Kopie davon (das yeast_options) an jede Hefe weitergegeben, wo es jetzt mit diesem Array ohne Schaden spielen kann andere Hefe Verhalten:

 ko.observableArray.fn.countVisible = function(){ 
 
      return ko.computed(function(){ 
 
       var items = this(); 
 

 
       if (items === undefined || items.length === undefined){ 
 
        return 0; 
 
       } 
 

 
       var visibleCount = 0; 
 

 
       for (var index = 0; index < items.length; index++){ 
 
        if (items[index]._destroy != true){ 
 
         visibleCount++; 
 
        } 
 
       } 
 

 
       return visibleCount; 
 
      }, this)(); 
 
     }; 
 

 
     function Hop(data) { 
 
      this.name = ko.observable(data.name || ""); 
 
      this.amount = ko.observable(data.amount || ""); 
 
      this.time = ko.observable(data.time || ""); 
 
      this.use = ko.observable(data.use || "Boil"); 
 
     } 
 

 
     function Fermentable(data) { 
 
      this.name = ko.observable(data.name || ""); 
 
      this.pounds = ko.observable(data.pounds || ""); 
 
      this.ounces = ko.observable(data.ounces || ""); 
 
      this.weight_unit = ko.observable(data.weight_unit || "oz"); 
 
      this.milling_preference = ko.observable(data.milling_preference || "Milled"); 
 
     } 
 

 
     function Yeast(data){ 
 
      var self = this; 
 
      var permanent_yeast_options = data.yeast_options; 
 
      self.name = ko.observable(data.name || "-"); 
 
      self.current_filter = ko.observable("-Any-"); 
 
      self.yeast_groups_individual = ko.computed(function(){ 
 
       if (self.current_filter() !== "-Any-"){ 
 
        var options = _.filter(data.yeast_options, function(option){ 
 
         return option.category === self.current_filter(); 
 
        }); 
 
        return options; 
 
       } else{ 
 
         return permanent_yeast_options; 
 
        } 
 
       } 
 
      ); 
 
      self.yeast_categories = ko.observableArray(); 
 
      ko.computed(function(){ 
 
       var starter_list = ['-Any-']; 
 
       var categories = _.pluck(permanent_yeast_options, 'category'); 
 
       var final = starter_list.concat(categories); 
 
       self.yeast_categories(final); 
 
      }) 
 
     } 
 

 
     function TaskListViewModel() { 
 
      var self = this; 
 
      self.hops_uses = ko.observableArray(['Boil', 'Dry Hop']); 
 
      self.weight_units = ko.observableArray(['oz', 'lb']); 
 
      self.milling_preferences = ko.observableArray(['Milled', 'Unmilled']); 
 
      self.recipe_name = ko.observable(""); 
 
      self.hops = ko.observableArray([new Hop({}), new Hop({})]); 
 
      self.fermentables = ko.observableArray([new Fermentable({name: 'test'}), new Fermentable({})]); 
 
      self.yeast_options = [ 
 
       {category: 'Danstar', yeasts: ['Danstar 1', 'Danstar 2']}, 
 
       {category: 'Fermentis', yeasts: ['West Coast', 'American Saison', 'White Wine']}, 
 
       {category: 'White Labs', yeasts: ['White 1', 'White Saison']}, 
 
      ]; 
 
      self.yeasts = ko.observableArray([new Yeast({yeast_options: self.yeast_options})]); 
 
      self.addFermentable = function(){ 
 
       self.fermentables.push(new Fermentable({})) 
 
      } 
 

 
      self.addYeast = function(){ 
 
       self.yeasts.push(new Yeast({yeast_options: self.yeast_options})); 
 
      } 
 

 
      self.addHop = function(){ 
 
       self.hops.push(new Hop({})); 
 
      } 
 

 
      self.removeFermentable = function(fermentable){ 
 
       self.fermentables.destroy(fermentable); 
 
      } 
 

 
      self.removeYeast = function(yeast){ 
 
       self.yeasts.destroy(yeast); 
 
      } 
 

 
      self.removeHop = function(hop){ 
 
       self.hops.destroy(hop); 
 
      } 
 

 
      self.removeItem = function(item, name){ 
 
       name.remove(function(hop){ 
 
        return hop.name === item.name; 
 
       }); 
 
       console.log(name()); 
 
       console.log(self.hops()); 
 
      } 
 

 
      self.ingredient_filter = function(the_array){ 
 
       var options = _.filter(the_array, function(item){ 
 
        return item.name != "" && item.name != "-"; 
 
       }); 
 
       return options; 
 
      } 
 

 
      self.prepareJSON = function(){ 
 
       object = { 
 
        fermentables: self.fermentables(), 
 
        hops: self.hops(), 
 
        yeasts: self.yeasts(), 
 
       } 
 
       return object 
 
      } 
 

 
      self.saveRecipeData = function(){ 
 
       var data_to_send = ko.toJSON(self); 
 
       var recipe_data = ko.toJSON(self.prepareJSON()); 
 
       alert("This is the data you're sending (universal Javascript object notation):\n\n" + recipe_data) 
 
       $.ajax({ 
 
        url: "http://127.0.0.1:5000/receive-recipe", 
 
        headers: { 
 
         "Content-Type": "application/json" 
 
        }, 
 
        method: "POST", 
 
        dataType: "json", 
 
        data: recipe_data, 
 
        success: function(data){ 
 
         console.log("Success! Saved the recipe"); 
 
        } 
 
       }); 
 
      } 
 
     } 
 
     ko.applyBindings(new TaskListViewModel());
<head> 
 

 
    <style> 
 
     body { 
 
      margin: 30px; 
 
      padding: 30px; 
 
     } 
 
     .setuprow label { 
 
      margin: 8px 0 0; 
 
      display: block; 
 
      clear: both; 
 
     } 
 
    </style> 
 
    <script type='text/javascript' src='https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.1/knockout-min.js'></script> 
 
    <script type='text/javascript' src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js'></script> 
 
    <script type='text/javascript' src='https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js'></script> 
 
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> 
 
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> 
 

 
</head> 
 

 
<body> 
 
    <div class="setuprow"> 
 
     <label>Recipe Name:</label> 
 
     <input type="text" data-bind="value: recipe_name" maxlength="250" class="recipeSetupText" /> 
 
    </div> 
 
    <div class="setuprow"> 
 
     <label>Brew Method:</label> 
 
     <select class="recipeSetupSelect"> 
 
      <option value="extract" selected>Extract</option> 
 
      <option value="partialmash">Mini-Mash</option> 
 
      <option value="allgrain">All Grain</option> 
 
      <option value="biab">Brew-in-a-bag</option> 
 
     </select> 
 
    </div> 
 

 
    <div class="setuprow"> 
 
     <label>Batch Size:</label> 
 
     <input type="text" value="5" maxlength="6" style="width: 60px" /> <span class="unit">(gallons)</span> 
 
    </div> 
 

 
    <div class="setuprow"> 
 
     <label>Style:</label> 
 
     <select class="recipeSetupSelect"> 
 
      <option value="--">--</option> 
 
      <option value="Standard American Beer">1. Standard American Beer</option> 
 
      <option value="International Lager">2. International Lager</option> 
 
      <option value="Czech Lager">3. Czech Lager</option> 
 
      <option value="Pale Malty European Lager">4. Pale Malty European Lager</option> 
 
      <option value="Pale Bitter European Beer">5. Pale Bitter European Beer</option> 
 
      <option value="Amber Malty European Lager">6. Amber Malty European Lager</option> 
 
      <option value="Amber Bitter European Lager">7. Amber Bitter European Lager</option> 
 
      <option value="Dark European Lager">8. Dark European Lager</option> 
 
     </select> 
 
    </div> 
 

 
    <div> 
 
     <label>Boil Time:</label> 
 
     <input type="text" value="60" maxlength="3" style="width: 60px" /> <span class="unit">(minutes)</span> 
 
    </div> 
 

 
    <div class="row"> 
 
     <h2>Fermentables</h2> 
 
     <div data-bind="foreach: fermentables"> 
 
      <label>Name:</label> 
 
      <input type="text" data-bind="value: name"/> 
 
      <label>Amount:</label> 
 
      <input style="width: 45px;" type="number" min="0" data-bind="value: pounds"/> lb 
 
      <input style="width: 55px;" type="number" min="0" data-bind="value: ounces"/> oz 
 
      <label>Milling preference: </label> 
 
      <select data-bind="options: $root.milling_preferences, value: weight_unit"> 
 
      </select> 
 
      <a href="#" data-bind="click: $root.removeFermentable, visible: $root.fermentables.countVisible() > 1"> 
 
       Delete 
 
      </a> 
 
      <br><br> 
 
     </div> 
 

 
     <input data-bind="click: addFermentable" type="button" value="Add Fermentable" /> 
 
    </div> 
 

 
    <div class="row"> 
 
     <h2 class="">Yeast</h2> 
 
     <div data-bind="foreach: yeasts"> 
 
      <span>Yeast Brand Filter:</span> 
 
      <select data-bind="options: yeast_categories, value: current_filter" id="yeast-brand-select"> 
 
      </select> 
 
      <br/> 
 
      <span>Yeast Variety:</span> 
 
      <select id="yeast-variety-select" style="width:325px" data-bind="value: name"> 
 
       <option value="-"> - </option> 
 
        <!-- ko foreach: yeast_groups_individual --> 
 
        <optgroup data-bind="attr: {label: category}"> 
 
         <!-- ko foreach: yeasts --> 
 
          <option data-bind="value: $data, text: $data"></option> 
 
         <!-- /ko --> 
 
        </optgroup> 
 
       <!-- /ko --> 
 
      </select> 
 
      <a href="#" data-bind="click: $root.removeYeast, visible: $root.yeasts.countVisible() > 1">Delete</a> 
 
      <br><br> 
 
     </div> 
 
     <br> 
 
     <input data-bind="click: addYeast" type="button" value="Add Yeast"/> 
 
    </div> 
 

 
    <div class="row"> 
 
     <h2 class="">Hops</h2> 
 
     <div data-bind='foreach: hops'> 
 
      <label>Hop:</label> <input type="text" data-bind="value: name" > 
 
      <label>Amount:</label> 
 
      <input type="number" data-bind="value: amount" maxlength="6"> oz 
 

 
      Time: <input type="text" data-bind="value: time" > 
 
      Min. 
 
      Use: <select data-bind="options: $root.hops_uses, value: use"></select> 
 

 
      <a href="#" data-bind="click: function() { $root.removeItem($data, $root.hops) }, visible: $root.hops.countVisible() > 1">Delete</a> 
 

 
      <br><br> 
 
     </div> 
 

 
     <br> 
 

 
     <input data-bind="click: addHop" type="button" value="Add Hop" /> 
 
    </div> 
 

 
    <p> 
 
     <button data-bind="click: saveRecipeData">Save recipe</button> 
 
    </p> 
 

 
    
 
</body>

Verwandte Themen