0
votes

I am building a large HTML form using Backbone. Each form field is an instance of a Backbone model called Field. I have a Backbone collection called Fields that fetches a JSON file and instantiates all the form fields.

Here's my issue: When I render the collection of form fields, I don't simply want a uniform list of form fields. For example, most backbone tutorials online show you how to render collections by wrapping each model's view in an li with the collection element being a ul.

Rather, I have an HTML template that is broken up into sections like so:

I'd like the "month" and "year" fields to be in one div while the other fields go into their respective divs. The fields will be styled differently from one another using CSS. Is it possible to pass a large underscore template to a collection and have it print its model instances into the appropriate places?

Is this a use case for something like Marionette.Region?

Any thoughts are appreciated!

4
I think you're using Backbone incorrectly. The form should be rendering off one model, and should really be one template because you're not really looping through anything - Bojangles

4 Answers

0
votes

I see 2 main approaches for your problem:

  1. The simpler way: Make your form be one big itemView and pass it a form model with a fields property (which would be your collection). Then, within the view, you need to iterate and generate the html.

  2. The cleaner way: Use a layout for your form, and render additional layouts into the "time", "location", etc. regions (as suggested by Lilith). For example, the "time" layout would contain the "month" and "year" views. The "month" view, in turn, would be a collection view rendering each option in the collection into an option for the select tag.

Although the first solutions tends to be simpler to implement (because it's closer to traditional stateless web development), the second one will be easier to manage. You'll be able to register event handlers on each view (e.g. select tag) without naming collisions, and since the form's complexity will be broken down into individual pieces, it will be easier to manage down the road.

0
votes

I'm not sure I totally understand you question, but I think you may need more info in your field model. For example you could include a group property in the field model and then render all fields form the same group in its own div.

Is this what you're trying to do?

0
votes

I would choose another approach: Break up the one template into at least different templates (Time, Location, VehicleInfo), because, these are three different topics, which I would handle in separate views. After that breaking up the Time-View into a Month and a Year view and so on.

Accordingly each subview has its own model with values to render its HTML. I see no sense in using a Collection here - since you have heterogenous 'fields' / Models.

After that I would use something like a form backing Model, which represents the current state of the form. So the implementation of a formView as a super view and the other views as nested views would be a good choice.

var FormView = new Backbone.View.extend({

initialize: function(){
    //initialize all subviews
    },
    events:{
        "change":"formChanged"
    }
    formChanged:function(element){
        //update formBackingObject aka this.model
    }
});

Then you have a clear separation for all of your views and one model to represent the state of the current selections.

0
votes

I think you can make use of Marionette CollectionView. With collection view, you can specify different view for each item in the collection. See the documentation; https://github.com/marionettejs/backbone.marionette/blob/master/docs/marionette.collectionview.md#collectionviews-itemview If you want control over where items will be rendered, you can override appendHtml to indicate how itemView's will be appended to collectionView