canjs - Routing Conventions in Can.js -
so i’m looking make routes within super cool can.js application. aiming this…
#!claims claimscontroller - lists claims #!claims/:id claimcontroller - views single claim #!claims/new claimcontroller - creates new claim #!claims/:id/pdf - nothing, claimcontroller handle #!admin admincontroller - loads administrative panel menu #!admin/users - nothing, admincontroller handle #!admin/settings - nothing, admincontroller handle so how might this?
“claims route”: function() { load('claimscontroller'); }, “claims/:id route”: function() { load('claimcontroller'); }, “admin”: function() { load(‘admincontroller’); }, cool beans, we’re off. if sends link like...
http://myapp#!claims/1/pdf nothing happens! ok, let’s add route.
“claims/:id/pdf route”: function() { load('claimcontroller'); }, great. link works. here, router’s job load controller. controller recognize pdf action wanted, , show correct view.
so pretend i’ve loaded claim claims/:id , edit 1 or 2 things. click print preview button view pdf , change route claims/:id/pdf.
what should happen… claim controller watching route , shows pdf view.
what happens… router sees change, matches claims/:id/pdf route added, , reloads claim controller, displaying fresh version of claim pulled server/cache, losing changes.
to try , define problem, need router identify when route changes, controller route belongs to, , if controller loaded, ignore it. hard!
claims // claims/:id // different controllers! claims/:id // claims/:id/pdf // same controller! we bind on "controller" change. defining routes can.route(':controller') , binding on :controller.
{can.route} controller // or can.route.bind('controller', function() {...}) but clicking on claim (changing claimscontroller claimcontroller) won't trigger, first token claim same in both cases.
is there convention can lean on? should specifying every single route in app , checking if controller loaded? preferred route urls not working?
the following how setup routing in complex canjs applications. can see example of here.
first, not use can.control routes. it's anti-pattern , removed in 3.0 ideas in this issue.
instead setup routing app module imports , sets modules convention similar this used here.
i explain how setup routing app module in moment. first, it's important understand how can.route different how used thinking of routing. difference makes difficult understand @ first, once it; you'll see how powerful , perfect client-side routing.
instead of thinking of urls, think of can.route's data. in can.route.attr(). example, urls seem have data like:
- page - primary area dealing with
- subpage - optional secondary area within page
- id - id of type
for example, admin/users might want can.route.attr() return:
{page: "admin", subpage: "users"} and, claims/5 might translate into:
{page: "claims", id: "5"} when start building application, use urls #!page=admin&subpage=users , ignore pretty routing until later. build application around state first , foremost.
once have mental picture of can.route.attr() data encapsulates application's state, build routing app module listens changes in can.route , sets right controls or components. yours might like:
can.route.bind("change", throttle(function(){ if( can.route.attr("page") == "admin" ) { load("admincontroller") } else if(can.route.attr("page") === "claims" && can.route.attr("id") { load("claimcontroller") } else if ( ... ) { ... } else { // convention, load controller whatever page load(can.capitalize(can.route.attr("page")+"controller") } }) ); finally, after setting of up, make pretty routes map expected can.route.attr() values:
can.route(":page"); // #!claims, #!admin can.route("claims/new", {page: "claims", subpage: "new"}); can.route("claims/:id", {page: "claims"}); can.route("admin/:subpage",{page: "admin"}); by doing way, keep routes independent of rest of application. listens changes in can.route's attributes. routing rules maintained in 1 place.
Comments
Post a Comment