I was following the backbonerails.com screencast episode 6. But I can't get the routing to work as it was explained.
Here is my code that is similar to what the screencast suggest:
#Report.module "UsersApp", (UsersApp, App, Backbone, Marionette, $, _) ->
class UsersApp.Router extends Marionette.AppRouter
initialize: ->
console.log "Happy days"
appRoutes:
"users" : "listUsers"
API =
listUsers: ->
console.log "hallo"
App.addInitializer ->
console.log "cheers"
new UsersApp.Router
controller: API
As you can see I have tried to add console.log in a few places to make sure the addInitializer is working and that the Router is started... but still the routing to #users does not do the corresponding console.log
I have this where I define the app:
App.on "initialize:after", ->
if Backbone.history
Backbone.history.start()
So that should run after router has started, if I understand it all.
Turns out that it was the Backbone history was not running. I found that out by running:
Backbone.History.started
in my console. For some reason
App.on "initialize:after", ->
if Backbone.history
Backbone.history.start()
did not start the history.
EDIT: turns about in v2 and above of Marionette you should use:
App.on "start", ->
Related
So my route filter is working as expected and I was writing some tests around it. I have several passing tests but for some reason I can't get this one test to pass. My route filter looks like this:
stripUs: ->
resolve: ->
resolution: ($location) ->
urlParts = $location.$$path.split("/")
if urlParts.indexOf('us') is 1
$location.path(urlParts.slice(2,urlParts.length).join("/"))
The idea is to redirect /us/foo/bar urls to /foo/bar.
the tests I currently have passing for this filter are:
ddescribe 'stripUs', ->
location = rootScope = null
beforeEach inject ($location, $rootScope, initialDataService, ignoreHttpBackend) ->
ignoreHttpBackend()
location = $location
rootScope = $rootScope
it 'removes /us from /us/programming', ->
location.path("/us/programming")
rootScope.$digest()
expect(location.path()).toEqual('/programming')
it 'removes /us from /us/programming/**', ->
location.path("/us/programming/sports")
rootScope.$digest()
expect(location.path()).toEqual('/programming/sports')
it 'preserves route params', ->
location.path("/us/programming/sports?affiliate=foo&&process=foobarred")
rootScope.$digest()
expect(location.path()).toEqual('/programming/sports?affiliate=foo&&process=foobarred')
The test I can't get to pass is:
it 'preserves route params', ->
location.path("/us/programming?affiliate=foo")
rootScope.$digest()
expect(location.path()).toEqual('/programming?affiliate=foo')
the error message is:
Expected '/us/programming?affiliate=foo' to equal '/programming?affiliate=foo'
which would lead me to believe the code isn't working but it is if I actually try to visit the page. Additionally when I try to put a console log at the very top of the route filter, the log is never hit. I am new to testing in Jasmine and could use any help possible. Thanks in advance.
I solved this issue by changing the expectation. I think I have a better test as a result but I never figured out why I couldn't get the test to run. here is what I changed the test to.
it 'preserves route params', ->
location.path("/us/programming/sports?affiliate=bestbuy&process=foobarred")
rootScope.$digest()
expect(location.path()).toContain('?affiliate=bestbuy&process=foobarred')
it 'preserves route params', ->
location.path("/us/programming?affiliate=bestbuy")
rootScope.$digest()
expect(location.path()).toContain('?affiliate=bestbuy')
I have the following:
#App.module "LocationGridApp", (LocationGridApp, App, Backbone, Marionette, $, _) ->
API =
showLocationGrid: ()->
LocationGridApp.Show.Controller.showLocationGrid(2)
class LocationGridApp.Router extends Marionette.AppRouter
appRoutes:
"" : "showLocationGrid"
controller: API
App.on 'before:start', ->
new LocationGridApp.Router
When I access <url> I get the showLocationGrid to fire off as expected. When I visit <url>/companies, showLocationGrid is still firing. I was expecting <url>/companies to be handled by my server. Is the empty route doing something I'm not expecting?
main_app.js.coffee
#App = do(Backbone, Marionette) ->
Arc = new Marionette.Application
Arc.addRegions
container: "#container"
Arc.on "start", ->
if Backbone.history
Backbone.history.start(pushState: false)
Arc
It's up to your server to serve different files depending on the route: if you get the same result for <url> and <url>/companies, it is that your server answered with the same static files. Nothing in your client-side code can take over your server-side routing. You should probably inspect your server routing settings.
I try to study and use Backbone/Marionette in my project. Now I stuck with Router navigation which work not as I though it should.
class MyApp.Router extends Marionette.AppRouter
appRoutes :
'info/:place/(:what)' : 'places_page'
MyApp.Controller = ->
places_page: (place,what)->
console.log 'Triggered places_page'
MyApp.addInitializer( ->
controller = new MyApp.Controller()
new MyApp.Router
controller: controller
Backbone.history.start( pushState: false )
)
MyApp.vent.on('do:search', ->
console.log 'triggered do:search'
place = 'Moscow'
what = 'Пицца'
info_model.set place: place, item:what
new_url = 'info/'+where+'/'+what
if new_url != decodeURIComponent(Backbone.history.fragment)
Backbone.history.navigate(new_url, {trigger: false})
On initial load of site.com/#info/Budapest/Vine page or reload it, I get Triggered places_page message as I expect.
But when I fire do:search event which update url to site.com/#info/Moscow/Пицца, I get Triggered places_page again! So it reload all my views from scratch instead of just change url and re-render one model.
What I can do wrong here?
Update 2:
Found strange thing. If I use latin letters in new url, everything work like it should.
But if I use cyrillic in new url path, it will trigger route function.
Backbone: 1.0, Marionette:v1.0.3, jquery: 1.9.1
Mystery solved!
That happens because of non-latin symbols in url.
Correct code:
new_url = 'info/'+encodeURIComponent(where)+'/'+encodeURIComponent(what)
if new_url != Backbone.history.fragment
Backbone.history.navigate(new_url, {trigger: false})
Because Backboune.navigate don't execute navigate if url didn't change and trigger is false by default, I can write it simple like that:
new_url = 'info/'+encodeURIComponent(where)+'/'+encodeURIComponent(what)
Backbone.history.navigate(new_url)
Backbone.history takes an object when starting. Try this syntax in CoffeeScript:
Backbone.history.start
pushState: false
In addition, pushState is false by default, so you can just have Backbone.history.start()
Does this solve your issue?
Proper URL encoding is required. I couldn't find this in the docs of Backbone related to the router functionality.
I had the same issue, alas with spaces in the query part, i.e.:
#app/terms?filter=java ee
Together with the encodeURIComponent solution as described in your answer, I also found the following lines of comments in backbone.js (1.0.0), pertaining to the navigate function:
// Save a fragment into the hash history, or replace the URL state if the
// 'replace' option is passed. You are responsible for properly URL-encoding
// the fragment in advance.
+im playing arround with backbone and coffeescript, trying to get the router up and running. executing the following code, the init function works, but when browsing localhost/#world/3 nothing happens, although it should log something....
App =
start: ->
new App.TestRouter
Backbone.history.start
App.TestRouter = Backbone.Router.extend
routes:
"world/:id": "testView"
initialize: ->
new App.TestView
console.log "Router init"
testView: (id) ->
console.log "testing! #{id}"
any advice here? am i blind?
Backbone.history.start() is a function, so you need the () to execute it. Otherwise, you're just getting a reference to the function itself.
App =
start: ->
new App.TestRouter
Backbone.history.start()
See this live jsFiddle:
http://jsfiddle.net/edwardmsmith/6pNLv/8/
This is driving me crazy right now. I cannot get a simple router to work...
jQuery ->
class MyRouter extends Backbone.Router
routes:
"" :"index"
"/list" :"showList"
"/item/:id" :"showItem"
index: =>
alert "index"
showList: =>
alert "get the lists"
showItem: (id)=>
alert "the item #{id}"
#app = window ? {}
#app = window.app ? {}
#app.myRouter = MyRouter
Backbone.history.start()
I always get this error:
index.js:50Uncaught TypeError: Cannot call method 'start' of undefined
and I saw this: Cannot call 'start' of undefined when starting backbone.js history.
but it did not help =(...
I am sure this is an easy one but I am some sort of stuck here ...
please help...
You didn't create an instance of a Backbone.Router, so Backbone.history.start() will fail.
#app.myRouter = new MyRouter()
The link you posted tells you exactly what the problem is:
TypeError: Cannot call method 'start' of undefined**
Hmm, for some reason Backbone.history is undefined, and so there is no start method on it. It turns out that Backbone.js creates an
instance of Backbone.History (upper case ‘H’) called Backbone.history
(lower case ‘h’) once a controller has been created that has at
least one route specified on it. This makes sense, as history
management is only required if there are routes to respond to.