$ rootScope. $ digest - это очистка параметров [duplicate]

Используйте moment.js для синтаксического анализа дат:

var caseOne = moment("Jul 8, 2005", "MMM D, YYYY", true).toDate();
var caseTwo = moment("2005-07-08", "YYYY-MM-DD", true).toDate();

Третий аргумент определяет строгий разбор (доступно с 2.3.0). Без него moment.js также может давать неверные результаты.

177
задан Coder1 20 February 2013 в 13:45
поделиться

10 ответов

Если вам не нужно использовать URL, например #/item/{{item.id}}/foo и #/item/{{item.id}}/bar, но #/item/{{item.id}}/?foo и #/item/{{item.id}}/?bar, вы можете настроить свой маршрут для /item/{{item.id}}/, чтобы reloadOnSearch установил false ( docs.angularjs.org/api/ngRoute.$routeProvider [/ д0]). Это говорит, что AngularJS не перезагружает представление, если изменяется поисковая часть URL-адреса.

106
ответ дан Michele Marcucci 17 August 2018 в 10:16
поделиться
  • 1
    Спасибо за это. Я пытаюсь выяснить, где я тогда сменил бы контроллер. – Coder1 20 February 2013 в 09:44
  • 2
    Понял. Добавлен параметр controller для моего массива view, а затем добавлен ng-controller="view.controller" в директиву ng-include. – Coder1 20 February 2013 в 10:42
  • 3
    Вы должны создать часы на $ location.search () в itemCtrlInit и в зависимости от параметра поиска обновить $ scope.view.template. И тогда эти шаблоны могут быть обернуты чем-то вроде <div ng-controller="itemFooCtrl">... your template content...</div>. EDIT: Приятно видеть, что вы решили, было бы здорово, если бы вы обновили свой вопрос, как вы решили, возможно, с помощью jsFiddle. – Anders Ekdahl 20 February 2013 в 10:42
  • 4
    Я обновлю его, когда нахожусь на 100%. У меня есть некоторые причуды с областью действия в дочерних контроллерах и ng-click. Если я загружу непосредственно из foo, ng-click выполняется в пределах области foo. Затем я нажимаю на строку, и ng-clicks в этом шаблоне будут выполняться в родительской области. – Coder1 20 February 2013 в 11:24
  • 5
    Следует отметить, что вам действительно не нужно переформатировать URLS. Возможно, это был случай, когда ответ был отправлен, но документация ( docs.angularjs.org/api/ngRoute.$routeProvider ) теперь говорит: [reloadOnSearch = true] - {boolean =} - перезагрузите маршрут, когда меняются только $ location.search () или $ location.hash (). – Rhys van der Waerden 11 February 2014 в 03:35

В ответах выше, включая GitHub, были некоторые проблемы для моего сценария, а также кнопка «Назад» или «Прямое изменение URL» из браузера - это перезагрузка контроллера, что мне не понравилось. Наконец я пошел со следующим подходом:

1. Определите свойство в определениях маршрутов, называемое noReload, для тех маршрутов, где вы не хотите, чтобы контроллер перезагружался при изменении маршрута.

.when('/:param1/:param2?/:param3?', {
    templateUrl: 'home.html',
    controller: 'HomeController',
    controllerAs: 'vm',
    noReload: true
})

2. В функции запуска вашего модуля поместите логику, которая проверяет эти маршруты. Это предотвратит перезагрузку, только если noReload - true, а предыдущий маршрут - тот же.

fooRun.$inject = ['$rootScope', '$route', '$routeParams'];

function fooRun($rootScope, $route, $routeParams) {
    $rootScope.$on('$routeChangeStart', function (event, nextRoute, lastRoute) {
        if (lastRoute && nextRoute.noReload 
         && lastRoute.controller === nextRoute.controller) {
            var un = $rootScope.$on('$locationChangeSuccess', function () {
                un();
                // Broadcast routeUpdate if params changed. Also update
                // $routeParams accordingly
                if (!angular.equals($route.current.params, lastRoute.params)) {
                    lastRoute.params = nextRoute.params;
                    angular.copy(lastRoute.params, $routeParams);
                    $rootScope.$broadcast('$routeUpdate', lastRoute);
                }
                // Prevent reload of controller by setting current
                // route to the previous one.
                $route.current = lastRoute;
            });
        }
    });
}

3. Наконец, в контроллере слушайте событие $ routeUpdate, чтобы вы могли делать все, что вам нужно, когда изменяются параметры маршрута.

HomeController.$inject = ['$scope', '$routeParams'];

function HomeController($scope, $routeParams) {
    //(...)

    $scope.$on("$routeUpdate", function handler(route) {
        // Do whatever you need to do with new $routeParams
        // You can also access the route from the parameter passed
        // to the event
    });

    //(...)
}

Имейте в виду, что при таком подходе вы не меняете вещи в контроллер, а затем обновить путь соответственно. Это наоборот. Сначала вы меняете путь, затем слушаете событие $ routeUpdate, чтобы изменить ситуацию в контроллере, когда изменяются параметры маршрута.

Это упрощает и согласовывает действия, поскольку вы можете использовать ту же логику, когда вы просто изменяете путь ( но без дорогостоящих $ http-запросов, если хотите) и когда вы полностью перезагрузите браузер.

0
ответ дан CGodo 17 August 2018 в 10:16
поделиться

Для тех, кому требуется изменение пути () без перезагрузки контроллеров. Вот плагин: https://github.com/anglibs/angular-location-update

Использование:

$location.update_path('/notes/1');

На основании https://stackoverflow.com/a/24102139/1751321

PS Это решение https://stackoverflow.com/a/24102139/1751321 содержит ошибку после вызова пути (, false) - это приведет к потере навигации браузера назад / вперед, пока путь (, true) не будет вызван

11
ответ дан Community 17 August 2018 в 10:16
поделиться

Существует простой способ изменения пути без перезагрузки

URL is - http://localhost:9000/#/edit_draft_inbox/1457

Используйте этот код для изменения URL-адреса, страница не будет перенаправлена ​​

. Второй параметр «false» очень важен.

$location.path('/edit_draft_inbox/'+id, false);
0
ответ дан Dinesh Vaitage 17 August 2018 в 10:16
поделиться

Хотя этот пост является старым и имеет принятый ответ, использование reloadOnSeach = false не решает проблему для тех из нас, кому нужно изменить фактический путь, а не только параметры. Вот простое решение:

Используйте ng-include вместо ng-view и назначьте свой контроллер в шаблоне.

<!-- In your index.html - instead of using ng-view -->
<div ng-include="templateUrl"></div>

<!-- In your template specified by app.config -->
<div ng-controller="MyController">{{variableInMyController}}</div>

//in config
$routeProvider
  .when('/my/page/route/:id', { 
    templateUrl: 'myPage.html', 
  })

//in top level controller with $route injected
$scope.templateUrl = ''

$scope.$on('$routeChangeSuccess',function(){
  $scope.templateUrl = $route.current.templateUrl;
})

//in controller that doesn't reload
$scope.$on('$routeChangeSuccess',function(){
  //update your scope based on new $routeParams
})

Только нижняя сторона - это то, что вы не можете использовать разрешить атрибут, но это довольно легко обойти. Также вам нужно управлять состоянием контроллера, например, логикой на основе $ routeParams, поскольку маршрут изменяется в контроллере по мере изменения соответствующего URL.

Вот пример: http: // plnkr. сотрудничество / редактировать / WtAOm59CFcjafMmxBVOP? р = предварительный просмотр

10
ответ дан Lukus 17 August 2018 в 10:16
поделиться
  • 1
    Кнопка «Назад» не работает (демонстрацию plunkr в собственном окне) – Gil Birman 25 September 2013 в 09:26
  • 2
    Не уверен, что кнопка «Назад» будет корректно вести себя в plnkr ... Как я уже говорил, вам нужно управлять некоторыми вещами самостоятельно, поскольку маршрут изменяется. Это не самое подходящее для кода решение, но оно работает – Lukus 25 September 2013 в 22:15

Вот мое более полное решение, которое решает несколько вещей: @ Vigrond и @rahilwazir пропущены:

  • Когда параметры поиска были изменены, это предотвратило бы трансляцию $routeUpdate.
  • Когда маршрут фактически оставлен без изменений, $locationChangeSuccess никогда не запускается, что приводит к предотвращению обновления маршрута next .
  • Если в том же цикле дайджеста был еще один запрос на обновление , на этот раз, желая перезагрузить, обработчик события отменит эту перезагрузку.
    app.run(['$rootScope', '$route', '$location', '$timeout', function ($rootScope, $route, $location, $timeout) {
        ['url', 'path'].forEach(function (method) {
            var original = $location[method];
            var requestId = 0;
            $location[method] = function (param, reload) {
                // getter
                if (!param) return original.call($location);
    
                # only last call allowed to do things in one digest cycle
                var currentRequestId = ++requestId;
                if (reload === false) {
                    var lastRoute = $route.current;
                    // intercept ONLY the next $locateChangeSuccess
                    var un = $rootScope.$on('$locationChangeSuccess', function () {
                        un();
                        if (requestId !== currentRequestId) return;
    
                        if (!angular.equals($route.current.params, lastRoute.params)) {
                            // this should always be broadcast when params change
                            $rootScope.$broadcast('$routeUpdate');
                        }
                        var current = $route.current;
                        $route.current = lastRoute;
                        // make a route change to the previous route work
                        $timeout(function() {
                            if (requestId !== currentRequestId) return;
                            $route.current = current;
                        });
                    });
                    // if it didn't fire for some reason, don't intercept the next one
                    $timeout(un);
                }
                return original.call($location, param);
            };
        });
    }]);
    
0
ответ дан Oded Niv 17 August 2018 в 10:16
поделиться
  • 1
    typo path в конце должен быть param, также это не работает с хэшами, а url в моей адресной строке не обновляется – deltree 18 October 2016 в 00:58
  • 2
    Исправлена. Хм, странно, это работает для меня, хотя на URL-адресах html5. Может все еще помочь кому-то, я думаю ... – Oded Niv 18 October 2016 в 05:35

Я использую это решение

angular.module('reload-service.module', [])
.factory('reloadService', function($route,$timeout, $location) {
  return {
     preventReload: function($scope, navigateCallback) {
        var lastRoute = $route.current;

        $scope.$on('$locationChangeSuccess', function() {
           if (lastRoute.$$route.templateUrl === $route.current.$$route.templateUrl) {
              var routeParams = angular.copy($route.current.params);
              $route.current = lastRoute;
              navigateCallback(routeParams);
           }
        });
     }
  };
})

//usage
.controller('noReloadController', function($scope, $routeParams, reloadService) {
     $scope.routeParams = $routeParams;

     reloadService.preventReload($scope, function(newParams) {
        $scope.routeParams = newParams;
     });
});

. Этот подход сохраняет функциональность кнопки «Назад», и вы всегда используете текущие параметры маршрута в шаблоне, в отличие от некоторых других подходов, которые я видел.

1
ответ дан parliament 17 August 2018 в 10:16
поделиться

Если вам нужно изменить путь, добавьте это после вашего .config в файл приложения. Затем вы можете сделать $location.path('/sampleurl', false);, чтобы предотвратить перезагрузку

app.run(['$route', '$rootScope', '$location', function ($route, $rootScope, $location) {
    var original = $location.path;
    $location.path = function (path, reload) {
        if (reload === false) {
            var lastRoute = $route.current;
            var un = $rootScope.$on('$locationChangeSuccess', function () {
                $route.current = lastRoute;
                un();
            });
        }
        return original.apply($location, [path]);
    };
}])

. Кредит переходит на https://www.consolelog.io/angularjs-change-path-without-reloading для самое элегантное решение, которое я нашел.

86
ответ дан ThisClark 17 August 2018 в 10:16
поделиться
  • 1
    Отличное решение. Есть ли в любом случае, чтобы получить кнопку возврата браузера в «честь»? это? – Mark B 30 July 2014 в 22:52
  • 2
    Имейте в виду, что это решение поддерживает старый маршрут, и если вы запрашиваете $ route.current, вы получите предыдущий путь, а не текущий. В противном случае это отличный маленький взлом. – jornare 8 August 2014 в 14:37
  • 3
    Просто хотел сказать, что оригинальное решение было подробно опубликовано журналом «EvanWinstanley». здесь: github.com/angular/angular.js/issues/1699#issuecomment-34841248 – chipit24 17 September 2014 в 05:25
  • 4
    Я использовал это решение какое-то время и просто заметил, что при некоторых изменениях пути перезагружают регистры как ложные, даже когда передается истинное значение. У кого-то еще были такие проблемы? – Will Hitchcock 13 April 2015 в 17:53
  • 5
    Я должен был добавить $timeout(un, 200); перед операцией return, поскольку иногда $locationChangeSuccess не срабатывал вообще после apply (и маршрут не был изменен, когда это действительно необходимо). Мое решение очищает вещи после вызова пути (..., false) – snowindy 11 October 2015 в 10:32

Добавить следующий внутренний тег заголовка

  <script type="text/javascript">
    angular.element(document.getElementsByTagName('head')).append(angular.element('<base href="' + window.location.pathname + '" />'));
  </script>

Это предотвратит перезагрузку.

0
ответ дан Vivek 17 August 2018 в 10:16
поделиться

почему бы просто не поставить ng-контроллер на один уровень выше,

<body ng-controller="ProjectController">
    <div ng-view><div>

И не устанавливать контроллер на маршруте,

.when('/', { templateUrl: "abc.html" })

он работает для меня.

17
ответ дан windmaomao 17 August 2018 в 10:16
поделиться
  • 1
    отличный совет, он отлично работает и для моего сценария! Большое спасибо! :) – daveoncode 17 March 2015 в 12:23
  • 2
    Это отличный «россияне использовали карандаши». ответ, работает для меня :) – inolasco 19 March 2015 в 22:53
  • 3
    Я говорил слишком рано. В этом обходном пути возникает проблема: если вам нужно загрузить значения из $ routeParams в контроллере, они не будут загружаться, по умолчанию - {} – inolasco 20 March 2015 в 00:49
  • 4
    @inolasco: работает, если вы читаете ваши $ routeParams в обработчике $ routeChangeSuccess. Чаще всего это, вероятно, то, что вы хотите в любом случае. чтение только в контроллере приведет только к значениям для первоначально загруженного URL. – plong0 19 May 2015 в 21:14
  • 5
    @ plong0 Хорошая точка, должна работать. Однако в моем случае мне нужно было получить значения URL, когда контроллер загружается при загрузке страницы, чтобы инициализировать определенные значения. Я закончил использование решения, предложенного vigrond, используя $ locationChangeSuccess, но ваш другой вариант. – inolasco 20 May 2015 в 22:11
Другие вопросы по тегам:

Похожие вопросы: