Question

So I'm following this tutorial:

http://www.tinywall.info/2012/02/change-browser-url-without-page-reload-refresh-with-ajax-request-using-javascript-html5-history-api-php-jquery-like-facebook-github-navigation-menu.html

My goal is to load the actual content of my views and change the browsers URL without reloading the page. However, because I'm using CodeIgniter as a framework of my application, I can't get it to work properly. I have a controller where I'm loading all of my Dashboard's views, ones I want display inside my div called content_container.

The problem is that every time I click another anchor tag to get different view to load through ajax request, it adds another "dashboard" -in my url and of course it doesn't display the view after that. So after couple clicks, the URL would look something like this: "dashboard/dashboard/dashboard/profile". I've tried to split the URL with Javascript, but that didn't help me.

One solution would be to create single controller for each view, but I consider it as a bad practice and the code is a lot more cleaner with just one controller to handle all the views.

Here's the controller:

<?php

class Dashboard extends CI_Controller {

    public function __construct()
    {

        parent::__construct();
        $this->output->nocache();
        $this->load->model('subject_model');
        $this->load->model('user_model');
    }


    public function index()
    {

        $this->load->view('header');
        $this->load->view('dashboard');
        $this->load->view('footer');
    }

    public function users() 
    {

        $data['users'] = $this->user_model->getUsers();
        $this->load->view('staff_users', $data);
    }
    public function lomake()
    {

        $this->load->view('lomake');
    }

    public function profile()
    {

        $data['userinfo'] = $this->user_model->getUserInformationById($this->session->userdata('user_id'));
        $this->load->view('myprofile', $data);
    }

    public function subjects()
    {

        $this->load->view('subjects');
    }   
}
?>

And here's my dashboard view (part of it):

<aside id="left_control_panel">

    <ul id="left_control_links">
        <li>
        <a href="home" id="ajax" class="active">Home</a>
        </li>
        <li>
        <a href="dashboard/subjects" rel="tab">Subjects</a>
        <span class="list_total_count"><?=$total_subjects?></span>
        </li>

        <li>
        <a href="dashboard/lomake" id="ajax">Query</a>
        </li>

    <?php if($this->session->userdata('user_type') == 'admin'):?>

        <span class="left_control_heading">User management</span>
        <li>
        <a href="dashboard/users" rel="tab">Users</a>
        <span class="list_total_count"><?=$total_users?></span>
        </li>

        <li>
        <a class="add_user" href="add_user">Add User</a>
        </li>
    <?php endif;?>

        <span class="left_control_heading">Account management</span>
        <li>
        <a href="dashboard/profile" rel="tab">My Profile</a>
        </li>

        <li>
        <a href="<?=base_url()?>users/logout">Sign Out</a>
        </li>
    </ul>
</aside> <!-- end of left_control_panel -->

<div id="wrapper_loggedin">
        <div class="content_container">
        <! -- I will display all the data from different views in here -->
        </div>
</div> <!-- end of wrapper_loggedin -->

And finally the JS part which can also be found in the tutorial:

$(function(){
    $("a[rel='tab']").click(function(e){
        //e.preventDefault(); 
        pageurl = $(this).attr('href');

        $.ajax({url:pageurl+'?rel=tab',success: function(data){
            $('.content_container').html(data);
        }});

        //to change the browser URL to 'pageurl'
        if(pageurl!=window.location){
            window.history.pushState({path:pageurl},'',pageurl);    
        }
        return false;  
    });
});

/* the below code is to override back button to get the ajax content without reload*/
$(window).bind('popstate', function() {
    $.ajax({url:location.pathname+'?rel=tab',success: function(data){
        $('.content_container').html(data);
    }});
});

Application/config/routes.php

$route['dashboard'] = 'dashboard/index';

$route['dashboard/(:any)'] = 'dashboard/$1';
Was it helpful?

Solution

well, with my specific situation I had thousands of products organized in categories and sub categories. Well..thats a ton of urls and controllers to write. so what i did was make a category template, a sub category template and a product page template. then made routes like below in my application/config/routes.php file:

$route['products'] = 'products/index';

//so i know now they are on a category page and $1 is the name of the category.
//i can go query my db and get all subcategorys and the products under each now.
$route['products/(:any)'] = 'products/category/$1'; 

//the 1 and 2 here are category and subcategory from the url. so i know from this to
//use these in my query to grab all products in this category and subcategory.
$route['products/(:any)/(:any)'] = 'products/subcategory/$1/$2'; 

//i know this is gonna be a product page. and i know the category, the sub category and the product name. in this case all i really need is the product name since there is only one product with that name.
$route['products/(:any)/(:any)/(:any)'] = 'products/details/$1/$2/$3';

in your situation you can do the same. use your urls, your taking the time to build them so use them. in javascript you can send them back to your controllers via 'window.location.pathname'; all you have to do is split it up and you can use the same mentality to load a page and know exactly where you are at.

Also, in your ajax url property make sure your url is either an absolute url, or it references the root first. I think i know what your issue is. you are using a url like "users/dashboard" in your url property when it should be "/users/dashboard" you need to always go to the root and get the controller, otherwise it uses the url and will always take on the "users/dashboard" to the current url you are on. So if you are on "users/dashboard" and go load it again, your actually telling it to load "/users/dashboard/users/dashboard" and this becomes an infinite loop. Just put a backslash in front of your url and it will always reference the root.

OTHER TIPS

I just did this very same thing. The way I did it was first make a dynamic route to always point to the same controller. $route['products/(:any)/(:any)/(:any)'] = 'products/details/$1/$2/$3'; etc. then anytime your page is loaded via a url (if someone puts in a specific url) you will still get content (bookmarks still work, you can send specific urls to people etc). Then what I did was every link that changed content also applied a data attribute to build the url out, i would also use those to pass back to the same controller. That controller also checks if the request is coming from an ajax request or not...if it is, you just load the page content...if it isnt then load the full template. its really not that hard and you actually almost have what i have. I think you are over thinking it. But the first thing i would do is make sure going to every page with the url works first. then try to get the ajax part working. The key is to detect if the request is coming from ajax or not within your controller. Then you can differentiate the two.

Also, I would strongly recommend you reading the user guide. The routes are usually one of the first thing you should cover when you start building projects with Codeigniter.

http://ellislab.com/codeigniter/user-guide/general/routing.html

Answering your question on the core controller. The answer is yes, you create a controller inside your core folder. It has to have a specific name. In your application/config/config.php file you should have:

$config['subclass_prefix'] = 'MY_';

This defines your prefix to any extended core controllers, models or system classes. Most Codeigniter system classes can be extended and you can overwrite properties (variables) and methods (functions). In your case you would drop a file called MY_Controller.php in your application/core folder. In this controller you would approach it like any other controller you write with the idea to not have to keep rewriting the same code over and over again, or to change the way the default Controller operates. You should read up on how a php class is suppose to work and the purpose of using them. Codeigniter doesn't really use them the way that you are suppose to use a class, but they approached it with the MVC approach. Usually, a class is referenced to as an object. Think of a class as a Bear. A bear has weight, age, length, color, height. All of these are called "properties". A bear can also eat, drink, and hunt. Each of these are called "methods". A more detailed version of a bear would be a polar bear, grisly bear or panda bear. These could be children of the bear object (they would extend the Bear object). Any child object inherits its parents properties and methods. But their values and actions could differ. The polar bear is a different color, size, height than the panda bear but it still eats, drinks, and hunts. Some properties and methods might not change, so there is no reason to rewrite those in the child classes. So in your case, the core controller can handle things that every page does. It can verify sessions, track a users activity, define global error messages etc. Ive even gone so far as to create a method in my core controller that loads my template pieces together (header, footer, sidebar, content) so i didn't have to keep stacking $this->load->view() when i was loading pieces of my template. All I had to do was pass the content and data that needed to be passed and it loaded my template everywhere. You also need to understand how the __construct works. You can think of the __construct as a function that always runs first before your page loads. so by defining a construct in your core controller you can then fill in data automatically. Browse these links as they go into a deeper explanation on how to use these features and shows examples.

http://ellislab.com/codeigniter/user-guide/general/core_classes.html

http://www.php.net/manual/en/language.oop5.php

Please give me a up vote if this guided you in the right direction :) Im trying to build up my points and profile and eventually link my account up to my website so it proves my plethora of php & codeigniter knowledge to any future employees.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top