threxx threxx - 13 days ago 9
Javascript Question

controller reloads even though reloadOnSearch is set false

i build a webpage where I have several views but only one controller. As the controller should not reload on page switch I changed all the routes to "/main/{{itemNo}}/?routname". However when switching pages the controller is still reloaded (so the language is always switched back to german even though english was selected). Can anybody tell me what I am doing wrong?

Here is some of my code:

This is part of the app.js with the new routes:

.config(function ($routeProvider) {
$routeProvider
.when('/main', {
templateUrl: 'views/main.html',
controller: 'MainCtrl',
controllerAs: 'main'
})
.when('/main/1/cart', {
templateUrl: 'views/cart.html',
controller: 'MainCtrl',
controllerAs: 'main',
reloadOnSearch: false
})
.when('/main/2/personaldata', {
templateUrl: 'views/personalData.html',
controller: 'MainCtrl',
controllerAs: 'main',
reloadOnSearch: false
})


This is my controller:

.controller('MainCtrl', function ($scope) {
this.awesomeThings = [
'HTML5 Boilerplate',
'AngularJS',
'Karma'
];
// console.log('init');




$('#german').click(function () {
changeValue('german');
});

$('#english').click(function () {
changeValue('english');
});

$('#toshoppingcart').click(function () {
setTimeout(function() {
changeValue(selectedLang);
}, 10);
});

$('#tocheckout').click(function () {
setTimeout(function() {
changeValue(selectedLang);
}, 10);
});



var loadScript = function (src, callbackfn) {
var newScript = document.createElement("script");
newScript.type = "text/javascript";
newScript.setAttribute("async", "true");
newScript.setAttribute("src", src);

if (newScript.readyState) {
newScript.onreadystatechange = function () {
if (/loaded|complete/.test(newScript.readyState)) callbackfn();
}
} else {
newScript.addEventListener("load", callbackfn, false);
}

document.documentElement.firstChild.appendChild(newScript);
};


function changeValue(language) {
console.log('change', language)
selectedLang = language;
if (language == 'english') {
loadScript("scripts/languages/english.js", function () {
updateValues()
});
} else {
loadScript("scripts/languages/german.js", function () {
updateValues()
});
}
}

var selectedLang = 'german';
changeValue(selectedLang);

Answer

The problem is that reloadOnSearch = false will prevent your route to reload when you change parameters (aka, search) or hash like ?q=blablabal and #/my-route#myHash. Instead of realoding it will trigger $routeUpdate on $rootScope. In your case, you aren't using either of them, you are changing the entire route, therefore it will reload the route.

According to the docs for $routeProvider:

[reloadOnSearch=true] - {boolean=} - reload route when only $location.search() or $location.hash() changes.

If the option is set to false and url in the browser changes, then $routeUpdate event is broadcasted on the root scope.

Also, you have to store selectedLang in a different location rather than the controller constructor scope, perhaps on $rootScope or localstorage, because every time the controller gets called (every route that you use it) your selectedLang variable is defined as 'german' instead of the previously deffined value.

Try something like this (of course, consider using the angular way of doing this, this is just an example):

function changeValue(language) {
  console.log('change', language)
  selectedLang = window.localStorage['language'] = language;
  if (language == 'english') {
    loadScript("scripts/languages/english.js", function () {
      updateValues()
    });
  } else {
    loadScript("scripts/languages/german.js", function () {
      updateValues()
    });
  }
}

var selectedLang = window.localStorage['language'] || 'german';
changeValue(selectedLang);