วิธีที่สั้นที่สุดในการอ่านพารามิเตอร์ข้อความค้นหาใน AngularJS คืออะไร


312

ฉันต้องการอ่านค่าของพารามิเตอร์การค้นหา 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เป็นพารามิเตอร์ในการควบคุมของฉัน)


ปรับปรุง:

ฉันโพสต์โซลูชันด้านล่าง แต่ฉันไม่พอใจกับมันทั้งหมด เอกสารที่คู่มือนักพัฒนาซอฟต์แวร์: บริการเชิงมุม: การใช้ $ locationระบุสิ่งต่อไปนี้$location:

ฉันควรใช้ตำแหน่ง $ เมื่อใด

เมื่อใดก็ตามที่แอปพลิเคชันของคุณต้องการตอบสนองต่อการเปลี่ยนแปลงใน URL ปัจจุบันหรือหากคุณต้องการเปลี่ยน URL ปัจจุบันในเบราว์เซอร์

สำหรับสถานการณ์ของฉันหน้าของฉันจะเปิดจากหน้าเว็บภายนอกพร้อมพารามิเตอร์การสืบค้นดังนั้นฉันจึงไม่ "ตอบสนองต่อการเปลี่ยนแปลงใน URL ปัจจุบัน" ต่อหนึ่งรายการ ดังนั้นอาจ$locationไม่ใช่เครื่องมือที่เหมาะสมสำหรับงาน (สำหรับรายละเอียดที่น่าเกลียดดูคำตอบของฉันด้านล่าง) ฉันได้เปลี่ยนชื่อของคำถามนี้จาก "วิธีอ่านพารามิเตอร์ข้อความค้นหาใน AngularJS โดยใช้ $ location" ถึง "วิธีรัดกุมที่สุดในการอ่านพารามิเตอร์ข้อความค้นหาใน AngularJS คืออะไร" เห็นได้ชัดว่าฉันสามารถใช้จาวาสคริปต์และการแสดงออกปกติเพื่อแยกวิเคราะห์location.searchแต่การที่ระดับต่ำสำหรับบางสิ่งบางอย่างเพื่อให้พื้นฐานจริงๆแล้วมันขัดกับความรู้สึกของโปรแกรมเมอร์

ดังนั้น: มีวิธีที่ดีกว่าที่จะใช้$locationกว่าที่ฉันทำในคำตอบของฉันหรือมีทางเลือกสั้นกระชับ?


1
$ location.search () ['target'] ไม่ควรทำงานหรือ
ปล้น

สิ่งนี้ใช้ไม่ได้เพราะไม่มีแฮชหลังพา ธ http://127.0.0.1:8080/test.html#?target=bobการทำงานก็จะแจ้งให้ทราบก่อน# เป็นวิธีการกำหนดเส้นทางระดับที่สองซึ่งไม่ได้ถูกส่งไปยังเซิร์ฟเวอร์ ?$location
Daniel F

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'}

แก้ไข: คุณยังสามารถรับและพารามิเตอร์แบบสอบถามชุดกับ$ สถานบริการ (ในที่มีอยู่ng) โดยเฉพาะอย่างยิ่งของsearchวิธีการ: $ location.search ()

$ routeParams มีประโยชน์น้อยกว่าหลังจากโหลดเริ่มต้นของคอนโทรลเลอร์ $location.search()สามารถเรียกได้ตลอดเวลา


1
ขอบคุณสำหรับคำแนะนำและลิงค์! ฉันอ่านหน้าและพยายามตั้งค่าตัวอย่างการทำงาน อย่างไรก็ตามวิธีการนี้ไม่ได้ผลสำหรับฉันเพราะฉันไม่ต้องการใช้การกำหนดเส้นทางในกรณีนี้ นี่เป็นคำแนะนำที่เป็นประโยชน์อย่างไรก็ตามและฉันจะถอนมันเมื่อฉันมีตัวแทน stackoverflow มากพอ
Ellis Whitehead

1
ผมจะบอกว่า @ pkozlowski.opensource 's คำตอบที่ถูกต้องมากขึ้นในสถานการณ์เช่นนี้
Martín Coll

2
ไม่มากนักพารามิเตอร์การสืบค้นจะรวมอยู่ในวัตถุ $ routeParams พร้อมพารามิเตอร์เส้นทางปกติ และคุณสามารถอ่าน / ตั้งค่าด้วย $ location.search () ฉันจะเพิ่มเข้าไปในคำตอบ
Andrew Joslin

5
จาคุบพูดถูก พวกมันต่างกัน เมื่อคุณใช้ "ค้นหา" ในเชิงมุมมันจะผนวกแบบสอบถามไปยังแฮช (สิ้นสุด URL) ข้อมูลจำเพาะ RFC สำหรับ URI ระบุว่าพารามิเตอร์การสืบค้นควรเสริม (ไม่ผนวก) แฮช ดังนั้น "การค้นหา" จึงเป็นโครงสร้างที่มีเพียงเชิงมุมเท่านั้นที่จะคาดการณ์และตีความ นี่คือเหตุผลที่โหมด HTML5 เท่านั้นที่ใช้งานได้สำหรับวิธีการแก้ปัญหาด้านบนเนื่องจากคุณมอบหมายการร้องขอทั้งหมดให้หนึ่งหน้า (ที่ระดับเซิร์ฟเวอร์) โดยไม่คำนึงถึง URI จริง
Steven Pena

2
ใช้งานได้เฉพาะในกรณีที่คุณต้องการใช้เส้นทางใน angularJS!
windmaomao

189

ดีที่คุณจัดการเพื่อให้มันทำงานกับโหมด html5 แต่ก็เป็นไปได้ที่จะทำให้มันทำงานในโหมด hashbang

คุณสามารถใช้:

$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 ()
Magne

2
@Magne: ใช่คุณต้องการวงเล็บ $ location.search เป็นวิธีdocs.angularjs.org/api/ng/service/$location
nandin

4
อย่าลืมว่าถ้าคุณไม่ได้ใช้งานHTML5Mode(true)จะมีเพียง params หลังจาก # / พร้อมใช้งานหรือเพิ่มใน url ด้วย # / ที่จุดเริ่มต้น
เซบาสเตียน

21
@nandin: ไม่มีคุณไม่ต้องวงเล็บรอบ $location.search()ฉันไม่แน่ใจว่าทำไมคำตอบนี้ทำให้พวกเขามี
Dan Tao

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)สายและใช้ที่อยู่ต่อไปนี้ด้วย hash + slash แทน

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

เอกสารที่เกี่ยวข้องอยู่ในคู่มือนักพัฒนาซอฟต์แวร์: บริการเชิงมุม: การใช้ $ location (แปลกที่การค้นหา google ของฉันไม่พบสิ่งนี้ ... )


ขอบคุณสำหรับสิ่งนี้. ฉันดึงผมออกมาพยายามอ่านใน params แบบสอบถาม เก็บ 'ไม่ได้กำหนด' ตามที่คุณกล่าวไว้ข้างต้น โหมดการตั้งค่าเป็น html5 ทำงาน
sthomps

ไม่ควรตั้งค่าng-controllerแอตทริบิวต์ของ<body>เป็นMyAppใช่หรือไม่
จาโก

4
ดูเหมือนว่าเริ่มต้นด้วย Angular 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

คุณสามารถทำให้มันทำงานได้โดยการเพิ่ม#/ใน URLhttp://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 () จะให้วัตถุว่างเปล่าแก่คุณ ในการแก้ปัญหานี้คุณต้องตั้งค่าต่อไปนี้ในแอป config (app.js)

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

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

1
อ๋อ นี่เป็นความเจ็บปวดที่จะพบ ขอบคุณสำหรับความคิดเห็น
ไมค์บอร์ก

2

แค่คำตอบที่เที่ยงตรงของ Ellis Whitehead $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

คุณสามารถใช้ตำแหน่ง $ ได้ด้วย $$ search.yourparameter


18
$$searchเป็นตัวแปรภายในการใช้งานที่ไม่ได้เป็นเช่นความคิดที่ดี
kumarharsh

1

สิ่งนี้อาจช่วยคุณได้

อะไรคือวิธีที่กระชับที่สุดในการอ่านพารามิเตอร์ข้อความค้นหาใน 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

มันคือถ้าคุณกำลังสร้างสปา URL ทั้งหมดของฉันมี # และ HTML5Mode หมายถึง 1) 404 ในการรีเฟรชหน้าเว็บและ 2) URL โดยตรงไม่ทำงาน ดูเหมือนว่าราคาสูงจ่าย
nuander
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.