取り急ぎソースだけ。
pushState / popStateの動作なので、ブラウザの戻る/進むなどにも反応して、クエリパラメータの変更を検知できる。
現状、パラメータは一つしか変更対象にできないが、複数に対応できると思う。
html5Modeがオフだと動かないのどうしようかなあ。
js
var app = angular.module('app', []);
app.provider('queryChanger', function() {
var paramName = 'page';
this.setParamName = function( _paramName ) {
paramName = _paramName;
};
this.$get = [ '$location', '$rootScope', function( $location, $rootScope ) {
// ページ表示時、強制的に対象のクエリパラメータを付加する
if( $location.search()[paramName] == null ) {
var query = $location.search();
query[paramName] = 0;
$location.search( query ).replace();
}
// $locationのルーティング支配下から強引に脱出する
$rootScope.$on('$locationChangeStart', function( event, newUrl, oldUrl ) {
var before = document.createElement('a');
before.href = oldUrl;
var after = document.createElement('a');
after.href = newUrl;
if( before.pathname != after.pathname ) {
window.location.href = newUrl;
event.preventDefault();
}
});
$rootScope.$on('$locationChangeSuccess', function() {
$rootScope.$broadcast('queryChanged', $location.search()[paramName] );
});
return {
change: function( paramValue ) {
var query = $location.search();
query[paramName] = paramValue;
$location.search( query );
}
};
}];
});
// --- 使い方サンプル --- //
// まずコンフィグします
app.config( [ '$locationProvider', 'queryChangerProvider', function( $locationProvider, queryChangerProvider ) {
$locationProvider.html5Mode({
enabled: true,
requireBase: false
});
queryChangerProvider.setParamName( 'p' );
}]);
// 使います
app.controller('myController', function( $location, $scope, queryChanger ) {
var _this = this;
// クエリパラメータを変更する
this.next = function() {
queryChanger.change( _this.p + 1 );
};
// クエリパラメータが変更されたとき
// 最初のページ表示時にもここが発火します
$scope.$on('queryChanged', function( event, value ) {
_this.p = Number( value );
});
});