Cách ngắn gọn nhất để đọc các tham số truy vấn trong AngularJS là gì?


312

Tôi muốn đọc các giá trị của các tham số truy vấn URL bằng AngularJS. Tôi đang truy cập HTML bằng URL sau:

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

Như mong đợi, location.search"?target=bob". Để truy cập giá trị của mục tiêu , tôi đã tìm thấy các ví dụ khác nhau được liệt kê trên web, nhưng không có ví dụ nào hoạt động trong AngularJS 1.0.0rc10. Cụ thể, sau đây là tất cả undefined:

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

Bất cứ ai biết những gì sẽ làm việc? (Tôi đang sử dụng $locationlàm tham số cho bộ điều khiển của mình)


Cập nhật:

Tôi đã đăng một giải pháp bên dưới, nhưng tôi không hoàn toàn hài lòng với nó. Tài liệu tại Hướng dẫn dành cho nhà phát triển: Dịch vụ góc: Sử dụng vị trí $ nêu các điều sau về $location:

Khi nào tôi nên sử dụng vị trí $?

Bất cứ lúc nào ứng dụng của bạn cần phản ứng với thay đổi trong URL hiện tại hoặc nếu bạn muốn thay đổi URL hiện tại trong trình duyệt.

Đối với kịch bản của tôi, trang của tôi sẽ được mở từ một trang web bên ngoài với tham số truy vấn, vì vậy tôi không "phản ứng với thay đổi trong URL hiện tại" mỗi lần. Vì vậy, có lẽ $locationkhông phải là công cụ phù hợp cho công việc (đối với các chi tiết xấu, xem câu trả lời của tôi dưới đây). Do đó, tôi đã thay đổi tiêu đề của câu hỏi này từ "Cách đọc tham số truy vấn trong AngularJS bằng cách sử dụng $ location?" thành "Cách ngắn gọn nhất để đọc các tham số truy vấn trong AngularJS là gì?". Rõ ràng là tôi chỉ có thể sử dụng javascript và biểu thức chính quy để phân tích cú pháp location.search, nhưng việc sử dụng mức độ thấp đó cho một cái gì đó rất cơ bản thực sự xúc phạm sự nhạy cảm của lập trình viên của tôi.

Vì vậy: có cách nào tốt hơn để sử dụng $locationhơn tôi trong câu trả lời của tôi, hoặc có một cách thay thế ngắn gọn?


1
Không nên $ location.search () ['target']?
cướp

Điều này không hoạt động, vì không có băm sau đường dẫn. http://127.0.0.1:8080/test.html#?target=bobsẽ làm việc, thông báo #trước ?. $locationlà một phương thức định tuyến cấp hai không được gửi đến máy chủ.
Daniel F

1
@DanielF @rob, bạn đều đúng cả. $location.search()['target']hoạt động sau khi $locationProvider.html5Mode(true)đã được gọi trong một trình duyệt hiện đại.
krispy 22/03/2016

Câu trả lời:


199

Bạn có thể đưa $ routeParams (yêu cầu ngRoute ) vào bộ điều khiển của bạn. Đây là một ví dụ từ các tài liệu:

// 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: Bạn cũng có thể nhận và đặt tham số truy vấn với dịch vụ $ location (có sẵn trong ng), đặc biệt là searchphương thức của nó : $ location.search () .

$ routeParams ít hữu ích hơn sau khi tải ban đầu của bộ điều khiển; $location.search()có thể được gọi bất cứ lúc nào.


1
Cảm ơn lời đề nghị và liên kết! Tôi đọc trang và cũng đã cố gắng thiết lập một mẫu làm việc. Tuy nhiên, cách tiếp cận sẽ không hiệu quả với tôi, vì tôi thực sự không muốn sử dụng định tuyến trong trường hợp này. Tuy nhiên, đây là một gợi ý hữu ích và tôi sẽ nâng cấp nó một khi tôi có đủ đại diện stackoverflow.
Ellis Whitehead

1
Tôi muốn nói câu trả lời của @ pkozlowski.opensource chính xác hơn trong tình huống này
Martín Coll

2
Không hoàn toàn .. các tham số truy vấn được bao gồm trong đối tượng $ routeParams với các tham số tuyến thông thường. và bạn có thể đọc chúng / đặt chúng với $ location.search (). Tôi sẽ thêm nó vào câu trả lời.
Andrew Joslin

5
Jakub nói đúng. Chúng là những thứ khác nhau. Khi bạn sử dụng "tìm kiếm" theo góc, nó sẽ nối truy vấn vào hàm băm (cuối URL). Thông số RFC cho URI nói rằng các tham số truy vấn nên thêm vào (không nối thêm) hàm băm. Do đó, "tìm kiếm" là một cấu trúc mà chỉ có góc sẽ ngoại suy và giải thích. Đây là lý do tại sao chỉ có chế độ HTML5 sẽ hoạt động cho giải pháp ở trên, vì bạn đang ủy thác tất cả các yêu cầu cho một trang (ở cấp máy chủ) bất kể URI thực tế.
Steven Pena

2
Điều này chỉ hoạt động nếu bạn muốn sử dụng tuyến đường trong angularJS!
Windmaomao

189

Thật tốt khi bạn đã quản lý để làm cho nó hoạt động với chế độ html5 nhưng cũng có thể làm cho nó hoạt động ở chế độ hashbang.

Bạn chỉ có thể sử dụng:

$location.search().target

để có quyền truy cập vào thông số tìm kiếm 'mục tiêu'.

Để tham khảo, đây là jsFiddle đang hoạt động: 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
bạn có cần dấu ngoặc đơn quanh $ location.search () không?
Magne

2
@Magne: có, bạn cần dấu ngoặc đơn, $ location.search là một phương thức docs.angularjs.org/api/ng/service/$location
nandin

4
Đừng quên rằng nếu bạn không sử dụng HTML5Mode(true)thì chỉ params sau # / có sẵn hoặc được thêm vào url với # / lúc đầu.
Sebastian

21
@nandin: Không, bạn không cần dấu ngoặc đơn xung quanh $location.search() . Tôi không chắc tại sao câu trả lời này lại đặt chúng ở đó.
Dan Tao

9
Tôi cảm thấy như @nandin đã hiểu nhầm câu hỏi "Bạn có cần dấu ngoặc đơn" không. Bạn làm cần ngoặc sau khi tìm kiếm, nhưng không phải là những xung quanh toàn bộ $location.search().
K. Thợ mộc

56

Để trả lời một phần câu hỏi của riêng tôi, đây là một mẫu hoạt động cho các trình duyệt 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>

Chìa khóa là gọi $locationProvider.html5Mode(true);như đã làm ở trên. Bây giờ nó hoạt động khi mở http://127.0.0.1:8080/test.html?target=bob. Tôi không hài lòng về việc nó sẽ không hoạt động trong các trình duyệt cũ hơn, nhưng dù sao tôi cũng có thể sử dụng phương pháp này.

Một cách khác có thể hoạt động với các trình duyệt cũ hơn là bỏ html5mode(true)cuộc gọi và sử dụng địa chỉ sau với hàm băm + gạch chéo thay thế:

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

Tài liệu liên quan có tại Hướng dẫn dành cho nhà phát triển: Dịch vụ góc: Sử dụng vị trí $ (lạ là tìm kiếm google của tôi không tìm thấy điều này ...).


Cảm ơn vì điều đó. Tôi đã kéo tóc ra để đọc trong thông số truy vấn. Giữ được "không xác định" như bạn đã đề cập ở trên. Chế độ cài đặt thành html5 hoạt động.
sthomps

Nên không phải là ng-controllerthuộc tính của <body>được thiết lập để MyApp?
Jago

4
Có vẻ như bắt đầu với Angular 1.3, để sử dụng html5Mode, bạn cũng cần thêm <base href="https://stackoverflow.com/" />thẻ hoặc thêm requireBase: falsedưới dạng tham số khác vào lệnh gọi tới html5Mode. Chi tiết tại đây
dae721

17

Nó có thể được thực hiện bằng hai cách:

  1. Sử dụng $routeParams

Giải pháp tốt nhất và được đề nghị là sử dụng $routeParamsvào bộ điều khiển của bạn. Nó yêu cầu các ngRoutemô-đun được cài đặt.

   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. Sử dụng $location.search().

Có một cảnh báo ở đây. Nó sẽ chỉ hoạt động với chế độ HTML5. Theo mặc định, nó không hoạt động đối với URL không có hàm băm ( #) trong đóhttp://localhost/test?param1=abc&param2=def

Bạn có thể làm cho nó hoạt động bằng cách thêm #/vào URL.http://localhost/test#/?param1=abc&param2=def

$location.search() để trả về một đối tượng như:

{
  param1: 'abc',
  param2: 'def'
}

5
Cảm ơn lời khuyên của bạn với # /
yonexbat

9

$ location.search () sẽ chỉ hoạt động với chế độ HTML5 được bật và chỉ trên trình duyệt hỗ trợ.

Điều này sẽ luôn hoạt động:

$ window.location.search


6

Chỉ để mùa hè.

Nếu ứng dụng của bạn đang được tải từ các liên kết bên ngoài thì angular sẽ không phát hiện ra đây là một thay đổi URL, vì vậy $ loaction.search () sẽ cung cấp cho bạn một đối tượng trống. Để giải quyết vấn đề này, bạn cần đặt sau trong cấu hình ứng dụng của mình (app.js)

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

      $locationProvider.html5Mode(true);
 }]);

1
Vâng. Đây là một nỗi đau để tìm. Cảm ơn các bình luận.
mikeborgh

2

Chỉ cần một sự chính xác cho câu trả lời của Ellis Whitehead. $locationProvider.html5Mode(true);sẽ không hoạt động với phiên bản mới của angularjs mà không chỉ định URL cơ sở cho ứng dụng bằng <base href="">thẻ hoặc đặt tham số requireBasethànhfalse

Từ tài liệu :

Nếu bạn định cấu hình $ location để sử dụng html5Mode (history.pushState), bạn cần chỉ định URL cơ sở cho ứng dụng bằng thẻ hoặc định cấu hình $ locationProvider để không yêu cầu thẻ cơ sở bằng cách chuyển một đối tượng định nghĩa với allowBase: false sang $ locationProvider. html5Mode ():

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

1

bạn cũng có thể sử dụng $ location. $$ search.yourparameter


18
Đây $$searchlà một biến nội bộ, việc sử dụng nó không phải là một ý tưởng tốt.
kumarharsh

1

điều này có thể giúp bạn

Cách ngắn gọn nhất để đọc các tham số truy vấn trong 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

Tôi thấy rằng đối với một HTML5Mode SPA gây ra rất nhiều vấn đề lỗi 404 và không cần thiết phải làm cho $ location.search hoạt động trong trường hợp này. Trong trường hợp của tôi, tôi muốn nắm bắt một tham số chuỗi truy vấn URL khi người dùng đến trang web của tôi, bất kể "trang" nào ban đầu họ liên kết đến, và có thể gửi chúng đến trang đó khi họ đăng nhập. Vì vậy, tôi chỉ cần nắm bắt tất cả những thứ đó trong 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'];
    }
    ...
}

sau đó sau khi đăng nhập tôi có thể nói $ state.go ($ rootScope.initialPage, $ rootScope.initialParams)


-3

Hơi muộn một chút, nhưng tôi nghĩ vấn đề của bạn là URL của bạn. Nếu thay vì

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

bạn có

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

Tôi khá chắc chắn rằng nó sẽ làm việc. Angular thực sự kén chọn về # /


Đó chỉ là khi bạn không kích hoạt chế độ HTML5. Số # / không phải lúc nào cũng có trong các góc Angular.
LocalPCGuy

Đó là nếu bạn đang xây dựng một SPA. Tất cả các url của tôi có một #. Và HTML5Mode có nghĩa là 1) 404 khi làm mới trang và 2) url trực tiếp sẽ không hoạt động. Có vẻ như một mức giá cao phải trả.
nuander
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.