2013-05-13 109 views
1

我完全失去了如何實現以下問題的解決方案:如何呈現和保存骨幹模型的動態屬性?

我有一個骨幹視圖,填充了來自骨幹模型的屬性。在此視圖中,顯示屬性,對於其中一個屬性,用戶需要能夠添加或修改現有屬性。這最適合作爲骨幹模型中的一組屬性(我認爲)。

我加入的js fiddle here

測試用例正如你可以在小提琴看到,狗的favorite_snacks可以由用戶加入,但我對如何編寫代碼來解析被完全掙扎並在實例化視圖時將其渲染,然後成功將它們保存回mysql數據庫。

我非常感謝這方面的幫助,整個週末我一直在頭撞我的桌子,試圖弄清楚它。

回答

0

確保視圖和模型獨立並完全分離,以便您的代碼可以在以後管理,總是一個更好的主意。

所以在這種情況下,每個寵物可以有一個或許多最喜歡的零食。因此,基本上你期望小吃在這裏,而不是單一小吃模型。

因此,最好創建一個單獨的小吃集合,然後Snack Model。然後保持一個獨立的視圖SnackListItem,然後遍歷的SnackCollection列表和渲染視圖每個項目..

所以對他們倆的

<div id="foo"></div> 
<script type="text/template" id="pet-view-template"> 
    <p> <span><b> Dog Name: </b> </span> <%= name %> </p> 
     <p> <span><b> Dog Color: </b></span> <%= color %> </p> 
    <h4> favorite snacks </h4> 
    <ul class="snacks-list"> 
    </ul> 
    snack name: <input type="text" class="snack-name" /> 
    cost : <input type="text" class="snack-cost" />  
    <button class="add-snack">add snack</button > 
</script> 

<script type="text/template" id="snack-view-template"> 
    <b>snack name:</b> <span> <%=favorite_snacks %> </span> :: 
    <b>cost: </b><span> <%= favorite_snack_cost %> </span> 

     <b class="toggle-change"> Change </b> 
     <span class="modify-fields hide"> 
      <b class="modify">snack name:</b> <input type="text" class="modify-name" data-key="favorite_snacks" /> 
      <b class="modify">snack cost:</b> <input type="text" class="modify-cost" data-key="favorite_snack_cost" />  
     </span> 
</script> 

我創建了一個獨立的視圖,並創建獨立的模板小吃集合的模型。 這仍然可以優化。

的Javascript

// Create a Dog Model 
var Dog = Backbone.Model.extend({ 
    defaults: { 
     name: 'New dog', 
     color: 'color' 
    } 
}); 

// Create a collection of dogs 
var Dogs = Backbone.Collection.extend({ 
    model: Dog 
}); 

// Create a model for Snacks 
var Snack = Backbone.Model.extend({ 
    defaults: { 
     favorite_snacks: 'bacon', 
     favorite_snack_cost: '52' 
    } 
}); 

// Create a collection of Snacks 
var Snacks = Backbone.Collection.extend({ 
    model: Snack 
}); 

// Define the model for a Dog 
var dog = new Dog({ 
    name: "Spot", 
    color: "white" 
}); 

// Create a View for the Snack Item 
var SnackItemView = Backbone.View.extend({ 
    tagName : 'li', 
    className: 'snacks', 
    template: _.template($('#snack-view-template').html()), 
    initialize: function() { 
     // Need to bind to save the context of this to the view 
     _.bind('toggleChange', this); 
     // Need to listen to the Model change event and render the view again 
     // as the new data has to be reflected 
     this.listenTo(this.model, 'change' , this.render); 
    },  
    // Assign events for the fields inside Snacks view 
    events : { 
     'click .toggle-change' : 'toggleChange', 
     'change input'   : 'modifyData' 
    }, 
    toggleChange: function() { 
     var $change = $('.modify-fields', this.$el); 
     $change.hasClass('hide') ? $change.removeClass('hide') : $change.addClass('hide'); 
    }, 
    // This will captue the data from the inputs and trigger the change event on the model 
    modifyData: function(e) { 
     var value = $(e.currentTarget).val(), 
      key = $(e.currentTarget).data('key'); 
     this.model.set(key,value); 
    }, 
    render: function() { 
     this.$el.html(this.template(this.model.toJSON())); 
     return this; 
    } 
}); 

var PetView = Backbone.View.extend({ 
    el: '#foo', 
    template: _.template($('#pet-view-template').html()), 
    initialize: function() { 
     this.collection = (this.collection && this.collection instanceof Backbone.Collection) || new Snacks(Snack); 
    }, 
    events: { 
     'click .add-snack' : 'addSnack' 
    }, 
    addSnack: function() { 
     // Render new snack Item 
     var newSnack = new Snack({ 
      favorite_snacks: $('.snack-name', this.$el).val(), 
      favorite_snack_cost: $('.snack-cost', this.$el).val() 
     }); 
     this.renderSnackView(newSnack); 
     // Clear the inputs 
     $('input', this.$el).val(''); 
    }, 
    // render each snack view 
    renderSnackView: function (snack) { 
     var snackView = new SnackItemView({ 
      model: snack 
     }); 
     $('.snacks-list', this.$el).append(snackView.el); 
     snackView.render(); 
    }, 
    render: function() { 
     var thisView = this; 
     // Append the PetView 
     this.$el.html(this.template(this.model.toJSON())); 
     // Iterate over each snack collection of the pet and render that item 
     _.each(this.collection.models, function (snack) { 
      thisView.renderSnackView(snack); 
     }); 
     return this; 
    } 
}); 



var petView = new PetView({ 
    model: dog 
}); 
petView.render(); 

Check the working fiddle

我已經用註釋來解釋一些代碼。最初學習骨幹網很困難,因爲我剛剛開始使用它,我知道我經歷的麻煩。但一旦你習慣了它,它是非常簡單但功能強大..希望這會有所幫助:)

但是,當您嘗試構建應用程序時,您需要銷燬未使用的視圖和事件以減少內存泄漏。