AngularJS - วิธีใช้ $ routeParams ในการสร้าง templateUrl?


96

แอปพลิเคชันของเรามีการนำทาง 2 ระดับ เราต้องการใช้ AngularJS $routeProviderเพื่อจัดเตรียมเทมเพลตให้กับ<ng-view />ไฟล์. ฉันกำลังคิดที่จะทำอะไรบางอย่างตามแนวนี้:

angular.module('myApp', []).
config(['$routeProvider', function($routeProvider) {
    $routeProvider.when('/:primaryNav/:secondaryNav', {
        templateUrl: 'resources/angular/templates/nav/'+<<primaryNavHere>>+'/'+<<secondaryNavHere>>+'.html'
    });
}]);

ฉันไม่รู้วิธีเติมข้อมูลส่วนต่างๆภายในไฟล์<<>>. ฉันรู้ว่า primaryNav และ secondaryNav เชื่อมโยงกับ $ routeParams แต่ฉันจะเข้าถึง $ routeParams ที่นี่เพื่อให้บริการเทมเพลตแบบไดนามิกได้อย่างไร

คำตอบ:


84

ฉันไม่พบวิธีฉีดและใช้$routeParamsบริการ (ซึ่งฉันคิดว่าน่าจะเป็นทางออกที่ดีกว่า) ฉันลองคิดว่ามันอาจได้ผล:

angular.module('myApp', []).
    config(function ($routeProvider, $routeParams) {
        $routeProvider.when('/:primaryNav/:secondaryNav', {
            templateUrl: 'resources/angular/templates/nav/'+$routeParams.primaryNav+'/'+$routeParams.secondaryNav+'.html'
        });
    });

ซึ่งทำให้เกิดข้อผิดพลาดนี้:

ผู้ให้บริการที่ไม่รู้จัก: $ routeParams จาก myApp

หากสิ่งที่เป็นไปไม่ได้คุณสามารถเปลี่ยนtemplateUrlให้ชี้ไปที่ไฟล์ HTML บางส่วนที่เพิ่งมีng-includeแล้วตั้งค่า URL ในคอนโทรลเลอร์ของคุณโดยใช้$routeParamดังนี้:

angular.module('myApp', []).
    config(function ($routeProvider) {
        $routeProvider.when('/:primaryNav/:secondaryNav', {
            templateUrl: 'resources/angular/templates/nav/urlRouter.html',
            controller: 'RouteController'
        });
    });

function RouteController($scope, $routeParams) {
        $scope.templateUrl = 'resources/angular/templates/nav/'+$routeParams.primaryNav+'/'+$routeParams.secondaryNav+'.html';
    }

ด้วยสิ่งนี้เป็นไฟล์ urlRouter.html

<div ng-include src="templateUrl"></div>

7
ปัญหาที่เกิดขึ้นว่าทำไมอดีตไม่ได้ทำงานเป็นเอกสารgroups.google.com/forum/?fromgroups=#!topic/angular/qNi5lqm-Ps8 เนื่องจากการฉีดกำหนดเป้าหมายไปยังconfig()ผู้ให้บริการเท่านั้นจึงไม่ใช่อินสแตนซ์บริการจริงเช่น$routePrams.
NRE

18
คุณไม่จำเป็นต้องสร้าง "ไฟล์ html แบบบรรทัดเดียว" เพียงแค่ใช้คีย์ "template:" แทน "templateUrl" และระบุสตริงที่มี html one-liner ;-)
DominikGuzei

1
ใช้templateแทนกันtemplateUrlไม่ได้เหรอ?
kaiser

1
สิ่งนี้จะใช้งานได้จริง แต่การใช้คอนโทรลเลอร์สำหรับแต่ละเทมเพลตที่เลือกล่ะ การใช้วิธีนี้จะทำให้คุณมีตัวควบคุม "หลัก" เพียงตัวเดียว: "RouteController"
Yaniv Efraim

9
หากคุณตั้งค่าtemplateเป็นฟังก์ชันคุณสามารถส่งผ่าน$routeParamsไปยังฟังก์ชันนั้นได้: $routeProvider.when('/:pNav/:sNav', { template: fn($routeParams) { return $routeParams.pNav + '/' + $routeParams.sNav + '.html' } });. อย่างไรก็ตามคุณไม่สามารถกำหนดคอนโทรลเลอร์แบบไดนามิกได้ด้วยวิธีนี้ :(
jacob

131

ฟีเจอร์ที่เป็นประโยชน์นี้พร้อมใช้งานแล้วโดยเริ่มจาก AngularJS เวอร์ชัน 1.1.2 ถือว่าไม่เสถียร แต่ฉันได้ใช้มัน (1.1.3) และใช้งานได้ดี

โดยทั่วไปคุณสามารถใช้ฟังก์ชันเพื่อสร้างสตริง templateUrl ฟังก์ชันจะถูกส่งผ่านพารามิเตอร์เส้นทางที่คุณสามารถใช้เพื่อสร้างและส่งคืนสตริง templateUrl

var app = angular.module('app',[]);

app.config(
    function($routeProvider) {
        $routeProvider.
            when('/', {templateUrl:'/home'}).
            when('/users/:user_id', 
                {   
                    controller:UserView, 
                    templateUrl: function(params){ return '/users/view/' + params.user_id; }
                }
            ).
            otherwise({redirectTo:'/'});
    }
);

ขอบคุณมากที่https://github.com/lrlopezสำหรับคำขอดึง

https://github.com/angular/angular.js/pull/1524


5
ตอนนี้ได้รับการสนับสนุนอย่างสมบูรณ์ใน 1.2 และอาจเป็นวิธีที่ดีที่สุด: docs.angularjs.org/api/ngRoute/provider/$routeProvider
Stu

สิ่งที่เกี่ยวกับตัวควบคุมแบบไดนามิกตามพารามิเตอร์?
โอ๊ค

ได้โปรด (ได้โปรด) บอกฉันทีว่ามันเป็นไปได้ที่จะทำกับcontrollers... ?
Cody

คุณจะเข้าถึงคอนโทรลเลอร์จากเทมเพลตในกรณีนี้ได้อย่างไร (จัดทำโดย $ routeProvider) โดยปกติถ้าคอนโทรลเลอร์ถูกผูกไว้ด้วยคำสั่ง ng-controller = "myController" คุณสามารถอ้างอิง myController เป็น myCtrl ได้ ฉันจะกำหนด myCtrl ในกรณีนี้ได้อย่างไร
FlavourScape

@FlavorScape ฉันก็มีปัญหานี้เหมือนกันวิธีแก้ปัญหาคือทำบางอย่างเช่น $ routeProvider.when ("/ foo", {controller: "FooController", controllerAs: "foo", templateUrl: "foo.html"});
Erin Drummond

18

templateUrl สามารถใช้เป็นฟังก์ชันโดยส่งคืน URL ที่สร้างขึ้น เราสามารถจัดการ url ด้วยการส่งผ่านอาร์กิวเมนต์ซึ่งใช้ routeParams

ดูตัวอย่าง

.when('/:screenName/list',{
    templateUrl: function(params){
         return params.screenName +'/listUI'
    }
})

หวังว่าจะช่วยได้


7

เอาล่ะคิดว่าเข้าใจแล้ว ...

พื้นหลังเล็ก ๆ น้อย ๆ ก่อน: เหตุผลที่ฉันต้องการสิ่งนี้คือการติด Angular ไว้ด้านบนของ Node Express และให้ Jade ประมวลผลบางส่วนให้ฉัน

นี่คือสิ่งที่ต้องทำ ... (ดื่มเบียร์และใช้เวลา 20+ ชั่วโมงก่อน !!!) ...

เมื่อคุณตั้งค่าโมดูลของคุณให้บันทึก$routeProviderทั่วโลก:

// app.js:
var routeProvider
    , app = angular.module('Isomorph', ['ngResource']).config(function($routeProvider){

        routeProvider = $routeProvider;
        $routeProvider
            .when('/', {templateUrl: '/login', controller: 'AppCtrl'})
            .when('/home', {templateUrl: '/', controller: 'AppCtrl'})
            .when('/login', {templateUrl: '/login', controller: 'AppCtrl'})
            .when('/SAMPLE', {templateUrl: '/SAMPLE', controller: 'SAMPLECtrl'})
            .when('/map', {templateUrl: '/map', controller: 'MapCtrl'})
            .when('/chat', {templateUrl: '/chat', controller: 'ChatCtrl'})
            .when('/blog', {templateUrl: '/blog', controller: 'BlogCtrl'})
            .when('/files', {templateUrl: '/files', controller: 'FilesCtrl'})
            .when('/tasks', {templateUrl: '/tasks', controller: 'TasksCtrl'})
            .when('/tasks/new', {templateUrl: '/tasks/new', controller: 'NewTaskCtrl'})
            .when('/tasks/:id', {templateUrl: '/tasks', controller: 'ViewTaskCtrl'})
            .when('/tasks/:id/edit', {templateUrl: '/tasks', controller: 'EditTaskCtrl'})
            .when('/tasks/:id/delete', {templateUrl: '/tasks', controller: 'DeleteTaskCtrl'})
        .otherwise({redirectTo: '/login'});

});

// ctrls.js
...
app.controller('EditTaskCtrl', function($scope, $routeParams, $location, $http){

    var idParam = $routeParams.id;
    routeProvider.when('/tasks/:id/edit/', {templateUrl: '/tasks/' + idParam + '/edit'});
    $location.path('/tasks/' + idParam + '/edit/');

});
...

นั่นอาจเป็นข้อมูลที่มากกว่าที่ต้องการ ...

  • โดยพื้นฐานแล้วคุณจะต้องจัดเก็บ$routeProviderตัวแปรของโมดูลไว้ทั่วโลกเช่นrouteProviderเพื่อให้ตัวควบคุมของคุณสามารถเข้าถึงได้

  • จากนั้นคุณสามารถใช้routeProviderและสร้างเส้นทางใหม่ (คุณไม่สามารถ 'รีเซ็ตเส้นทาง' / 'ประกาศใหม่' ได้คุณต้องสร้างเส้นทางใหม่) ฉันเพิ่งเพิ่มเครื่องหมายทับ (/) ในตอนท้ายเพื่อให้เป็นความหมาย เป็นครั้งแรก

  • จากนั้น (ภายในคอนโทรลเลอร์ของคุณ) ตั้งค่าtemplateUrlเป็นมุมมองที่คุณต้องการตี

  • นำcontrollerคุณสมบัติของ.when()วัตถุออกไปเกรงว่าคุณจะได้รับลูปคำขอที่ไม่มีที่สิ้นสุด

  • และสุดท้าย (ยังอยู่ในตัวควบคุม) ใช้$location.path()เพื่อเปลี่ยนเส้นทางไปยังเส้นทางที่เพิ่งสร้างขึ้น

หากคุณสนใจในวิธีการที่จะตบแอปเชิงมุมบนแอป Express คุณสามารถแยก repo ของฉันที่นี่: https://github.com/cScarlson/isomorph

และวิธีนี้ยังช่วยให้คุณเพื่อให้ AngularJS ข้อมูลแบบสองทิศทางการรวมในกรณีที่คุณต้องการที่จะผูก HTML ของคุณไปยังฐานข้อมูลของคุณโดยใช้ WebSockets {{model.param}}ฉะนั้นโดยไม่ต้องวิธีนี้เชิงมุมข้อมูลผูกของคุณเพียงแค่จะออก

หากคุณโคลนสิ่งนี้ในเวลานี้คุณจะต้องมี mongoDB บนเครื่องของคุณเพื่อเรียกใช้งาน

หวังว่านี่จะช่วยแก้ปัญหานี้ได้!

โคดี้

อย่าดื่มน้ำของคุณ


3

เราเตอร์: -

...
.when('/enquiry/:page', {
    template: '<div ng-include src="templateUrl" onload="onLoad()"></div>',
    controller: 'enquiryCtrl'
})
...

ตัวควบคุม: -

...
// template onload event
$scope.onLoad = function() {
    console.log('onLoad()');
    f_tcalInit();  // or other onload stuff
}

// initialize
$scope.templateUrl = 'ci_index.php/adminctrl/enquiry/'+$routeParams.page;
...

ฉันเชื่อว่ามันเป็นจุดอ่อนใน angularjs ที่ $ routeParams มองไม่เห็นภายในเราเตอร์ การเพิ่มประสิทธิภาพเพียงเล็กน้อยจะสร้างความแตกต่างระหว่างการนำไปใช้งาน


3

ฉันได้เพิ่มการสนับสนุนสำหรับสิ่งนี้ในส้อมเชิงมุมแล้ว ช่วยให้คุณระบุ

$routeProvider
    .when('/:some/:param/:filled/:url', {
          templateUrl:'/:some/:param/:filled/template.ng.html'
     });

https://github.com/jamie-pate/angular.js/commit/dc9be174af2f6e8d55b798209dfb9235f390b934

ไม่แน่ใจว่าสิ่งนี้จะถูกหยิบขึ้นมาเพราะมันเทียบกับเมล็ดพืชเชิงมุม แต่มันมีประโยชน์สำหรับฉัน


ถูกต้อง! ยังไม่ได้ใช้ แต่ต้องการจริงๆ มีข้อควรระวังอื่น ๆ ที่ฉันควรระวังหรือไม่? นอกจากนี้คำใด ๆ เกี่ยวกับ Angular ที่ใช้มัน? - ฉันชอบใช้ CDN
Cody

ไม่มีความคิดฉันไม่เคยได้รับเอกสารที่ลงนามดังนั้นเรื่องนี้จึงเป็นทางตัน แต่คุณสามารถรับการเปลี่ยนแปลงและพยายามดึงมันเข้ามาในตัวเอง (ฉันไม่ได้ทำงานที่ บริษัท ที่ฉันอยู่ด้วยอีกต่อไปเมื่อฉันทำสิ่งนี้และพวกเขาก็ไม่ทำ ไล่ตาม angularjs ต่อไป)
Jamie Pate

โอเคขอบคุณสำหรับข้อมูลและการมีส่วนร่วมของคุณในการแก้ไขปัญหานี้เราจะดำเนินการแก้ไขและแก้ไขปัญหาในอีกสักครู่
Cody

1
//module dependent on ngRoute  
 var app=angular.module("myApp",['ngRoute']);
    //spa-Route Config file
    app.config(function($routeProvider,$locationProvider){
          $locationProvider.hashPrefix('');
          $routeProvider
            .when('/',{template:'HOME'})
            .when('/about/:paramOne/:paramTwo',{template:'ABOUT',controller:'aboutCtrl'})
            .otherwise({template:'Not Found'});
    }
   //aboutUs controller 
    app.controller('aboutCtrl',function($routeParams){
          $scope.paramOnePrint=$routeParams.paramOne;
          $scope.paramTwoPrint=$routeParams.paramTwo;
    });

ใน index.html

<a ng-href="#/about/firstParam/secondParam">About</a>

firstParam และ secondParam สามารถเป็นอะไรก็ได้ตามความต้องการของคุณ


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.