I'm rewriting a Backbone.js app trying to use an AMD approach. I've downloaded the AMD-ified versions of Backbone and Underscore. I checked and jQuery, Backbone and Underscore all get called. It's a fairly simple project, but for some reason my collection is no longer being passed to my view. I'm new to AMD.
Here is my model:
define([
'underscore',
'backbone'
], function(_, Backbone) {
var tableModel = Backbone.Model.extend({});
return tableModel;
});
Here is my collection:
define([
'jquery',
'underscore',
'backbone',
'models/tableModel'
],
function($, _, Backbone, tableModel) {
var tablesCollection = Backbone.Collection.extend({
url: this.url, // passed into collection at runtime, so same code can process multiple sets of data
model: tableModel,
initialize: function(models, options) {
if (options && options.url) {
this.url = options.url;
}
this.fetch({
success: function(data, options) {
if ($.isEmptyObject(data.models)) {
App.Collections.Tables.NoData(data);
}
}
});
}
});
return tablesCollection;
});
Here is my view:
define([
'jquery',
'underscore',
'backbone',
'models/tableModel',
'collections/tablesCollection',
'views/tableView'
],
function($, _, Backbone, tableModel, tablesCollection, tableView) {
var tv = Backbone.View.extend({
tagName: 'div',
initialize: function() {
console.log(this.collection); // returns collection and undefined
this.collection.on('reset', this.render, this); // errors: this.collection is undefined
},
render: function() {
return this;
}
});
return tv;
});
Here is where the view and collection are instantiated:
define([
'jquery',
'underscore',
'backbone',
'models/tableModel',
'collections/tablesCollection',
'views/tablesView'
], function($, _, Backbone, tableModel, tablesCollection, tablesView) {
var t = new tablesCollection(null, { url: 'main-contact'} );
var tables = new tablesView({ collection: t, template: 'main-contact-template'});
$('#web-leads').html(tables.render().el);
});
Why am I getting function (){return c.apply(this,arguments)} returned when I console.log(tablesCollection)? It's like the collection is not being passed in. Could it be a paths issue? My project is structured with a js folder with subfolders called collections, models and views. If I console.log(this), I get:
My data is in there, but is this what I need? Why do I not get my collection when I try to console.log it?
Do not use tablesCollection directly. Use this.collection. You have already initialized view with it
What you see is the function tablesCollection, i.e. the Backbone.Collection.extend(...) function.
The function tablesCollection is probably passed in fine into the view. However, you need to instantiate the object, e.g. new tablesCollection(null, {url: 'url'}) before logging it to the console, otherwise the extend wrapper function will show, which is what you see now.
Related
define(['jquery',
'underscore',
'backbone',
'app/js/components/models/Application'
], function($, _, Backbone , Application) {
var applicationView = Backbone.View.extend({
model : new Application(),
'initialize': function() {
console.log('initializing app view...')
this.render();
},
render: function() {
}
});
return applicationView;
});
But it is showing me error as Uncaught TypeError: Application is not a function.
Application.js
define(['jquery',
'underscore',
'backbone'
], function($, _, Backbone) {
var Application = Backbone.Model.extend({
defaults : {
version : 0.1
},
initialize : function(){
}
});
});
You application module doesn't return (export) anything, or to be technically correct, it returns (exports) undefined.
You should return your Application model constructor:
define(['jquery',
'underscore',
'backbone'
], function($, _, Backbone) {
var Application = Backbone.Model.extend({
defaults : {
version : 0.1
},
initialize : function(){
}
});
return Application; // <---------- add this
});
Also make sure 'app/js/components/models/Application' is the correct path and you don't have other errors in console.
Backbone version 1.1.2
Require version 2.0.2
//My main file
require.config({
paths: {
jquery: 'assets/js/libs/jquery/jquery-1.9.1.min',
underscore: 'assets/js/libs/underscore/underscore-min',
backbone: 'assets/js/libs/backbone/backbone-min',
bootstrap: 'assets/js/libs/bootstrap/bootstrap.min',
text : 'assets/js/libs/require/text',
mustache: 'assets/js/libs/mustache/mustache'
},
shim: {
'backbone': {
deps: ['jquery','underscore'],
exports: 'Backbone'
},
'bootstrap': {
deps: ['jquery']
}
}
});
require([
// Load our app module and pass it to our definition function
'assets/js/app',
], function(App){
App.initialize();
});
//My App file
define([
'jquery',
'underscore',
'backbone',
'assets/js/router'
], function($, _, Backbone, Router){
var initialize = function(){
Router.initialize();
}
return {
initialize: initialize
};
});
//My Router File
define([
'jquery',
'underscore',
'backbone',
'assets/js/views/trabajadores/list'
], function($, _, Backbone, TrabajadoresListView){
var AppRouter = Backbone.Router.extend({
routes:{
'':'mostrarTrabajadores',
'trabajadores': 'mostrarTrabajadores'
},
mostrarTrabajadores: function(){
var trabajadoresListView = new TrabajadoresListView();
trabajadoresListView.render();
}
});
var initialize = function(){
var app_router = new AppRouter;
Backbone.history.start();
};
return {
initialize: initialize
};
});
I'm a inspection the code and when the following code line executes "var app_router = new AppRouter; ", the console says: Uncaught TypeError: undefined is not a function.
The Router it's not working for me.why?
You can declare your route actions inside the initialize method. Just use the following:
var initialize = function(){
var app_router = new AppRouter;
app_router.on('route:index', function() {
console.log('index route');
});
return {
initialize: initialize
};
});
Just make sure you follow the format "route:Action" in the Router's 'on()' method.
Getting the following error when initializing a Backbone View:
this.collection.on is not a function
I have the following View:
define([
'jquery',
'underscore',
'backbone',
'events',
'utils',
'text!../../templates/vehicles-template.html'
],
function (
$,
_,
Backbone,
vent,
utils,
vehiclesTemplate) {
var VehiclesView = Backbone.View.extend({
template: vehiclesTemplate,
initialize: function () {
this.collection.on('reset', this.render, this); //error: this.collection.on is not a function
utils.log('Vehicles view initialized');
},
render: function() {
this.$el.empty().html(this.template({ vehicles: this.collection.toJSON() }));
return this;
}
});
return VehiclesView;
});
this is returning the view, but does not fails on collection or model when trying to bind to events.
What I am missing here?
As discussed in question comments, you need to pass the collection property to the view:
var view = new VehiclesView({collection:collection});
Something odd is going on with my Backbone project. I'm rebuilding it as AMD and I'm having to change some variable names to get it working again. I have a collection I'm passing into a view, but when I console.log the collection, I get both the object and null.
Here is my view:
define([
'jquery',
'underscore',
'backbone',
'models/tableModel',
'collections/tablesCollection',
'views/tablesView',
'views/tableView'
],
function($, _, Backbone, tableModel, tablesCollection, tableView) {
var tv = Backbone.View.extend({
tagName: 'div',
initialize: function() {
console.log(this.collection);
this.collection.on('reset', this.render, this);
this.template = this.options.template;
this.url = this.collection.url;
},
render: function() {
//tablesCollection.collection.each(this.addOne, this);
return this;
},
addOne: function(model) {
var t = new tableView({ model: model, template: this.template, url: this.url });
this.$el.append(t.render().el);
return this;
},
stripQueryString: function(url) {
return url.split('?')[0];
}
});
return tv;
});
You'll see the console.log several lines down in the project. Here is what I get in Firebug as a result:
Both cite the same line number. Here is what's in the object:
What is going on here? Why am I getting two results for the same thing? One of them is what I want and the other one isn't.
EDIT:
Here is where I instantiate the view:
define([
'jquery',
'underscore',
'backbone',
'models/tableModel',
'collections/TablesCollection',
'views/tablesView',
'views/tableView'
], function($, _, Backbone, TableModel, tablesCollection, tablesView, tableView) {
var t = new tablesCollection(null, { url: 'main-contact'} );
var tables = new tablesView({ collection: t, template: 'main-contact-template'});
$('#web-leads').html(tables.render().el);
});
Here is my collection:
define([
'jquery',
'underscore',
'backbone',
'models/tableModel'
],
function($, _, Backbone, tableModel) {
var tablesCollection = Backbone.Collection.extend({
url: this.url,
model: tableModel,
initialize: function(models, options) {
if (options && options.url) {
this.url = options.url;
}
this.fetch({
success: function(data, options) {
}
});
}
});
return tablesCollection;
});
Two other files:
// Filename: app.js
define([
'jquery',
'underscore',
'backbone',
'router' // Request router.js
], function($, _, Backbone, Router){
var initialize = function(){
// Pass in our Router module and call it's initialize function
Router.initialize();
};
return {
//initialize: initialize <--This is where the second init call was happening.
};
});
Main.js:
require.config({
paths: {
//jquery: 'libs/jquery/jquery-1.8.3.min',
underscore: 'libs/underscore/underscore-min',
backbone: 'libs/backbone/backbone-min'
}
});
if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
define( 'jquery', [], function () { return jQuery; } );
}
//the "main" function to bootstrap your code
require(['jquery', 'underscore', 'backbone', 'app'],
function () {
var App = require('app');
App.initialize();
// console.log($);
// console.log(_);
// console.log(Backbone);
});
You prior version of the code made more sense than this edited version, as in the prior version you were actually pushing to console.log the object that was giving trouble
// contents of 'that/view/that/gives/me/problems.js'
define([
'jquery',
'underscore',
'backbone',
'models/tableModel',
'collections/tablesCollection',
'views/tablesView',
'views/tableView'
],
function($, _, Backbone, tableModel, tablesCollection, tableView) {
console.log("factory", tablesCollection.collection); // <- you did not have this line. my addition
var tv = Backbone.View.extend({
tagName: 'div',
initialize: function() {
console.log("init", tablesCollection.collection); // <- your prior version. Point of your error
this.collection.on('reset', this.render, this);
this.template = this.options.template;
this.url = this.collection.url;
}
// ...
});
return tv;
});
Now the reason you have it show up twice is because the view you define above is initialized twice somewhere.
First time it's initialized it shows the value as you can see. The second time around the pointer tablesCollection is cleaned up by something and, hence, you have that error.
Now what cleans up tablesCollection and why I don't see anywhere in the code you present. It has likely something to do with re-requiring 'collections/tablesCollection' module somewhere in your code. As I can see from your 'collections/tablesCollection' module code, you REDEFINE the output on every factory call. What I would do is calc it once and serve cached:
// contents of 'collections/tablesCollection.js'
;(function(){
var mythings = {}
function initializer($, _, Backbone, tableModel){
return Backbone.Collection.extend({
url: 'url',
model: tableModel,
initialize: function(models, options) {
// ...
}
});
}
define([
'jquery',
'underscore',
'backbone',
'models/tableModel'
],
function($, _, Backbone, tableModel) {
if (!mythings.tablesCollection){
// this will be done on first run.
mythings.tablesCollection = initializer($, _, Backbone, tableModel)
}
// all others will just return same exact instance of collection class
return mythings.tablesCollection
})
})();
EDIT:
Asked the AMD spec group if there is a chance of 'factory' function rerunning on every require. Immediate answer was "Not likely" but long term answer is "Possible (if asked under different name)"
I added comment lines to the code snippet above indicating what files they are.
I also added a console.log line in the first snippet that should help you understand that the issue you have is NOT with AMD loader. You simply initialize the view twice somewhere.
When you run the code with comment lines like in the top snippet you will see factory log line shoing up only once and init line twice, like in your origianl error screenshot.
You need to trace where you use the view returned in that tv variable. You are initing it twice.
As to what happens to (what clears) reference to tablesCollection in the second run I don't know and don't see anywhere in the snippets you provided.
I've been trying to practice on backbone.js, I found one tutorial online which I was trying to follow (http://backbonetutorials.com/what-is-a-router/) but unfortunately i have problem reaching to my view through the router.
Below is my code
main.js
requirejs.config({
// create local alias for package
paths: {
l : 'my/vehicle',
underscore : 'vendors/underscore',
jqueryui : 'vendors/jquery-ui/js/jquery-ui-1.9.0.custom.min',
backbone : 'vendors/backbone',
bootstrap : 'vendors/bootstrap'
},
shim: {
backbone: {
deps: ["underscore", "jquery"],
exports: "Backbone"
},
underscore: {
exports: "_"
}
}
})
require(['../../config'], function(core){
require(["l/app"], function(App) {
'use strict';
App.initialize();
});
});
app.js
define(["jquery", "backbone", "l/router"], function($, Backbone, Router) {
var initialize = function(){
// Pass in our Router module and call it's initialize function
Router.initialize();
}
return {
initialize: initialize
};
});
router.js
define([
'jquery',
'underscore',
'backbone',
'l/views/BrowseVehicle'
], function($, _, Backbone, BrowseVehicleView){
var AppRouter = Backbone.Router.extend({
routes: {
// Define some URL routes
'/browse' : 'showVehicleBrowse',
// Default
'*actions' : 'defaultAction'
}
});
var initialize = function(){
var app_router = new AppRouter;
app_router.on('showVehicleBrowse', function(){
// Call render on the module we loaded in via the dependency array
console.log('am here');
var BrowseVehicleView = new BrowseVehicleView();
BrowseVehicleView.render();
});
app_router.on('defaultAction', function(actions){
// We have no matching route, lets just log what the URL was
console.log('No route:', actions);
});
Backbone.history.start();
};
return {
initialize: initialize
};
});
views/BrowseVehicle.js
define([
'jquery',
'underscore',
'backbone'
], function($, _, Backbone){
var BrowseVehicleView = Backbone.View.extend({
el: $('#vehicle-browse-form'),
render: function(){
// Using Underscore we can compile our template with data
console.log('I reached vehicle browse form');
}
});
// Our module now returns our view
return BrowseVehicleView;
});
There is no error on loading the code, console.log is not printing anything in the view nor in the router inside the routed function. I tried to access my urls using URL/#/browse but not getting the console.log statement.
Can anyone please advise?
In the routes {} definition remove the forward slash in front of browse.