Какой самый краткий способ прочитать параметры запроса в AngularJS?

279

Я хотел бы прочитать значения параметров URL-запроса, используя AngularJS. Я обращаюсь к HTML со следующим URL-адресом:

http://127.0.0.1:8080/test.html?target=bob

Как и ожидалось, location.search составляет "?target=bob". Для доступа к значению цели я нашел несколько примеров, перечисленных в Интернете, но ни один из них не работает в AngularJS 1.0.0rc10. В частности, все undefined:

  • $location.search.target
  • $location.search['target']
  • $location.search()['target']

Кто-нибудь знает, что будет работать? (Я использую $location в качестве параметра для моего контроллера)


Update:

Я разместил решение ниже, но я не вполне доволен этим. Документация в Руководство разработчика: Angular Сервисы: с помощью $location указано следующее о $location:

Когда следует использовать $location?

Каждый раз, когда ваше приложение должно реагировать на изменение текущего URL или если вы хотите изменить текущий URL-адрес в браузере.

В моем сценарии моя страница будет открыта с внешней веб-страницы с параметром запроса, поэтому я не буду реагировать на изменение текущего URL-адреса. Так что, может быть, $location не является правильным инструментом для работы (для уродливых деталей см. Мой ответ ниже). Поэтому я изменил название этого вопроса: "Как читать параметры запроса в AngularJS с помощью $location?" на "Какой самый сжатый способ чтения параметров запроса в AngularJS?". Очевидно, я мог бы просто использовать javascript и регулярное выражение для синтаксического анализа location.search, но переход на этот низкоуровневый уровень для чего-то такого базового действительно оскорбляет мою чувствительность программиста.

Итак: есть ли лучший способ использовать $location, чем я в своем ответе, или есть ли более краткий вариант?

  • 1
    Разве $ location.search () ['target'] не должен работать?
  • 0
    Это не работает, потому что после пути нет хеша. http://127.0.0.1:8080/test.html#?target=bob будет работать, обратите внимание на # перед ? , $location - это метод маршрутизации второго уровня, который не отправляется на сервер.
Показать ещё 1 комментарий
Теги:
ngroute

10 ответов

201

Вы можете ввести $routeParams (требуется ngRoute) в ваш контроллер. Вот пример из документов:

// Given:
// URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby
// Route: /Chapter/:chapterId/Section/:sectionId
//
// Then
$routeParams ==> {chapterId:1, sectionId:2, search:'moby'}

EDIT: вы также можете получить и установить параметры запроса с помощью службы $location (доступной в ng), в частности ее search: $location.search().

$routeParams менее полезны после начальной загрузки контроллера; $location.search() можно вызывать в любое время.

  • 1
    Спасибо за предложение и ссылку! Я прочитал страницу и также попытался настроить рабочий образец. Тем не менее, подход не сработает для меня, потому что я действительно не хочу использовать маршрутизацию в этом случае. Тем не менее, это было полезное предложение, и я оповестю его, как только у меня будет достаточно стэкаповерпла.
  • 1
    Я бы сказал, что ответ @ pkozlowski.opensource более точен в этой ситуации.
Показать ещё 4 комментария
181

Хорошо, что вам удалось заставить его работать с режимом html5, но также можно заставить его работать в режиме hashbang.

Вы можете просто использовать:

$location.search().target

чтобы получить доступ к параметру "target".

Для справки, вот рабочий jsFiddle: http://web.archive.org/web/20130317065234/http://jsfiddle.net/PHnLb/7/

var myApp = angular.module('myApp', []);

function MyCtrl($scope, $location) {

    $scope.location = $location;
    $scope.$watch('location.search()', function() {
        $scope.target = ($location.search()).target;
    }, true);

    $scope.changeTarget = function(name) {
        $location.search('target', name);
    }
}
<div ng-controller="MyCtrl">

    <a href="#!/test/?target=Bob">Bob</a>
    <a href="#!/test/?target=Paul">Paul</a>
    
    <hr/>    
    URL 'target' param getter: {{target}}<br>
    Full url: {{location.absUrl()}}
    <hr/>
    
    <button ng-click="changeTarget('Pawel')">target=Pawel</button>
    
</div>
  • 2
    Вам нужны скобки вокруг $ location.search ()?
  • 2
    @Magne: да, вам нужны скобки, $ location.search - это метод docs.angularjs.org/api/ng/service/$location
Показать ещё 10 комментариев
50

Чтобы дать частичный ответ на мой собственный вопрос, вот рабочий пример для браузеров HTML5:

<!DOCTYPE html>
<html ng-app="myApp">
<head>
  <script src="http://code.angularjs.org/1.0.0rc10/angular-1.0.0rc10.js"></script>
  <script>
    angular.module('myApp', [], function($locationProvider) {
      $locationProvider.html5Mode(true);
    });
    function QueryCntl($scope, $location) {
      $scope.target = $location.search()['target'];
    }
  </script>
</head>
<body ng-controller="QueryCntl">

Target: {{target}}<br/>

</body>
</html>

Ключом был вызов $locationProvider.html5Mode(true);, как указано выше. Теперь он работает при открытии http://127.0.0.1:8080/test.html?target=bob. Я не доволен тем, что он не будет работать в старых браузерах, но я мог бы использовать этот подход в любом случае.

Альтернативой, которая будет работать со старыми браузерами, было бы отказаться от вызова html5mode(true) и вместо этого использовать следующий адрес с hash + slash:

http://127.0.0.1:8080/test.html#/?target=bob

Соответствующая документация находится в Руководство разработчика: Angular Услуги: использование $location (странно, что мой поиск в Google не нашел этого...).

  • 0
    Спасибо за это. Я выдернул свои волосы, пытаясь прочитать в параметрах запроса. Продолжал получать «неопределенный», как вы упомянули выше. Настройка режима на html5 сработала.
  • 0
    Не должен ли атрибут ng-controller для <body> быть установлен в MyApp ?
Показать ещё 1 комментарий
16

Это можно сделать двумя способами:

  • Использование $routeParams

Лучшее и рекомендуемое решение - использовать $routeParams в вашем контроллере. Он требует установки модуля ngRoute.

   function MyController($scope, $routeParams) {
      // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby
      // Route: /Chapter/:chapterId/Section/:sectionId
      // $routeParams ==> {chapterId:'1', sectionId:'2', search:'moby'}
      var search = $routeParams.search;
  }
  1. Использование $location.search().

Здесь есть оговорка. Он будет работать только в режиме HTML5. По умолчанию он не работает для URL-адреса, который не имеет хеша (#) в нем http://localhost/test?param1=abc&param2=def

Вы можете заставить его работать, добавив #/ в URL. http://localhost/test#/?param1=abc&param2=def

$location.search(), чтобы вернуть объект, например:

{
  param1: 'abc',
  param2: 'def'
}
  • 5
    Спасибо за ваш совет с # /
7

$location.search() будет работать только с включенным режимом HTML5 и только при поддержке браузера.

Это будет работать всегда:

$window.location.search

5

Просто для летания.

Если ваше приложение загружается из внешних ссылок, то angular не обнаружит это как изменение URL-адреса, поэтому $loaction.search() предоставит вам пустой объект. Чтобы решить эту проблему, вам нужно установить следующие настройки приложения (app.js)

.config(['$routeProvider', '$locationProvider', function ($routeProvider,     $locationProvider) 
{
   $routeProvider
      .when('/', {
         templateUrl: 'views/main.html',
         controller: 'MainCtrl'
      })
      .otherwise({
         redirectTo: '/'
      });

      $locationProvider.html5Mode(true);
 }]);
  • 1
    Ага. Это было больно найти. Спасибо за комментарий.
2

вы также можете использовать $location. $$ search.yourparameter

  • 17
    $$search - это внутренняя переменная, использование которой не очень хорошая идея.
1

Просто точность ответа Эллиса Уайтхеда. $locationProvider.html5Mode(true); не будет работать с новой версией angularjs без указания базового URL-адреса приложения с тегом <base href=""> или установки параметра requireBase на false

Из документа:

Если вы настроите $location для использования html5Mode (history.pushState), вам нужно указать базовый URL-адрес приложения с тегом или настроить $locationProvider, чтобы не требовать базовый тег, передав объект определения с requireBase: false для $locationProvider.html5Mode():

$locationProvider.html5Mode({
  enabled: true,
  requireBase: false
});
1

это может помочь uou

Какой самый сжатый способ чтения параметров запроса в AngularJS

// Given:
// URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby
// Route: /Chapter/:chapterId/Section/:sectionId
//
// Then
$routeParams ==> {chapterId:1, sectionId:2, search:'moby'}

<!DOCTYPE html>
<html ng-app="myApp">
<head>
  <script src="http://code.angularjs.org/1.0.0rc10/angular-1.0.0rc10.js"></script>
  <script>
    angular.module('myApp', [], function($locationProvider) {
      $locationProvider.html5Mode(true);
    });
    function QueryCntl($scope, $location) {
      $scope.target = $location.search()['target'];
    }
  </script>
</head>
<body ng-controller="QueryCntl">

Target: {{target}}<br/>

</body>
</html>

($location.search()).target
-3

Немного поздно, но я думаю, что ваша проблема была в вашем URL. Если вместо

http://127.0.0.1:8080/test.html?target=bob

у вас был

http://127.0.0.1:8080/test.html#/?target=bob

Я уверен, что это сработало бы. Angular действительно придирчив к своему #/

  • 0
    Это только если вы не включаете режим HTML5. # / Не всегда есть в угловых URL.
  • 0
    Это если вы строите СПА. У всех моих URL есть #. А HTML5Mode означает 1) 404 при обновлении страницы и 2) прямые URL не будут работать. Похоже на высокую цену.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню