Backbone router.navigate how to pass dynamic ID - javascript

Using backbone marionette I need to navigate to the following route:
'page/:id': 'page'
This is what I have tried so far:
success: function (page) {
id = page.get('id')
router.navigate('page', {trigger: true});
}
But I have two problems with above.
1) Router is undefined in my view
2) I cannot find a reference to how I pass the ID
How do I resolve this or does marionette have any build in methods?

You can pass the id just putting it in the url:
success: function (page) {
id = page.get('id')
router.navigate('page/' + id, {trigger: true});
}
Reference
Regarding the router you need to create it:
var MyRouter = Backbone.Router.extend({
routes: {
'page/:id': 'page'
},
page: function(id) {
...
}
});
var router = new MyRouter();

Related

Easiest way to get Json / Collection through Meteor Iron Router

I'm creating a set of routes, for example
/ - should render home page template
/items - should items page template
/items/weeARXpqqTFQRg275 - should return item from MongoDB with given _id
This is example of what I'm trying to achieve
Router.route('items/:_id', function () {
var item = return myItems.find(:_id);
this.render(item);
});
[update - solved]
solved this by using Router.map on server side instead of Router.route
Router.map(function () {
this.route('post', {
path: 'items/:_id',
where: 'server',
action: function(){
var id = this.params._id;
var json = myItems.findOne({_id: id});
this.response.setHeader('Content-Type', 'application/json');
this.response.end(JSON.stringify(json, null, 2));
}
});
});
There are several problems with your code.
First, it seems you want to get the _id parameter from the url and don't know how. It's stored on this.params, so it's this.params._id.
Second, the first parameter you should send to find is a MongoDB query that in your case would be { _id: this.params._id }.
Third, that's not how you render something in Iron Router. The string parameter on the render method is the name of the template you want to render, not the item.
Assuming that myItems is a valid collection and your template is called showItem, your code should be something like:
Router.route('items/:_id', {
name: 'showItem',
data: function () {
return myItems.find({ _id: this.params._id });
}
});
Try something like this:
Router.map(function () {
this.route('items/:myItemId', {
data: function(){
return myItems.findOne({_id: this.params.myItemId});
}
});
});
good luck!

Backbone routes doesn't work with Laravel

I dont't know exactly where the error/s is/are.
I'm doing a Single Page App, this is the context:
I have a resource controller in Laravel that watch this route "domain.dev/v1/"
Laravel serves the first page/view "/public/views/layouts/application.blade.php"
Mustache views are stored under "public/views/" and they are loaded synchronously when they are called by the Backbone Router (I've modified the "app/config/view.php" file to serve the views from bakcbone)
In backbone, the Router controls every URI change, even pushstate and the respective Mustache views. Everything seems to work fine, but if you type the direct URI for a user o list or users...you only see JSON returned by the server, not the corresponding Backbone View, in other words, I dont know Which is not doing the correct work, the Laravel Router or the Backbone Router. Or is it a Laravel configuration?
This is my code so far:
// app/routes.php
Route::group(['prefix' => 'v1'],function (){
Route::resource('users','V1\UsersController');
Route::get('/', function()
{
return View::make('layouts.application')->nest('content', 'app');
});
});
// app/controllers/V1/UsersController.php
namespace V1;
//import classes that are not in this new namespace
use BaseController;
use User;
use View;
use Input;
use Request;
class UsersController extends \BaseController {
public function index()
{
return $users = User::all(['id','email','name']) ;
}
public function show($id)
{
$user = User::find($id,['id','email','name']);
if(is_null($user)){
return array(
'id' => 0,
'email' => 'fake email'
);
}
return $user;
}
// public/js/namespaces.js
(function(){
window.App = {
Models : {},
Collections : {},
Views : {},
Router : {}
};
window.Templator = function (mustacheView){
return $.ajax({
url: '/views/'+mustacheView,
async : false,
type: 'GET',
}).responseText;
};
window.Vent = _.extend({},Backbone.Events);
})();
// public/js/backbone/router.js
App.Router = Backbone.Router.extend({
routes : {
'' : 'home',
'users' : 'showAll',
'users/:id' : 'showUser',
'login' : 'showLoginForm'
},
home: function (){
Vent.trigger('home:index');
},
showAll : function (){
Vent.trigger('users:showAll');
},
showUser: function (id){
Vent.trigger('users:show',id);
},
showLoginForm : function (){
Vent.trigger('login:form');
}
});
// public/js/app.js
$(function() {
$(document).on("click", "a", function(e){
var href = $(this).attr("href");
if (href != '#') {
e.preventDefault();
Backbone.history.navigate(href,{trigger:true});
}
});
new App.Views.AllUsers;
new App.Views.Index;
new App.Views.Login;
new App.Router;
Backbone.history.start({
pushState: true,
silent: true,
root: '/v1'
});
});
So, if I type this URI "domain.dev/v1/users" on the nav bar, shows list of users in JSON and the view associated in backbone is not displayed.
Any suggestions?
Have a look at my answer I just gave in a similar question about Angular: Angular and Laravel
In the text, just mentally replace Angular with Backbone.
How to pass the route from Laravel to Backbone:
The base view, that is returned from Laravel for the '/' route needs to have something like this somewhere in its <head> before backbone.js is included:
<script>
var myRoute = "{{ $route }}";
</script>
This blade template creates a Javascript variable. Then, after you declared your routes in Backbone, add this:
Backbone.history.start(); // You should already have this line, so just add the next one
App.nav.navigate(myRoute);
This should do the trick.

Refresh page to see content

I've created a Rails app using Backbone, but I've run into a small but annoying problem. When a user goes to his profile and then back to the frontpage the frontpage is empty and I have to refresh it in order to show the content of the backbone view.
In my Movieseat.Routers.Movieseats I have:
routes:
'': 'index'
initialize: ->
#movieSeats = new Movieseat.Collections.Movieseats()
#movieSeats.fetch()
#searchResults = new Movieseat.Collections.Moviesearch()
index: ->
view = new Movieseat.Views.MovieseatsIndex(collection: #movieSeats)
$('#container').html(view.render().el)
Any idea on why users have to refresh to see the frontpage?
I don't know CoffeeScript but the fetch() method takes a success callback where you can ensure the collection has loaded. In your index you're creating a new view passing the #movieSeats collection but the collection may have not been loaded by that time. Try the following:
{
routes: {
'': 'index'
},
initialize: function() {
this.movieSeats = new Movieseat.Collections.Movieseats();
},
index: function() {
var self = this, view;
this.movieSeats.fetch({
success: function(collection) {
view = new Movieseat.Views.MovieseatsIndex({ collection: collection })
$('#container').html(view.render().el)
}
});
}
}
However, you might want to "bootstrap" your collection like is shown on the Backbone docs: http://documentcloud.github.io/backbone/#FAQ-bootstrap

Backbone Boilerplate - fetch method don't refresh collection

is my first question here, so I please about some patience and forgive my english:)
When I type link in browser address bar, all is OK. But when I do this inside browser by clicking element, collection is empty. But the main problem is there is always the same response from server, but fetch "dont load" any items, so view render empty collection.
I use Backbone Boilerplate,
Browser.Views.Catalog - it is Backbone.View
Browser.Catalog - it is of Backbone.Collection
My router:
var Router = Backbone.Router.extend({
routes: {
'' : 'browse'
},
refreshCatalog: function(folder){
app.layout.setViews({
"#catalog" : new Browser.Views.Catalog({
collection: app.catalog
})
}).render();
},
browse: function(folder){
app.catalog = new Browser.Catalog();
app.folders.fetch({
error: function() { console.log(arguments); },
success: this.refreshFolders(folder),
data: $.param({folder: folder}),
cache:false
});
//app.catalog = new Browser.Catalog();
app.catalog.fetch({
error: function() { console.log(arguments); },
success: this.refreshCatalog(folder),
data: $.param({folder: folder}),
cache:false
});
},
I belive you should set the catalog in the initialize function
app.catalog = new Browser.Catalog();
should go in here ( add this function)
initialize: function (options) {
app.catalog = new Browser.Catalog();
}
the initialize function is called when the page is loaded so when browsing to #catelog it will have been set http://backbonejs.org/#Router-constructor

backbone.js, handlebars error : this._input.match is not a function

I'm new to backbone.js and handlebars and I'm having a problem getting my template to render out the data.
Here is my collection and model data from tagfeed.js module:
// Create a new module.
var Tagfeed = app.module();
// Default model.
Tagfeed.Model = Backbone.Model.extend({
defaults : {
name : '',
image : ''
}
});
// Default collection.
Tagfeed.Collection = Backbone.Collection.extend({
model : Tagfeed.Model,
url : Api_get('api/call')
});
Tagfeed.TagView = Backbone.LayoutView.extend({
template: "tagfeed/feed",
initialize: function() {
this.model.bind("change", this.render, this);
},
render: function(template, context) {
return Handlebars.compile(template)(context);
}
});
Then in my router I have:
define([
// Application.
"app",
// Attach some modules
"modules/tagfeed"
],
function(app, Tagfeed) {
// Defining the application router, you can attach sub routers here.
var Router = Backbone.Router.extend({
routes: {
"index.html": "index"
},
index: function() {
var collection = new Tagfeed.Collection();
app.useLayout('main', {
views: {
".feed": new Tagfeed.TagView({
collection: collection,
model: Tagfeed.Model,
render: function(template, context) {
return Handlebars.compile(template)(context);
}
})
}
});
}
});
return Router;
});
THis successfully makes a call to the api, makes a call to get my main template, and makes the call to get the feed template HTML. If I don't include that render(template, context) function, then it renders on the page as the straight up HTML that I have in the feed template with the {{ name }} still included. however when its included, I get the error
TypeError: this._input.match is not a function
[Break On This Error]
match = this._input.match(this.rules[rules[i]]);
and if I examine the variables that get passed into the appLayout views render function for feed, I see that the template var is a function, and the context var is undefined, then it throws that error.
Any ideas what I'm doing wrong? I know I have at least one problem here, probably more.
Since you're using requirejs, you can use the text module to externalise your templates or better still pre-compile them and include them in your view. Check out http://berzniz.com/post/24743062344/handling-handlebars-js-like-a-pro
E.g. using pre-compiled templates
// router.js
define(['views/tag_feed', 'templates/feed'], function(TagFeedView) {
var AppRouter = Backbone.Router.extend({
// ...
});
})
// tag_feed.js
define(['collections/tag_feed'], function() {
return Backbone.View.extend({
// ...
render: function() {
this.$el.html(
Handlebars.templates.feed({
name: '...'
})
);
}
});
})
For reference I've created simple boilerplate for a backbone/require/handlebars setup https://github.com/nec286/backbone-requirejs-handlebars

Categories

Resources