Apa cara paling ringkas untuk membaca parameter kueri di AngularJS?

312

Saya ingin membaca nilai parameter kueri URL menggunakan AngularJS. Saya mengakses HTML dengan URL berikut:

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

Seperti yang diharapkan, location.searchadalah "?target=bob". Untuk mengakses nilai target , saya telah menemukan berbagai contoh yang terdaftar di web, tetapi tidak ada yang bekerja di AngularJS 1.0.0rc10. Secara khusus, berikut ini semuanya undefined:

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

Adakah yang tahu apa yang akan berhasil? (Saya menggunakan $locationsebagai parameter ke controller saya)


Memperbarui:

Saya telah memposting solusi di bawah ini, tetapi saya tidak sepenuhnya puas dengannya. Dokumentasi di Panduan Pengembang: Layanan Angular: Menggunakan $ location menyatakan yang berikut tentang $location:

Kapan saya harus menggunakan $ location?

Kapan saja aplikasi Anda perlu bereaksi terhadap perubahan pada URL saat ini atau jika Anda ingin mengubah URL saat ini di browser.

Untuk skenario saya, halaman saya akan dibuka dari halaman web eksternal dengan parameter kueri, jadi saya tidak "bereaksi terhadap perubahan dalam URL saat ini" per se. Jadi mungkin $locationbukan alat yang tepat untuk pekerjaan itu (untuk detail yang jelek, lihat jawaban saya di bawah). Karena itu saya mengubah judul pertanyaan ini dari "Bagaimana cara membaca parameter kueri di AngularJS menggunakan $ location?" to "Apa cara paling ringkas untuk membaca parameter kueri di AngularJS?". Jelas saya hanya bisa menggunakan javascript dan ekspresi reguler untuk mem-parsing location.search, tetapi pergi ke tingkat rendah untuk sesuatu yang sangat mendasar benar-benar menyinggung perasaan programmer saya.

Jadi: apakah ada cara yang lebih baik untuk digunakan $locationdaripada jawaban saya, atau adakah alternatif yang ringkas?

Ellis Whitehead
sumber
1
Tidakkah $ location.search () ['target'] berfungsi?
merampok
Ini tidak berhasil, karena tidak ada hash setelah jalan. http://127.0.0.1:8080/test.html#?target=bobakan bekerja, perhatikan #sebelum ?. $locationadalah metode perutean tingkat kedua yang tidak dapat dikirim ke server.
Daniel F
1
@DanielF @rob, Anda berdua benar. $location.search()['target']berfungsi setelah $locationProvider.html5Mode(true)dipanggil di browser modern.
krispy

Jawaban:

199

Anda dapat menyuntikkan $ routeParams (membutuhkan ngRoute ) ke controller Anda. Berikut ini contoh dari dokumen:

// 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: Anda juga bisa mendapatkan dan mengatur parameter kueri dengan layanan $ location (tersedia di ng), khususnya searchmetodenya: $ location.search () .

$ routeParams kurang berguna setelah beban awal controller; $location.search()bisa dipanggil kapan saja.

Andrew Joslin
sumber
1
Terima kasih atas saran dan tautannya! Saya membaca halaman dan juga mencoba untuk membuat sampel yang berfungsi. Namun, pendekatan itu tidak akan berhasil bagi saya, karena saya benar-benar tidak ingin menggunakan perutean dalam kasus ini. Meskipun demikian, ini adalah saran yang sangat membantu, dan saya akan membatalkannya setelah saya memiliki cukup rep stackoverflow.
Ellis Whitehead
1
Saya akan mengatakan jawaban @ pkozlowski.opensource lebih akurat dalam situasi ini
Martín Coll
2
Tidak cukup .. paramaters kueri termasuk dalam objek $ routeParams dengan parameter rute normal. dan Anda dapat membacanya / mengaturnya dengan $ location.search (). Saya akan menambahkan itu ke jawabannya.
Andrew Joslin
5
Jakub benar. Mereka adalah hal yang berbeda. Saat Anda menggunakan "pencarian" di sudut, itu menambahkan kueri ke hash (akhir URL). Spesifikasi RFC untuk URI menyatakan bahwa params kueri harus menambahkan (tidak menambahkan) hash. Dengan demikian "pencarian" adalah konstruksi yang hanya sudut akan memperkirakan dan menafsirkan. Inilah sebabnya mengapa hanya mode HTML5 yang akan bekerja untuk solusi di atas, karena Anda mendelegasikan semua permintaan ke satu halaman (di tingkat server) terlepas dari URI yang sebenarnya.
Steven Pena
2
ini hanya berfungsi jika Anda ingin menggunakan rute di angularJS!
windmaomao
189

Bagus bahwa Anda berhasil membuatnya bekerja dengan mode html5 tetapi juga memungkinkan untuk membuatnya bekerja dalam mode hashbang.

Anda cukup menggunakan:

$location.search().target

untuk mendapatkan akses ke param pencarian 'target'.

Untuk referensi, inilah jsFiddle yang berfungsi: 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>

pkozlowski.opensource
sumber
2
apakah Anda memerlukan tanda kurung di sekitar $ location.search ()?
Magne
2
@Magne: ya, Anda membutuhkan tanda kurung, $ location.search adalah metode docs.angularjs.org/api/ng/service/$location
nandin
4
Jangan lupa bahwa jika Anda tidak menggunakan HTML5Mode(true)maka hanya params setelah # / tersedia atau ditambahkan ke url dengan # / di awal.
Sebastian
21
@nandin: Tidak, Anda tidak perlu tanda kurung di sekitar $location.search() . Saya tidak yakin mengapa jawaban ini menempatkan mereka di sana.
Dan Tao
9
Saya merasa @nandin salah mengerti pertanyaan "Apakah Anda membutuhkan tanda kurung". Anda memang perlu tanda kurung setelah pencarian, tetapi tidak yang kurung di seluruh $location.search().
K. Carpenter
56

Untuk memberikan sebagian jawaban pertanyaan saya sendiri, berikut adalah contoh yang berfungsi untuk browser 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>

Kuncinya adalah menelepon $locationProvider.html5Mode(true);seperti yang dilakukan di atas. Sekarang berfungsi saat membuka http://127.0.0.1:8080/test.html?target=bob. Saya tidak senang dengan kenyataan bahwa itu tidak akan berfungsi di browser lama, tetapi saya mungkin akan menggunakan pendekatan ini.

Alternatif yang akan bekerja dengan browser lama adalah dengan html5mode(true)menelpon dan menggunakan alamat berikut dengan hash + slash sebagai gantinya:

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

Dokumentasi yang relevan ada di Panduan Pengembang: Layanan Angular: Menggunakan $ location (aneh bahwa pencarian google saya tidak menemukan ini ...).

Ellis Whitehead
sumber
Terima kasih untuk ini. Saya sudah mencabut rambut saya mencoba membaca di params permintaan. Tetap 'tidak terdefinisi' seperti yang Anda sebutkan di atas. Pengaturan mode ke HTML5 berhasil.
sthomps
Bukankah seharusnya ng-controlleratribut <body>diatur ke MyApp?
Jago
4
Sepertinya dimulai dengan Angular 1.3, untuk menggunakan html5Mode Anda juga perlu menambahkan <base href="https://stackoverflow.com/" />tag, atau menambahkan requireBase: falseparameter lain ke panggilan ke html5Mode. Detail di sini
dae721
17

Itu bisa dilakukan dengan dua cara:

  1. Menggunakan $routeParams

Solusi terbaik dan yang disarankan adalah untuk digunakan $routeParamske controller Anda. Membutuhkan ngRoutemodul untuk diinstal.

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

Ada peringatan di sini. Ini hanya akan bekerja dengan mode HTML5. Secara default, ini tidak berfungsi untuk URL yang tidak memiliki hash ( #) di dalamnyahttp://localhost/test?param1=abc&param2=def

Anda dapat membuatnya berfungsi dengan menambahkan #/URL.http://localhost/test#/?param1=abc&param2=def

$location.search() untuk mengembalikan objek seperti:

{
  param1: 'abc',
  param2: 'def'
}
Fizer Khan
sumber
5
Terima kasih atas saran Anda dengan # /
yonexbat
9

$ location.search () akan bekerja hanya dengan mode HTML5 dihidupkan dan hanya pada browser yang mendukung.

Ini akan selalu berhasil:

$ window.location.search

Illidan
sumber
6

Hanya untuk musim panas.

Jika aplikasi Anda sedang dimuat dari tautan eksternal maka sudut tidak akan mendeteksi ini sebagai perubahan URL sehingga $ loaction.search () akan memberi Anda objek kosong. Untuk mengatasi ini, Anda perlu mengatur yang berikut di konfigurasi aplikasi Anda (app.js)

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

      $locationProvider.html5Mode(true);
 }]);
lemah
sumber
1
Ya. Ini sulit ditemukan. Terima kasih atas komentarnya.
mikeborgh
2

Hanya presisi untuk jawaban Ellis Whitehead. $locationProvider.html5Mode(true);tidak akan bekerja dengan versi baru dari angularjs tanpa menentukan URL dasar untuk aplikasi dengan <base href="">tag atau pengaturan parameter requireBaseuntukfalse

Dari dokumen :

Jika Anda mengonfigurasi $ location untuk menggunakan html5Mode (history.pushState), Anda perlu menentukan URL dasar untuk aplikasi dengan tag atau mengonfigurasi $ locationProvider untuk tidak memerlukan tag dasar dengan meneruskan objek definisi dengan requireBase: false ke $ locationProvider. html5Mode ():

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

Anda juga bisa menggunakan $ location. $$ search.yourparameter

thewindev
sumber
18
Ini $$searchadalah variabel internal, penggunaannya bukan ide yang bagus.
kumarharsh
1

ini dapat membantu kamu

Apa cara paling ringkas untuk membaca parameter kueri di 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
krishna
sumber
1

Saya menemukan bahwa untuk SPA HTML5Mode menyebabkan banyak 404 masalah kesalahan, dan tidak perlu membuat $ location.search berfungsi dalam kasus ini. Dalam kasus saya, saya ingin menangkap parameter string kueri URL ketika pengguna datang ke situs saya, terlepas dari "halaman" mana yang awalnya mereka tautkan, DAN dapat mengirimkannya ke halaman tersebut setelah mereka masuk. Jadi saya hanya menangkap semua barang-barang itu di 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'];
    }
    ...
}

kemudian nanti setelah login saya bisa mengatakan $ state.go ($ rootScope.initialPage, $ rootScope.initialParams)

nuander
sumber
-3

Ini agak terlambat, tapi saya pikir masalah Anda adalah URL Anda. Jika bukan

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

kamu punya

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

Saya cukup yakin itu akan berhasil. Angular benar-benar pilih-pilih tentang # /

Octavio Kidd
sumber
Itu hanya jika Anda tidak mengaktifkan mode HTML5. # / Tidak selalu ada di url Angular.
LocalPCGuy
Itu jika Anda membangun SPA. Semua url saya memiliki #. Dan HTML5Mode berarti 1) 404 pada refresh halaman dan 2) url langsung tidak akan berfungsi. Sepertinya harga yang harus dibayar.
nuander