Search code examples
javascriptphpbackbone.jslaravel

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:

  1. I have a resource controller in Laravel that watch this route "domain.dev/v1/"
  2. Laravel serves the first page/view "/public/views/layouts/application.blade.php"
  3. 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)
  4. 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?


Solution

  • 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.