I'm in the process of hacking/learning my way though backbone.js. For some reason I can follow the #account model instance all the way down to the view but in the template when I do <%= account.get('name') %> nothing is returned. When I do <%= account %> I get [object Object]
Am I simply using the wrong tag to display account?
Anyways, here's my code.
Router: shows.js.coffee:
class AppName.Routers.Shows extends Backbone.Router
routes:
'': 'index'
initialize: ->
# Fetch Show Dates
#collection = new AppName.Collections.Shows
#collection.fetch()
# Fetch Account Info
#account = new AppName.Models.Account
#account.fetch()
index: ->
# Shows
view = new AppName.Views.ShowsIndex(collection: #collection)
$('div.shows_container').html(view.render().el)
# Account
view = new AppName.Views.Account(model: #account)
$('div.account_container').html(view.render().el)
Model: show.js.coffee
class AppName.Models.Account extends Backbone.Model
urlRoot: 'api/account'
View: show.js.cofee
class AppName.Views.Account extends Backbone.View
template: JST['accounts/show']
render: ->
$(#el).html(#template(account: #model))
this
Template: show.jst.ejs
<%= account.get('name') %>
Related
I'm walking into a large Backbone.js project so I'm still getting my bearings. My template, my-group-item.jhbs has:
{{#if isComplete}}
.row-fluid
.span2
img.entity-image(src="/pictures/{{entityId}}.png")
.span10
.row-fluid
.span12
h3 {{entityName}}
p My first variable {{totalFirst}} and my second variable {{totalValue}}
{{/if}}
My View is:
module.exports = class MyItemView extends View
className: ->
templateData = #getTemplateData()
primaryData = #model.get('primaryData')
tagName: 'li'
template: require 'views/my-group-item'
initialize: () ->
super
primaryData = #model.get('primaryData')
In my template, the totalFirst and totalValue variables show nothing.
I'm calling my view with:
#groupView = new MyItemView
collection: groups
el: '.group-list'
How can I get these to show in the template?
You could pass more than 1 variable to your template, the first being your model and the second being the attributes of primaryData.
I have an API resource that gives me a list of users that each have several items. The hierarchy is like so:
- users
- user
- items
- item
- item
- item
- user
- items
- item
- item
- item
I would like to display the list of users on a single page, with each user entry displaying each of its items on the page as well.
When any one of these items is clicked, it should set an chosen attribute that is accessible through the overall users collection.
I'm having difficulty getting the item click information to bubble back up. My current implementation is creating a separate items collection in order to render the view, but then I lose the connection to its original user model, so I can't notify it when the item is selected.
My views are structured like so:
class List.Item extends Marionette.ItemView
template: "path/to/template"
events:
"click" : "choose"
choose: (e) ->
# what to do?
class List.User extends Marionette.CompositeView
collection: #collection
template: "path/to/template"
itemView: List.Item
itemViewContainer: "span"
initialize: ->
#collection = new App.Entities.Items(#model.get("items"), parent: #)
events:
"click a" : "toggleChoose"
#include "Chooseable"
class List.Users extends Marionette.CollectionView
itemView: List.User
Is there a better way to structure these collections or views, or is there a way to pass the information from the List.Item view to the parent List.User view and then into the users collection?
EDIT
I have tried backbone-relational, but it didn't seem to quite do what I need. Please correct me if I'm wrong here.
Your List.Item should contain it's current model with all properties at the time when choose is triggered. In this way, you can trigger other events with the List.Item's model values:
choose(e) : ->
trigger("mylistitem:choose", model)
Then listen for the event elsewhere :
itemView.on("itemview:mylistitem:choose", ( childView, model ) -> {
alert(model.get('..whatever..')
}
It is actually possible to instantiate the items collection to reference the parent user and vice-versa directly in Backbone:
class Entities.User extends Backbone.Model
...
initialize: ->
#items = new Entities.Items #get("items"),
user: #
class Entities.Items extends Backbone.Collection
...
initialize: (models, options) ->
#user = options?.user
So now the List.User CompositeView can pass this information to the List.Item ItemView:
class List.User extends Marionette.CompositeView
collection: #collection
...
initialize: ->
#collection = #model.items
With this in place, it is possible to access the user directly from the ItemView:
class List.Item extends Marionette.ItemView
...
events:
"click" : "choose"
choose: (e) ->
e.preventDefault()
user = #model.collection.user
console.log "user: ", user
And from there it's possible to take any necessary actions on the user and its collection.
I'm following Brian Mann's tutorial on building an application in Backbone + Marionette (~35min into Ep08), and I'm having problems with a controller inserting content into the main region rather than one of its sub-regions.
The page layout is structured like so:
<div id="header-region"></div>
<div id="main-region"></div>
<div id="footer-region"></div>
And I'm trying to insert content into an #admin-navs-region, which is to be nested under the #admin-list region inside of the #main-region:
<!-- admin/list/templates/list_layout; inserted into #main-region -->
<div id="admin-list">
<div id="banner-region"></div>
<div id="admin-navs-region"></div>
<div id="article-region"></div>
</div>
The controller in question is as follows:
#PE.module "AdminApp.List", (List, App, Backbone, Marionette, $, _) ->
class List.Controller extends App.Controllers.Application
initialize: ->
adminNavs = App.request "admin:nav:entities"
#layout = #getLayoutView()
#listenTo #layout, "show", => ## LINES IN QUESTION
#bannerRegion() ## LINE 11
#listRegion adminNavs ## LINE 12
#show #layout
bannerRegion: ->
bannerView = #getBannerView()
#show bannerView, region: #layout.bannerRegion
listRegion: (adminNavs) ->
listView = #getListView adminNavs
#show listView, region: #layout.adminNavsRegion
getListView: (adminNavs) ->
new List.Navs
collection: adminNavs
getBannerView: ->
new List.Banner
getLayoutView: ->
new List.Layout
And the corresponding view:
#PE.module "AdminApp.List", (List, App, Backbone, Marionette, $, _) ->
class List.Layout extends App.Views.Layout
template: "admin/list/list_layout"
regions:
bannerRegion: "#banner-region"
articleRegion: "#article-region"
adminNavsRegion: "#admin-navs-region"
class List.Banner extends App.Views.ItemView
template: "admin/list/_banner"
class List.Nav extends App.Views.ItemView
template: "admin/list/_nav"
tagName: "li"
class List.Navs extends App.Views.CollectionView
tagName: "ul"
className: "side-nav"
itemView: List.Nav
When I comment out the LINES IN QUESTION (see 3rd code snippet), the list_layout is rendered properly within the #main-region. However, if I uncomment LINE 11 or LINE 12, #admin-list is being entirely replaced with the List.Banner or List.Nav templates, rather than inserting into the specified region.
Everything looks like it should be working to me, but instead of insertion into the correct region, the code is simply replacing everything inside of #main-region.
Does anyone know how to start debugging this?
Solved after realizing this is from some peculiar coffeescript / Backbone / Marionette interactions...
I'm using tabs (not spaces) to indent my coffeescript, and I had:
<tab> class List.Layout extends App.Views.Layout
<space><space><tab> template: "admin/list/list_layout"
For whatever reason, this doesn't break things but rather causes Marionette to render over the parent section. Fixed this by replacing the <space><space> with a <tab>:
<tab> class List.Layout extends App.Views.Layout
<tab><tab> template: "admin/list/list_layout"
Just one of those Mondays...
Backbone.LocalStorage stores a list of players client-side when calling create on a players collection, but the stored models are not being fetched later, even though I can inspect them in localStorage. I can call #collections.players.localStorage.findAll() to retrieve all the stored objects and manually push them onto my collection.
class App.Models.Player extends Backbone.Model
defaults:
name: 'Unnamed'
team: 'Unassigned'
class App.Collections.Players extends Backbone.Collection
localStorage: new Backbone.LocalStorage('players')
model: App.Models.Player
class App.ViewModels.Game extends kb.ViewModel
constructor: ->
#collections =
players: new App.Collections.Players()
#collections.players.fetch(
success: (collection) =>
console.log(collection) # shows none
console.log(#collections.players.localStorage.findAll())
# shows all the stored players
)
# #players below is rendered by a foreach in a knockout template
#players = kb.collectionObservable #collections.players, { view_model: App.ViewModels.Player }
addPlayer: -> # called when a button is pressed
#collections.players.create(new App.Models.Player({ name: 'New Player' }))
return
Why is Knockback unable to fetch the stored entities automatically?
The following call manually retrieves all objects:
_.each #collections.players.localStorage.findAll(), (elem) =>
#collections.players.add(elem)
This :
#model
Returns :
Object { type="conjugation", verb="ser", yo="soy", more...}
But when I try :
#model.toJSON()
I get :
TypeError: this.model.toJSON is not a function
I am trying to eventually complete this line :
$(#el).html(#template(#model.toJSON() ))
So that I can render this object in a Show with my template.
Any recommendations?
Update
Persuant the comments. I have this as a model, but I can see now how they're are not related.
class AiProject.Models.Verb extends Backbone.Model
paramRoot: 'verb'
I'm going to try and instantiate this type of verb.
class AiProject.Routers.QuestionsRouter extends Backbone.Router
initialize: (options) ->
#verb = new AiProject.Models.Verb
#verb = options.words
And then back to my View :
class AiProject.Views.Questions.ConjugationView extends Backbone.View
template: JST["backbone/templates/questions/conjugation"]
render: ->
$(#el).html(#template(#model.toJSON() ))
Still get the same error though..
It looks like you're setting your model correctly at first, then overwriting it with the value options.words.
Instead of this:
class AiProject.Routers.QuestionsRouter extends Backbone.Router
initialize: (options) ->
#verb = new AiProject.Models.Verb
#verb = options.words
Try this:
class AiProject.Routers.QuestionsRouter extends Backbone.Router
initialize: (options) ->
#verb = new AiProject.Models.Verb(options.words)
That creates your model and passes in options.words to be set as the model's attributes.