Qual è il modo più conciso per leggere i parametri di query in AngularJS?


312

Mi piacerebbe leggere i valori dei parametri di query URL usando AngularJS. Accedo all'HTML con il seguente URL:

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

Come previsto, lo location.searchè "?target=bob". Per accedere al valore di target , ho trovato vari esempi elencati sul web, ma nessuno di questi funziona in AngularJS 1.0.0rc10. In particolare, sono tutti i seguenti undefined:

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

Qualcuno sa cosa funzionerà? (Sto usando $locationcome parametro per il mio controller)


Aggiornare:

Di seguito ho pubblicato una soluzione, ma non ne sono completamente soddisfatto. La documentazione nella Guida per gli sviluppatori: Servizi angolari: l'utilizzo di $ location indica quanto segue $location:

Quando dovrei usare $ location?

Ogni volta che l'applicazione deve reagire a una modifica dell'URL corrente o se si desidera modificare l'URL corrente nel browser.

Per il mio scenario, la mia pagina verrà aperta da una pagina Web esterna con un parametro di query, quindi non sto "reagendo a una modifica dell'URL corrente" di per sé. Quindi forse $locationnon è lo strumento giusto per il lavoro (per i dettagli brutti, vedi la mia risposta di seguito). Ho quindi modificato il titolo di questa domanda da "Come leggere i parametri di query in AngularJS usando $ location?" a "Qual è il modo più conciso per leggere i parametri di query in AngularJS?". Ovviamente potrei semplicemente usare javascript ed espressione regolare per analizzare location.search, ma andare a quel livello basso per qualcosa di così semplice offende davvero la mia sensibilità del programmatore.

Quindi: c'è un modo migliore di usare di $locationquello che faccio nella mia risposta, o c'è un alternato conciso?


1
$ Location.search () ['target'] non dovrebbe funzionare?
derubare il

Questo non funziona, perché non c'è hash dopo il percorso. http://127.0.0.1:8080/test.html#?target=bobavrebbe funzionato, notare il #prima il ?. $locationè un metodo di routing di secondo livello che non viene inviato al server.
Daniel F,

1
@DanielF @rob, hai ragione entrambi. $location.search()['target']funziona dopo che $locationProvider.html5Mode(true)è stato chiamato in un browser moderno.
Krispy,

Risposte:


199

Puoi iniettare $ routeParams (richiede ngRoute ) nel tuo controller. Ecco un esempio dai documenti:

// 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: Puoi anche ottenere e impostare parametri di query con il servizio $ location (disponibile in ng), in particolare il suo searchmetodo: $ location.search () .

$ routeParams sono meno utili dopo il caricamento iniziale del controller; $location.search()può essere chiamato in qualsiasi momento.


1
Grazie per il suggerimento e il link! Ho letto la pagina e ho anche tentato di creare un campione funzionante. Tuttavia, l'approccio non funzionerà per me, perché in questo caso non voglio davvero usare il routing. Questo è stato comunque un suggerimento utile e lo voterò una volta che avrò abbastanza rappresentante dello stackoverflow.
Ellis Whitehead,

1
Direi che la risposta di @ pkozlowski.opensource è più accurata in questa situazione
Martín Coll

2
Non del tutto ... i parametri di query sono inclusi nell'oggetto $ routeParams con i normali parametri di route. e puoi leggerli / impostarli con $ location.search (). Lo aggiungerò alla risposta.
Andrew Joslin,

5
Jakub ha ragione. Sono cose diverse. Quando si utilizza la "ricerca" in angolare, si aggiunge la query all'hash (fine dell'URL). Le specifiche RFC per l'URI indicano che i parametri della query devono anteporre (non aggiungere) l'hash. Quindi la "ricerca" è un costrutto che solo angolare estrapolerà e interpreterà. Questo è il motivo per cui solo la modalità HTML5 funzionerà per la soluzione sopra, perché stai delegando tutte le richieste a una pagina (a livello di server) indipendentemente dall'URI effettivo.
Steven Pena,

2
funziona solo se vuoi usare route in angularJS!
windmaomao,

189

Bene che sei riuscito a farlo funzionare con la modalità html5 ma è anche possibile farlo funzionare in modalità hashbang.

Puoi semplicemente usare:

$location.search().target

per accedere al parametro di ricerca "target".

Per il riferimento, ecco il jsFiddle funzionante: 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
hai bisogno delle parentesi intorno a $ location.search ()?
Magne,

2
@Magne: sì, hai bisogno di parentesi, $ location.search è un metodo docs.angularjs.org/api/ng/service/$location
nandin

4
Non dimenticare che se non lo usi, HTML5Mode(true)solo i parametri dopo # / sono disponibili o vengono aggiunti all'URL con # / all'inizio.
Sebastian,

21
@nandin: No, non hai bisogno delle parentesi in giro $location.search() . Non sono sicuro del perché questa risposta li metta lì.
Dan Tao,

9
Sento che @nandin ha frainteso la domanda "Hai bisogno di parentesi". È fare bisogno di parentesi dopo la ricerca, ma non quelli di tutto l'interezza della $location.search().
K. Carpenter il

56

Per dare una risposta parziale alla mia domanda, ecco un esempio funzionante per i 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>

La chiave era chiamare $locationProvider.html5Mode(true);come fatto sopra. Ora funziona all'apertura http://127.0.0.1:8080/test.html?target=bob. Non sono contento del fatto che non funzionerà nei browser più vecchi, ma potrei comunque utilizzare questo approccio.

Un'alternativa che funzionerebbe con i browser più vecchi sarebbe quella di eliminare la html5mode(true)chiamata e utilizzare invece il seguente indirizzo con hash + barra:

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

La documentazione pertinente è nella Guida per gli sviluppatori: Servizi angolari: utilizzo di $ location (strano che la mia ricerca su Google non abbia trovato questo ...).


Grazie per questo. Mi sono strappato i capelli cercando di leggere i parametri della query. Ho continuato a diventare "indefinito" come hai detto sopra. L'impostazione della modalità su HTML5 ha funzionato.
Sthomps,

L' ng-controllerattributo di non dovrebbe <body>essere impostato su MyApp?
Jago,

4
Sembra che inizi con Angular 1.3, per usare html5Mode devi anche aggiungere un <base href="https://stackoverflow.com/" />tag o aggiungere requireBase: falsecome altro parametro alla chiamata a html5Mode. Dettagli qui
dae721,

17

Può essere fatto in due modi:

  1. utilizzando $routeParams

La soluzione migliore e consigliata è utilizzare $routeParamsnel controller. Richiede l' ngRouteinstallazione del modulo.

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

C'è un avvertimento qui. Funzionerà solo con la modalità HTML5. Per impostazione predefinita, non funziona per l'URL che non contiene hash ( #)http://localhost/test?param1=abc&param2=def

Puoi farlo funzionare aggiungendo #/l'URL.http://localhost/test#/?param1=abc&param2=def

$location.search() per restituire un oggetto come:

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

5
Grazie per il tuo consiglio con # /
yonexbat il

9

$ location.search () funzionerà solo con la modalità HTML5 attivata e solo sul browser di supporto.

Questo funzionerà sempre:

$ window.location.search


6

Giusto per l'estate.

Se l'app viene caricata da collegamenti esterni, Angular non lo rileverà come una modifica dell'URL, quindi $ loaction.search () ti darebbe un oggetto vuoto. Per risolvere questo problema, devi impostare quanto segue nella configurazione dell'app (app.js)

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

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

1
Sì. È stato un dolore da trovare. Grazie per il commento.
mikeborgh,

2

Solo una precisione alla risposta di Ellis Whitehead. $locationProvider.html5Mode(true);non funzionerà con la nuova versione di angularjs senza specificare l'URL di base per l'applicazione con un <base href="">tag o impostare il parametro requireBasesufalse

Dal documento :

Se si configura $ location per utilizzare html5Mode (history.pushState), è necessario specificare l'URL di base per l'applicazione con un tag o configurare $ locationProvider per non richiedere un tag di base passando un oggetto di definizione con requireBase: false a $ locationProvider. html5Mode ():

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

1

puoi anche usare $ location. $$ search.yourparameter


18
La $$searchè una variabile interna, il cui uso non è tale una buona idea.
Kumarharsh,

1

questo può aiutarti

Qual è il modo più conciso per leggere i parametri di query in 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

Ho scoperto che per una SPA HTML5Mode provoca molti 404 problemi di errore, e in questo caso non è necessario far funzionare $ location.search. Nel mio caso, voglio acquisire un parametro della stringa di query URL quando un utente accede al mio sito, indipendentemente dalla "pagina" a cui inizialmente si collegano, ed essere in grado di inviarli a quella pagina una volta effettuato l'accesso. quella roba in 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'];
    }
    ...
}

poi dopo il login posso dire $ state.go ($ rootScope.initialPage, $ rootScope.initialParams)


-3

È un po 'tardi, ma penso che il tuo problema sia stato il tuo URL. Se invece di

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

avete avuto

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

Sono abbastanza sicuro che avrebbe funzionato. Angular è davvero esigente riguardo al suo # /


Questo è solo se non si abilita la modalità HTML5. Il # / non è sempre presente negli URL angolari.
LocalPCGuy

È se stai costruendo una SPA. Tutti i miei URL hanno un #. E HTML5Mode significa 1) 404 sull'aggiornamento della pagina e 2) gli URL diretti non funzioneranno. Sembra un prezzo elevato da pagare.
Nuander,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.