AngularJS - Bagaimana cara menggunakan $ routeParams dalam membuat templateUrl?

96

Aplikasi kami memiliki navigasi 2 tingkat. Kami ingin menggunakan AngularJS $routeProvideruntuk menyediakan template secara dinamis ke file <ng-view />. Saya sedang berpikir untuk melakukan sesuatu seperti ini:

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

Saya hanya tidak tahu bagaimana mengisi bagian-bagian di dalam <<>>. Saya tahu primaryNav dan secondaryNav terikat ke $ routeParams, tetapi bagaimana cara mengakses $ routeParams di sini untuk menyajikan template secara dinamis?

dnc253
sumber

Jawaban:

84

Saya tidak dapat menemukan cara untuk menyuntikkan dan menggunakan $routeParamslayanan (yang saya anggap akan menjadi solusi yang lebih baik) Saya mencoba berpikir ini mungkin berhasil:

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

Yang menghasilkan kesalahan ini:

Penyedia tidak dikenal: $ routeParams dari myApp

Jika hal seperti itu tidak memungkinkan, Anda dapat mengubah Anda templateUrlmenjadi menunjuk ke file HTML parsial yang baru memiliki ng-includedan kemudian mengatur URL di pengontrol Anda menggunakan $routeParams seperti ini:

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

Dengan ini sebagai milikmu urlRouter.html

<div ng-include src="templateUrl"></div>
Gloopy
sumber
7
Masalah mengapa yang pertama tidak berfungsi didokumentasikan groups.google.com/forum/?fromgroups=#!topic/angular/qNi5lqm-Ps8 . Karena target injeksi config()hanya ke penyedia yang diteruskan, bukan instance layanan sebenarnya seperti $routePrams.
nre
18
Anda sebenarnya tidak perlu membuat "file html satu baris" - cukup gunakan kunci "template:" alih-alih "templateUrl" dan berikan string yang berisi html one-liner ;-)
DominikGuzei
1
Tidak bisakah Anda menggunakan templatesaja templateUrl?
kaiser
1
Ini benar-benar akan berfungsi, tetapi bagaimana dengan menerapkan pengontrol untuk setiap templat yang dipilih? Menggunakan metode ini akan membuat Anda hanya memiliki satu pengontrol "master": "RouteController"
Yaniv Efraim
9
jika Anda menetapkan templateke fungsi, Anda dapat melewati $routeParamske dalam fungsi bahwa: $routeProvider.when('/:pNav/:sNav', { template: fn($routeParams) { return $routeParams.pNav + '/' + $routeParams.sNav + '.html' } });. Namun, Anda tidak dapat secara dinamis menentukan pengontrol dengan cara ini :(
jacob
131

Fitur yang sangat membantu ini sekarang tersedia mulai dari versi 1.1.2 AngularJS. Ini dianggap tidak stabil tetapi saya telah menggunakannya (1.1.3) dan berfungsi dengan baik.

Pada dasarnya Anda dapat menggunakan fungsi untuk menghasilkan string templateUrl. Fungsi ini meneruskan parameter rute yang bisa Anda gunakan untuk membuat dan mengembalikan string 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:'/'});
    }
);

Terima kasih banyak kepada https://github.com/lrlopez atas permintaan tariknya.

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

jlareau
sumber
5
Ini sekarang sepenuhnya didukung di 1.2 dan mungkin itu cara terbaik: docs.angularjs.org/api/ngRoute/provider/$routeProvider
Stu
bagaimana dengan pengontrol dinamis berdasarkan params?
Oak
Tolong, tolong (tolong!) Beritahu saya bahwa ini mungkin dilakukan dengan controllers...?
Cody
bagaimana Anda mengakses pengontrol dari template dalam kasus ini (disediakan oleh $ routeProvider)? Biasanya, jika controller terikat oleh direktif ng-controller = "myController", Anda dapat mereferensikannya myController sebagai myCtrl. Bagaimana saya mendefinisikan myCtrl dalam kasus ini?
FlavorScape
@FlavorScape Saya baru saja mengalami masalah ini - solusinya adalah melakukan sesuatu seperti $ routeProvider.when ("/ foo", {controller: "FooController", controllerAs: "foo", templateUrl: "foo.html"});
Erin Drummond
18

templateUrl dapat digunakan sebagai fungsi dengan mengembalikan URL yang dihasilkan. Kita bisa memanipulasi url dengan melewati argumen yang mengambil routeParams.

Lihat contohnya.

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

Semoga bantuan ini.

Ravi K.
sumber
7

Baiklah, kupikir aku mengerti ...

Sedikit latar belakang pertama: Alasan saya membutuhkan ini adalah untuk menempelkan Angular di atas Node Express dan meminta Jade memproses parsial saya untuk saya.

Jadi, inilah yang harus dilakukan ... (minum bir dan habiskan 20+ jam untuk itu dulu !!!) ...

Saat Anda menyiapkan modul Anda, simpan $routeProvidersecara global:

// 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/');

});
...

Itu mungkin lebih banyak info daripada yang dibutuhkan ...

  • Pada dasarnya, Anda ingin menyimpan $routeProvidervar Modul Anda secara global, misalnya routeProvideragar dapat diakses oleh Pengontrol Anda.

  • Kemudian Anda bisa menggunakan routeProviderdan membuat rute BARU (Anda tidak bisa 'RESET rute' / 'Janji ulang'; Anda harus membuat yang baru), saya hanya menambahkan garis miring (/) di akhir sehingga itu semantik sebagai yang pertama.

  • Kemudian (di dalam Controller Anda), atur templateUrlke tampilan yang ingin Anda tekan.

  • Keluarkan controllerproperti .when()objek, jangan sampai Anda mendapatkan loop permintaan tak terbatas.

  • Dan terakhir (masih di dalam Controller), gunakan $location.path()untuk mengarahkan ke rute yang baru saja dibuat.

Jika Anda tertarik dengan cara menampar aplikasi Angular ke aplikasi Express, Anda dapat membagi repo saya di sini: https://github.com/cScarlson/isomorph .

Dan metode ini juga memungkinkan Anda untuk menyimpan AngularJS Bidirectional Data-Bindings jika Anda ingin mengikat HTML ke database Anda menggunakan WebSockets: jika tidak tanpa metode ini, data-binding Angular Anda hanya akan ditampilkan {{model.param}}.

Jika Anda mengkloning ini saat ini, Anda memerlukan mongoDB di komputer Anda untuk menjalankannya.

Semoga ini menyelesaikan masalah ini!

Cody

Jangan minum air mandi Anda.

Cody
sumber
3

Router: -

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

Pengontrol: -

...
// 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;
...

Saya percaya itu adalah kelemahan di angularjs bahwa $ routeParams TIDAK terlihat di dalam router. Peningkatan kecil akan membuat perbedaan dunia selama implementasi.

Ron deBoer
sumber
3

Saya telah menambahkan dukungan untuk ini di garpu sudut saya. Ini memungkinkan Anda untuk menentukan

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

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

tidak yakin ini akan diterima karena agak bertentangan dengan grain untuk sudut, tapi ini berguna bagi saya

Jamie Pate
sumber
Benar! Belum pernah menggunakannya tapi BENAR-BENAR membutuhkannya. Apakah ada peringatan lain yang harus saya waspadai? Juga, ada kata di Angular yang mengimplementasikannya? - Saya suka menggunakan CDN.
Cody
Tidak tahu, saya tidak pernah mendapatkan dokumen yang ditandatangani jadi ini jalan buntu, tetapi Anda dapat mengambil perubahan dan mencoba menariknya sendiri (Saya tidak lagi bekerja di perusahaan tempat saya dulu ketika saya melakukan ini, dan mereka tidak mengejar angularjs lebih jauh)
Jamie Pate
Oke, terima kasih atas infonya dan kontribusi Anda terhadap masalah ini - Saya akan membahasnya dan mengotak-atiknya sebentar lagi.
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;
    });

di index.html

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

firstParam dan secondParam bisa apa saja sesuai kebutuhan.

Aniket Jha
sumber
0

Saya mengalami masalah serupa dan saya $stateParamsmalah menggunakanrouteParam

mcneela86
sumber