2013-04-26 7 views
8

So bin ich fest. Ich habe die große Backbone.Marionette, um meine verschachtelten Childs/Eltern-Beziehungen und Rendering (tun es mit dem nackten Rücken war ein Albtraum) behandeln, aber jetzt habe ich Probleme mit meiner verschachtelten Composite-Ansicht,Backbone Marionette Nested Composite Ansehen

Ich bin immer Getting a Die angegebene itemViewContainer wurde nicht gefunden: .tab-content von der übergeordneten Verbundansicht - CategoryCollectionView, obwohl der itemViewContainer auf der Vorlage verfügbar ist, hier ist, was ich versuche zu tun, habe ich ein Restaurant-Menü, das ich brauche vorhanden, so habe ich mehrere Kategorien und in jeder Kategorie I mehrere Menüpunkte haben, so meine letzte html so sein würde:

<div id="order-summary">Order Summary Goes here</div> 
    <div id="categories-content"> 
     <ul class="nav nav-tabs" id="categories-tabs"> 
       <li><a href="#category-1">Appetizers</a></li> 
     </ul> 
     <div class="tab-content" > 
       <div class="tab-pane" id="category-1"> 
        <div class="category-title">...</div> 
        <div class="category-content">..the category items goes here.</div> 
     </div> 
    </div> 

H ere ist das, was ich bisher:

Zuerst werden die Vorlagen

Template-Skelett

<div id="order-summary"></div> 
<div id="categories-content"></div> 

Template-menu-Kern

<ul class="nav nav-tabs" id="categories-tabs"></ul> 
<div class="tab-content" ></div> 

Template-Kategorie

<div class="category-title"> 
    <h2><%=name%></h2> 
    <%=desc%> 
</div> 
<div class="category-content"> 
    The menu items goes here 
    <ul class="menu-items"></ul> 
</div> 

Template-Menüpunkt

Item <%= name%> 
<strong>Price is <%= price%></strong> 
<input type="text" value="<%= quantity %>" /> 
<a href="javascript:void()" class="add">Add</a> 

nun das Skript

var ItemModel = Backbone.Model.extend({ 
    defaults: { 
     name: '', 
     price: 0, 
     quantity: 0 
    } 
}); 

var ItemView = Backbone.Marionette.ItemView.extend({ 
    template: '#template-menuitem', 
    modelEvents: { 
     "change": "update_quantity" 
    }, 
    ui: { 
     "quantity" : "input" 
    }, 
    events: { 
     "click .add": "addtoBasket" 
    }, 
    addtoBasket: function (e) { 
     this.model.set({"quantity": this.ui.quantity.val() }); 
    }, 
    update_quantity: function() { 
     //@todo should we do a re-render here instead or is it too costy 
     this.ui.quantity.val(this.model.get("quantity")); 
    } 
}); 

var ItemCollection = Backbone.Collection.extend({ 
    model: ItemModel 
}); 



var CategoryModel = Backbone.Model.extend({ 
    defaults: { 
     name: '' 
    } 
}); 

var CategoryView = Backbone.Marionette.CompositeView.extend({ 

    template: '#template-category', 

    itemViewContainer: ".menu-items", 
    itemView: ItemView, 

    className: "tab-pane", 
    id: function(){ 
     return "category-" + this.model.get("id"); 
    }, 

    initialize: function() { 

     this.collection = new ItemCollection(); 
     var that = this; 
     _(this.model.get("menu_items")).each(function (menu_item) { 
      that.collection.add(new ItemModel({ 
       id: menu_item.id, 
       name: menu_item.name, 
       price: menu_item.price, 
       desc: menu_item.desc 
      })); 
     }); 


    } 
}); 


var CategoryCollection = Backbone.Collection.extend({ 
    url: '/api/categories', 
    model: CategoryModel 
}); 

var CategoryCollectionView = Backbone.Marionette.CompositeView.extend({ 

    el_tabs: '#categories-tabs', 

    template: '#template-menu-core', 
    itemViewContainer: ".tab-content", // This is where I'm getting the error 
    itemView: CategoryView, 

    onItemAdded: function (itemView) { 
     alert("halalouya"); 
     //this.$el.append("<li><a href=\"#cateogry-" + tab.get("id") + "\">" + tab.get("name") + "</a></li>"); 

     //$(this.el_tabs).append("<li><a href='#category-" + itemView.model.get("id") + "'>" 
      //+ itemView.model.get("name") + "</a></li>") 
    } 
}); 

Ich weiß, es ist ein bisschen schwer zu folgen, aber ihr seid meine letzte Ausweg. Es gibt keine Probleme mit den Vorlagen und die cateogry fetching und die anderen Dinge (es funktionierte bereits vor der CategoryCollectionView aus einer Puppensammlung in eine zusammengesetzte Ansicht umzuwandeln.)

Edit 1

Added App initalizer auf Anfrage:

  AllegroWidget = new Backbone.Marionette.Application(); 

      AllegroWidget.addInitializer(function (options) { 

       // load templates and append them as scripts 
       inject_template([ 
         { id: "template-menuitem", path: "/js/templates/ordering-widget-menuitem.html" }, 
         { id: "template-category", path: "/js/templates/ordering-widget-category.html" }, 
         { id: "template-menu-core", path: "/js/templates/ordering-widget-menu-core.html" }, 
         { id: "template-skeleton", path: "/js/templates/ordering-widget-skeleton.html" } 
        ]); 

       // create app layout using the skeleton 
       var AppLayout = Backbone.Marionette.Layout.extend({ 
        template: "#template-skeleton", 

        regions: { 
         order_summary: "#order-summary", 
         categories: "#categories-content" 
        } 
       }); 

       AllegroWidget.layout = new AppLayout(); 
       var layoutRender = AllegroWidget.layout.render(); 
       jQuery("#allegro-ordering-widget").html(AllegroWidget.layout.el); 

       // Initialize the collection and views 
       var _category_collection = new CategoryCollection(); 

       var _cateogories_view = new CategoryCollectionView({ api_key: window.XApiKey, collection: _category_collection }); 


       _category_collection.fetch({ 
        beforeSend: function (xhr) { 
         xhr.setRequestHeader("X-ApiKey", window.XApiKey); 
        }, 
        async: false 
       }); 


       //AllegroWidget.addRegions({ 
       /// mainRegion: "#allegro-ordering-widget" 
       //}); 
       AllegroWidget.layout.categories.show(_cateogories_view); 

      }); 



      AllegroWidget.start({api_key: window.XApiKey}); 
+0

ohne Bezug Hinweis. Ich habe festgestellt, dass Sie onItemAdded in Ihrem Code verwenden. Es wurde kürzlich geändert, Sie möchten onBeforeItemAdded verwenden. Siehe meine Antwort in diesem Beitrag http://stackoverflow.com/questions/16180159/adding-a-model-to-a-marionette-collectionviews-collection-doesnt-trigger-onite/16195832#16195832 –

+0

Können Sie den Code teilen erstellt eine Instanz von CategoryCollectionView und ruft region.show() auf? –

+0

@ScottPuleo danke für den Tipp, habe gerade damit zu kämpfen, ich habe den App Initialisierer an die Frage –

Antwort

6

Sie fügen der Sammlung per Abruf hinzu, bevor Sie auf der Region anzeigen.

Marionette.CompositeView ist standardmäßig so verkabelt, dass ItemViews angehängt werden, wenn Modelle zu seiner Sammlung hinzugefügt werden. Dies ist ein Problem, da der itemViewContainer .tab-content nicht zum dom hinzugefügt wurde, da show für die Region nicht aufgerufen wurde.

Einfach zu reparieren, überarbeiten Sie Code wie unten und es sollte ohne overloading appendHtml funktionieren.

// Initialize the collection and views 
var _category_collection = new CategoryCollection(); 

// grab a promise from fetch, async is okay 
var p = _category_collection.fetch({headers: {'X-ApiKey': window.XApiKey}); 

// setup a callback when fetch is done 
p.done(function(data) { 
    var _cateogories_view = new CategoryCollectionView({ api_key: window.XApiKey, collection: _category_collection }); 
    AllegroWidget.layout.categories.show(_cateogories_view); 
}); 
+0

@ScottPuelo great stuff man –

+0

Dies half mir meine marionette Architektur enorm aufzuräumen .. alles funktioniert wirklich jetzt. VIELEN DANK. – MBHNYC

0

okay, das ist ziemlich seltsam, aber das Hinzufügen dieser in der CategoryCollectionView Klasse:

appendHtml: function (collectionView, itemView, index) { 
    //@todo very weird stuff, assigning '.tab-content' to itemViewContainer should have been enough 
    collectionView.$(".tab-content").append(itemView.el); 
} 

löste das Problem, aber ich habe keine Ahnung, warum es funktioniert, assigning '.tab-content' auf den itemViewContainer sollte ausreichen, eine Idee?

+0

angeschlossen Dies funktioniert, weil hier 'Tab-Inhalt' in der View-Methode fest codiert ist. –

+0

Das Problem scheint in der getItemViewContainer-Methode zu sein, die anscheinend aufgerufen wird, bevor die Vorlage gerendert wird. Ich habe diese Methode überschrieben und den Fehler entfernt, nachdem es funktioniert hat. –

Verwandte Themen