Який найкоротший спосіб читати параметри запиту в AngularJS?


312

Я хотів би прочитати значення параметрів URL-запиту за допомогою AngularJS. Я отримую доступ до HTML із такою URL-адресою:

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

Як і очікувалося, location.searchє "?target=bob". Для доступу до значення target я знайшов різні приклади, перелічені в Інтернеті, але жоден з них не працює в AngularJS 1.0.0rc10. Зокрема, такі undefined:

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

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


Оновлення:

Я розмістив рішення нижче, але не повністю задоволений ним. Документація в Посібнику розробника: Кутові послуги: Використання $ location визначає наступне про $location:

Коли я повинен використовувати $ location?

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

Для мого сценарію мою сторінку буде відкрито із зовнішньої веб-сторінки з параметром запиту, тому я сам по собі не реагую на зміну поточної URL-адреси. Тож, можливо, $locationце не правильний інструмент для роботи (про некрасиві деталі див. Мою відповідь нижче). Тому я змінив назву цього питання на "Як читати параметри запиту в AngularJS за допомогою $ location?" до "Який найкоротший спосіб зчитувати параметри запиту в AngularJS?". Очевидно, що я міг просто використовувати javascript і регулярне вираження для розбору location.search, але перехід цього низького рівня на щось настільки базове дійсно ображає мої функції програміста.

Отже: чи є кращий спосіб використання, $locationніж я, у своїй відповіді, або є лаконічне чергування?


1
Чи не повинен $ location.search () ['target'] працювати?
пограбувати

Це не спрацьовує, тому що немає хешу після шляху. http://127.0.0.1:8080/test.html#?target=bobбуде працювати, помітити #раніше ?. $locationце метод маршрутизації другого рівня, який не надсилається на сервер.
Даніель Ф

1
@DanielF @rob, ви обоє праві. $location.search()['target']працює після того, $locationProvider.html5Mode(true)як його викликали в сучасному браузері.
krispy

Відповіді:


199

Ви можете ввести $ 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 в цій ситуації точніша
Martín Coll

2
Не зовсім .. параметри запитів включаються в об’єкт $ routeParams з нормальними параметрами маршруту. і ви можете їх прочитати / встановити за допомогою $ location.search (). Я додам це до відповіді.
Ендрю Джослін

5
Якуб правий. Вони різні речі. Коли ви використовуєте "пошук" у кутку, він додає запит до хеша (кінець URL-адреси). Специфікація RFC для URI заявляє, що параметри запиту повинні додавати (а не додавати) хеш. Таким чином, "пошук" - це конструкція, яка лише кутова буде екстраполювати та інтерпретувати. Ось чому для рішення вище буде працювати лише режим HTML5, оскільки ви делегуєте всі запити на одній сторінці (на рівні сервера) незалежно від реального URI.
Стівен Пена

2
це працює лише в тому випадку, якщо ви хочете використовувати маршрут у angularJS!
windmaomao

189

Добре, що вам вдалося змусити його працювати в режимі html5, але також можна змусити його працювати в режимі хешбангу.

Ви можете просто використовувати:

$location.search().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
nandin

4
Не забувайте, що якщо ви не використовуєте, HTML5Mode(true)то на початку доступні лише параметри після # / або додані до URL з # / на початку.
Себастьян

21
@nandin: Ні, круглі дужки навколо не потрібні . Я не впевнений, чому ця відповідь ставить їх туди. $location.search()
Дан Тао

9
Я відчуваю, що @nandin неправильно зрозумів питання "Чи потрібні вам дужки". Ви робите потрібні круглі дужки після пошуку, але не ті , навколо повноти $location.search().
К. Карпентер

56

Щоб дати часткову відповідь на моє власне питання, ось робочий зразок для браузерів 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)дзвінка і використовувати замість такої адреси хеш + косу рису:

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

Відповідна документація знаходиться в Посібнику розробника: Кутові послуги: Використання $ location (дивно, що мій пошук в Google не знайшов цього ...).


Дякую за це Я витягнув волосся, намагаючись прочитати в парамах запитів. Продовжуйте отримувати "невизначений", як ви згадали вище. Режим налаштування на html5 працював.
sthomps

Чи не слід ng-controllerатрибут <body>бути встановлений MyApp?
Джаго

4
Схоже, починаючи з кутового 1.3, для того, щоб використовувати html5Mode, вам також потрібно або додати <base href="https://stackoverflow.com/" />тег, або додати requireBase: falseяк інший параметр виклику до html5Mode. Деталі тут
dae721

17

Це можна зробити двома способами:

  1. Використання $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
Дякую за пораду з # /
yonexbat

9

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

Це працюватиме завжди:

$ window.location.search


6

Тільки щоб літати.

Якщо ваш додаток завантажується із зовнішніх посилань, кутовий звичай не визначатиме це як зміну 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
Так. Це було болю знайти. Дякуємо за коментар
mikeborgh

2

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

Від док .

Якщо ви налаштуєте $ location для використання html5Mode (history.pushState), вам потрібно вказати базову URL-адресу програми з тегом або налаштувати $ locationProvider, щоб не вимагати базового тегу, передавши об’єкт визначення з RequBase: false до $ locationProvider. html5Mode ():

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

1

ви також можете використовувати $ location. $$ search.yourparameter


18
Це $$searchвнутрішня змінна, використання якої не є такою хорошою ідеєю.
кумархарш

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

1

Я виявив, що для SPA HTML5Mode виникає багато проблем із помилками 404, і не потрібно змушувати $ location.search працювати в цьому випадку. У моєму випадку я хочу зафіксувати параметр рядка запиту URL-адреси, коли користувач заходить на мій сайт, незалежно від того, на яку "сторінку" вони спочатку посилаються, і я можу надсилати їх на цю сторінку, коли вони ввійдуть у систему. Тому я просто захоплюю всі ті речі в app.run

$rootScope.$on('$stateChangeStart', function (e, toState, toParams, fromState, fromParams) {
    if (fromState.name === "") {
        e.preventDefault();
        $rootScope.initialPage = toState.name;
        $rootScope.initialParams = toParams;
        return;
    }
    if ($location.search().hasOwnProperty('role')) {
        $rootScope.roleParameter = $location.search()['role'];
    }
    ...
}

потім пізніше після входу я можу сказати $ state.go ($ rootScope.initialPage, $ rootScope.initialParams)


-3

Це трохи пізно, але я думаю, що вашою проблемою була ваша URL-адреса. Якщо замість

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

ти мав

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

Я майже впевнений, що це спрацювало б. Кутова дійсно прискіплива до свого # /


Це лише в тому випадку, якщо ви не вмикаєте режим HTML5. # / Не завжди є в кутових URL-адресах.
LocalPCGuy

Це якщо ви будуєте SPA. Усі мої URL-адреси мають #. І HTML5Mode означає 1) 404 на оновлення сторінки та 2) прямі URL-адреси не працюватимуть. Здається, висока плата.
nuander
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.