Rahul Prabhakar
Rahul Prabhakar

Reputation: 51

AngularJS routing links don't work on reload

I've been doing a mini project using the TMDb API and AngularJS. My Angular routing part works, and i can load the movie details on click. The click on the homepage takes you to details view and the URL changes to movie/:id/:title and now if the user clicks on another movie present in the details view, the relevant data for the newly clicked movie replaces the previous data. Now if i try going back using the browser the data of the previous movie is not loading up, but the URL shows the previous movie's title.

Along with this error, there's an other bug. When i try reloading the browser it causes 404 Error. If i turn html5Mode(true)this occurs. If i disabled html5Mode the page doesn't show relevant information, but shows me an empty template in the view. I'm just a beginner in AngularJS. I don't know how to fix this. I have mentioned the domain where i've hosted the website. I guess, looking at it would be easier to understand my problem. Hope someone out here could help me.

PROJECT URL: http://movie-buffs.xyz/

This is my routing code.

.config(['$routeProvider','$locationProvider', function($routeProvider, $locationProvider){
            $routeProvider
            .when('/',{
                templateUrl:'templates/movies.html'
            })
            .when('/movies/:id/:title',{
                templateUrl:'templates/moviedetails.html'
            })
            .when('/search',{
                templateUrl:'templates/search.html'
            })
            .when('/tv',{
                templateUrl:'templates/tv.html'
            })
            .when('/tv/:id/:title',{
                templateUrl:'templates/tvdetails.html'
            })
            .when('/celebs',{
                templateUrl:'templates/celebs.html'
            })
            .when('/celebs/:id/:name',{
                templateUrl:'templates/celebsdetails.html'
            })
            .when('/contact',{
                templateUrl:'contact_us.html'
            })

            .otherwise({
                redirectTo:'/'
            });

    $locationProvider.html5Mode(true);
        }]);

Upvotes: 2

Views: 1240

Answers (3)

Curiousdev
Curiousdev

Reputation: 5778

Solution 1

angularjs provides html5Mode, which makes your app use pushstate-based URL instead of hashtags. However this requires server side support, since the generated urls need to be rendered properly as well.

Simply copy index.html to 404.html, and add this to your app:

angular.module('app', []).config(function($locationProvider) {
  $locationProvider.html5Mode(true);
});

Please find this link for more information

Solution 2

open index.html page and in head section add

<base href="/">

Your Angular code enable html5Mode

 angular.module('main', []).config(['$locationProvider', function($locationProvider) {  
      ...
      $locationProvider.html5Mode(true);
      ...
    });

After doing this, you need to create a .htaccess file on the root of your shared Apache server as your are using apache server add below code

Apache Server

RewriteEngine On  
  # If an existing asset or directory is requested go to it as it is
  RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
  RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
  RewriteRule ^ - [L]

  # If the requested resource doesn't exist, use index.html
  RewriteRule ^ /index.html

IIS Server

<rewrite>
  <rules>
    <rule name="AngularJS" stopProcessing="true">
      <match url=".*" />
      <conditions logicalGrouping="MatchAll">
        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
      </conditions>
      <action type="Rewrite" url="/" />
    </rule>
  </rules>
</rewrite>

That's it

Upvotes: 1

Jens Alenius
Jens Alenius

Reputation: 1931

This is how I do it. In my config.

.config(['$routeProvider', function ( $routeProvider) {
$locationProvider.html5Mode(false).hashPrefix('');
$routeProvider.otherwise({redirectTo: '/dashboard'});}]);

I divide the html with corresponding js in to folders ex:

/movie-details/movie-detail.html
/movie-details/movie-detail.js

My movie-details.js should look something like:

'use strict';
angular.module('myapp')
    .config(['$routeProvider', function ($routeProvider) {
        $routeProvider.when('/movies/:Id', {
            templateUrl: 'movie-details/movie-detail.html',
            controller: 'MovieDetails as vm'
        });
    }])
    .controller('MovieDetails', function ($scope, $routeParams) {
        var vm = this;
        vm.movieId= $routeParams.Id;

    });

In the html you wont need any Controller directive. Just:

{{vm.something}}

Upvotes: 0

Jens Alenius
Jens Alenius

Reputation: 1931

Nice page! Try out the html5 mode answer from Curiousdev. And I think you can make the routing simpler. You could change the routing from

('/movies/:id/:title')

to

('/movies/:id')

Here is an example on single movie on imdb:

http://www.imdb.com/title/tt1219827/?pf_rd_m=A2FGELUUNOQJNL&pf_rd_p=2896364242&pf_rd_r=0QKNGNCGK3XM4PBDN2A0&pf_rd_s=hero&pf_rd_t=15061&pf_rd_i=homepage&ref_=hm_hp_cap_pri_2

They don't provide the title in the url either

Further: If you want to break down the problems in angular routing , remove all extra jquery scripts an so on. Make sure it works before you add the cool gui stuff

Upvotes: 0

Related Questions