Search code examples
javascriptphpcodeigniterknockout.jssammy.js

Knockout.js and Sammy.js with multpage cms app


I am working on programming a CMS using Knockout.js and Sammy.js. The original CMS was built using PHP with CodeIgniter.

My CMS for example has a Users section and a Courses section.

Originally, each section had its own pages for adding/editing/deleting data. What I want to do is basically create single page applications for each section. So the Users section would be a single page app to allow you to list/add/edit/delete users.

My problem is, when I want to click a link to go to the Courses section, Sammy tries to run on that page which isn't setup yet. Some pages might not require Sammy so I am trying to figure out now how to disable it, at the same time, I want to use the same combined javascript file on every page in the CMS.

In my application if have a UserViewModel using Knockout JS with the Sammy function

UserViewModel() {
    // Data
    var self = this;

    self.newUser = ko.observable();
    self.userData = ko.observable();
    self.userList = ko.observableArray([]);
    self.successMessage = ko.observable();
    self.errorMessage = ko.observable();

    // Behaviors
    self.goToList = function() { location.hash = '#/'; };
    self.goToAdd = function() { location.hash = 'add/'; };
    self.goToEdit = function(user) { location.hash = 'edit/' + user.id; };
    self.goToDelete = function(user) { location.hash = 'delete/' + user.id; };

    self.addUser = function() {
        $.ajax("user/add", {
            type: "post",
            data: {
                user: self.newUser,
            },
            contentType: "application/json",
            success: function(result) {
                if (result.success) {
                    self.goToList();
                    self.successMessage(result.success);
                } else {
                    self.errorMessage(result.error);
                }
            }
        });
    };

    // Client-side routes
    Sammy(function() {          
        this.get('', function() {
            // What can I do here to ignore certain paths and just have them work like a normal link?
        });
        this.get('/admin/user#/', function() {
            self.userData(null);
            self.newUser(null);

            $.getJSON("user/getList", function(data) {
                var users = $.map(data, function(users) {
                    return new User(users);
                });
                self.userList(users);
            });
        });

        this.get('/admin/user#add/', function() {
            self.userList.removeAll();
            self.newUser(new User(''));
        });

        this.get('/admin/user#edit/:id', function() {
            self.userList.removeAll();
            self.newUser(null);
            $.getJSON("/admin/user/getEdit/" + this.params.id, function(allData) {
                var mappedSession = $.map(allData, function(item) {
                    return new Session(item);
                });
                self.sessionData(mappedSession[0]);
            });
        });

        this.get('/admin/user#delete/:id', function() {
            self.sessionList.removeAll();
            // TODO: Setup delete function
        });

        this.get('/admin/user', function() { this.app.runRoute('get', '/admin/user#/'); });
    }).run();
}
ko.applyBindings(new UserViewModel(), document.getElementById('user'));

Solution

  • If I got you right, you can just assign your Sammy initialization to some view model's variable, like this:

    self.sammy = Sammy(function()...); // NOTE: don't run it yet!
    

    Then on bindings application:

    var vm = new UserViewModel();
    ko.applyBindings(vm, document.getElementById('user'));
    vm.sammy.run();