Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Refresh(F5) ngview with angularJS

I've got an issue with my Angular application. The application is running well the first time, it is possible to navigate inside, but it fails when I try to refresh the page with F5. When F5 key is pressed, the partial is called to the server, and the server obviously responds with the partial view, but not the whole application.

Node routing:

app.get('/', node_routes.welcome);
...
app.get('/profile', pass.ensureAuthenticated, profile_routes.profile);
app.get('/profile/:name', pass.ensureAuthenticated, profile_routes.partials);
app.post('/profile/update', pass.ensureAuthenticated, profile_routes.update);
...

Controller:

exports.profile = function(req, res) {
    var user = req.user;
    Profile.findOne({ username: user.username }, function(err, profile) {
        if (err) { 
            res.redirect('/'); 
        }       
        res.render("profile");
    });  
};  

exports.partials = function(req, res) {
    var name = req.params.name;
    var user = req.user;
    Profile.findOne({ username: user.username }, function(err, profile) {
        if (err) { 
            res.redirect('/'); 
        }       
        res.render(path.join(__dirname + '/../views/profile/' + name));
    });
};

exports.update = function(req, res){
    var profile = req.body;
    delete profile._id;
    Profile.update({'username':profile.username},profile,{safe:true}, function(err, result){
        if(err) {
            console.log('Error updating profile. ' + err);
            res.redirect('/profile');
        }
        else{
            console.log('' + result + ' profile updated for user: ' + profile.username);
            res.redirect('/profile');
        }           
    });
};

Angular application

myApp.config(['$routeProvider','$locationProvider', function($routeProvider,$locationProvider){
    $routeProvider
       .when('/profile/update', {
           controller: 'myJobOfferListCtrl',
           templateUrl: '/profile/update',
           reloadOnSearch: false
       })
       .when('/profile', {
           controller: 'myJobOfferListCtrl',
           templateUrl: '/profile/dashboard'
       })
       .when('/profile/dashboard', {
           controller: 'myJobOfferListCtrl',
           templateUrl: '/profile/dashboard',
           reloadOnSearch: false
       })
       .when('/profile/offers', {
           controller: 'myJobOfferListCtrl',
           templateUrl: '/profile/offers',
           reloadOnSearch: false
       })      
       .otherwise({redirectTo: '/profile'});
    $locationProvider.html5Mode(true);
}]);

My profile page

extends layout

block content   
   div.container-fluid(ng-app="appProfile", ng-controller="myJobOfferListCtrl", ng-init="initProfile()")
      div.row-fluid
         div.span3(ng-controller="navBarCtrl")
           div.well.sidebar-nav
             ul.nav.nav-list
               li.well.nav-header.
                  My Profile ({{data.profile.username}})
               li(ng-class="{ active: isActive('dashboard')}") 
                  a(href="/profile/dashboard") Dashboard   
               li(ng-class="{ active: isActive('update')}") 
                  a(href="/profile/update") Update profile
               li.divider
               li.well.nav-header My Jobs
               li(ng-class="{ active: isActive('offers')}") 
                  a(href="/profile/offers") Offers
               li(ng-class="{ active: isActive('application')}") 
                  a(href="/profile/application") Applications
         div.span9(ng-view, ng-cloak)

And a sample partial view page

   div.row-fluid 
      div(ng-init="initMyOffers()")  
         accordion.span8.offset1(close-others="true")
            accordion-group(ng-repeat="item in data.myJobs", heading="{{item.title}}")
               accordion-heading
                  {{item.title}}
                  i.pull-right.icon-remove-circle.removeButton(ng:click="remove(item)") 
               p {{item.description}}
               hr
               div.footer
                  div.pull-left 
                     i.icon-calendar.calendar
                     {{item.dueDate | date:'d MMMM yyyy'}}
                  div.pull-right 
                     i.icon-user 
                     {{item.author}}

How can I reload a partial page when refreshing with F5 ?? What I expected with angular is that when trying to refresh for example the page /profile/dashboard, the partial /views/profile/dashboard.jade is called but also the views/profile.jade. And what about the $scope ?

Sorry, but I'm a little confioused... thanks for you help !

like image 644
GuillaumeA Avatar asked Nov 20 '13 19:11

GuillaumeA


2 Answers

I think it is a common problem and the user is not supposed to use F5 in your application. I do not think, it is possible to stop default browser action after F5 has been pressed.

One simple solution is to add this or similar script to every view:

<script>
    if (angular == undefined)
        // alert("It is SPA (Single Page Application) -- do not press F5 anymore, please.");
        window.location.replace("your/main/url");
</script>

A bit more complicated would be realization of the following scenario.

  1. user hits f5
  2. server sends partial view for current url current_url
  3. client codes detects lack of angular and send request to be redirected to current_url
  4. server sends modified version of the index.html file [with e.g. some hidden input field, that stores current_url]
  5. after angular has been loaded, the application checks the hidden field and change the location accordingly
like image 144
artur grzesiak Avatar answered Sep 25 '22 08:09

artur grzesiak


The simplest and most elegant way to avoid losing stuff when refreshing an Angular app is to store whatever values you need in a cookie by using $cookies service. Here's an example. Hope this helps.

"use strict";
angular.module('myApp').factory('SessionSrv', [ '$cookies', function($cookies){

    var _myString = $cookies.get('myString'); // e.g. "foo"
    var _myObject = $cookies.getObject('myObject'); // e.g. {foo: "bar"}

    return {

        setMyString: function(myString){
            _myString = myString;
            $cookies.put('myString', _myString);
        },

        getMyString: function(){
            return _myString;
        },

        setMyObject: function(myObject){
            _myObject = myObject;
            $cookies.putObject('myObject', _myObject);
        },

        getMyObject: function(){
            return _myObject;
        },

    };
}]);
like image 33
Mig82 Avatar answered Sep 21 '22 08:09

Mig82