0

I'm developing my first backbone project and I have requirement that I'm not sure how to meet. I'm sure the solution has something to do with properly routing my app, but I'm not sure...

App.Router = Backbone.Router.extend({
        initialize: function(options) {
            this.el = options.el;
        },
        routes: {
            '': 'search',
            'search': 'search'
        },
search: function() {
            var search = new App.SearchView();
            search.render();
        }
}
    });

I have three views:

// Defines the View for the Search Form
App.SearchView = Backbone.View.extend({

    initialize: function() {
        _.bindAll(this, 'render');
        this.render();
    },

    template: _.template($('#search-form').html()),
    el: $('#search-app'),
    events: {
        'click .n-button' : 'showResults'
    },

    showResults: function() {
        this.input = $('#search');
        var search = new App.ResultsSearchView();
        var grid = new App.GridView({ query: this.input.val() });
        search.render();
        grid.render();
    },

    render: function() {
        $(this.el).html(this.template());
        return this;
    },
    name: function() { return this.model.name(); }

}); // App.SearchView

//Defines the View for the Search Form when showing results
App.ResultsSearchView = Backbone.View.extend({

    initialize: function() {
        _.bindAll(this, 'render');
        this.render();
    },  
    template: _.template($('#results-search-form').html()),
    el: $('#search-input'), 
    render: function() {
        $(this.el).html(this.template());
        return this;
    },
    events: {
        'click .n-button' : 'showResults'
    },
    showResults: function() {
        this.input = $('#search');
        var grid = new App.GridView({ query: this.input.val() });
        grid.render();
    },
    name: function() { return this.model.name(); }

}); // App.ResultsSearchView


// Defines the View for the Query Results
App.GridView = Backbone.View.extend({
    initialize: function(options) {
        var resultsData = new App.Results();
        resultsData.on("reset", function(collection) {

        });

        resultsData.fetch({
            data: JSON.stringify({"query":this.options.query, "scope": null}),
            type: 'POST',
            contentType: 'application/json',
            success: function(collection, response) {
                $('#grid').kendoGrid({
                    dataSource: {
                        data: response.results,
                        pageSize: 5
                    },
                    columns: response.columns,
                    pageable: true,
                    resizable: true,
                    sortable: {
                        mode: "single",
                        allowUnsort: false
                    },
                    dataBinding: function(e) {

                    },
                    dataBound: function(){

                    }
                });

            },
            error: function(collection, response) {
                console.log("Error: " + response.responseText);
            }


        });
        _.bindAll(this, 'render');
        this.render();
    },
    el: $('#search-app'),
    template: _.template($('#results-grid').html()),
    render: function() {
        $(this.el).html(this.template());
        return this;
    }
}); // App.GridView

The issue I am having is that we want our users to be able to use the back button to navigate back to the initial search and also from there, be able to move forward again to their search results. I just have no idea how to do this. Any assistance would be a huge help.

Thanks!

Charles
  • 309
  • 1
  • 16

1 Answers1

1

Backbone handles the browser history -- all you have to do is call Backbone.history.start() on startup. Well, that and make sure to call Router.navigate whenever you want to save the current navigation state.

In your example, the appropriate time would be when the user clicks "search". In the searchView.showResults method, instead of creating and rendering the results view, call:

myRouter.navigate("results/" + this.input.val(), { trigger: true });

This causes the router to go to the results/query route, which you have to add:

'results/:query': 'results'

Finally, create the results method within your router, and put the view-creating logic there:

results: function(query) {
    var search = new App.ResultsSearchView();
    var grid = new App.GridView({ query: query });
    search.render();
    grid.render();
}

  • Here's a working demo -- it's a bit hard to see on JSFiddle because the page is within an iFrame, but you can confirm it's working by hitting Alt+Left, Alt+Right to call the browser's back and forward respectively.

  • And for contrast, here's a similar demo, except it uses a single route. It calls router.navigate without trigger: true. You can see that, using this single-route method, you're able to navigate back; however, you can't go forward again to the results view, because Backbone has no way to re-trace the steps to get there.

App

var HomeView = Backbone.View.extend({
    initialize: function() {
        this.render();
    },
    el: "#container",
    events: {
        "submit #search": "search"
    },
    template: _.template($("#search-template").html()),
    render: function() {
        var html = this.template();
        this.$el.html(html);
    },
    search: function(e) {
        e.preventDefault();
        router.navigate("results/" + $(e.target).find("[type=text]").val(), { trigger: true });
    }
});

var ResultsView = Backbone.View.extend({
    initialize: function() {
        this.render();
    },
    el: "#container",
    render: function() {
        var html = "Results test: " + this.model.get("query");
        this.$el.html(html);
    }
});

var Router = Backbone.Router.extend({
    routes: {
        "" : "search",
        "results/:query": "results"
    },

    search: function() {
        console.log("search");
        var v = new HomeView();
    },
    results: function(query) {
        console.log("results");
        var v = new ResultsView({ model: new Backbone.Model({ query: query }) });
    }       
});
var router = new Router();
Backbone.history.start();

HTML

<script type='text/template' id='search-template'>
    <form id="search">
    <input type='text' placeholder='Enter search term' />
    <input type='submit' value='Search' />
    </form>
</script>

<div id="container"></div>​
McGarnagle
  • 101,349
  • 31
  • 229
  • 260