AngularJS - как использовать $ routeParams для создания templateUrl?


96

В нашем приложении двухуровневая навигация. Мы хотим использовать 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-адрес в своем контроллере, используя $routeParams следующим образом:

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-файл ;-)
DominikGuzei

1
Не могли бы вы просто использовать templateвместо templateUrl?
kaiser

1
Это действительно сработает, но как насчет применения контроллера для каждого выбранного шаблона? При использовании этого метода у вас останется только один «главный» контроллер: «RouteController»
Янив Эфраим

9
если вы установите templateна функцию, вы можете передать $routeParamsв эту функцию: $routeProvider.when('/:pNav/:sNav', { template: fn($routeParams) { return $routeParams.pNav + '/' + $routeParams.sNav + '.html' } });. Однако вы не можете динамически определить контроллер таким образом :(
jacob 05

131

Эта очень полезная функция теперь доступна начиная с версии 1.1.2 AngularJS. Он считается нестабильным, но я использовал его (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

как насчет динамического контроллера на основе параметров?
Oak

Подскажите пожалуйста (пожалуйста!), Что это можно сделать с controllers...?
Коди

как в этом случае получить доступ к контроллеру из шаблона (предоставленного $ routeProvider)? Обычно, если контроллер связан директивой ng-controller = "myController", вы можете ссылаться на него myController как на myCtrl. Как мне определить myCtrl в этом случае?
FlavorScape

@FlavorScape У меня тоже была эта проблема - решение - сделать что-то вроде $ routeProvider.when ("/ foo", {controller: "FooController", controllerAs: "foo", templateUrl: "foo.html"});
Эрин Драммонд

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

});
...

Это может быть больше информации, чем нужно ...

  • По сути, вы хотите хранить $routeProvidervar вашего модуля глобально, например, routeProviderчтобы он был доступен вашим контроллерам.

  • Затем вы можете просто использовать routeProviderи создать НОВЫЙ маршрут (вы не можете 'RESET a route' / 'REpromise'; вы должны создать новый), я просто добавил косую черту (/) в конце, чтобы он был семантическим как первый.

  • Затем (внутри вашего контроллера) установите templateUrlвид, который вы хотите поразить.

  • Выньте controllerсвойство .when()объекта, чтобы не получить бесконечный цикл запроса.

  • И, наконец (все еще внутри контроллера), используйте $location.path()для перенаправления на только что созданный маршрут.

Если вас интересует, как вставить приложение Angular в приложение Express, вы можете разветвить мое репо здесь: https://github.com/cScarlson/isomorph .

И этот метод также позволяет вам сохранить двунаправленные привязки данных AngularJS на случай, если вы хотите привязать свой HTML к своей базе данных с помощью WebSockets: в противном случае без этого метода ваши привязки данных Angular будут просто выводиться {{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

Я добавил поддержку этого в свой форк angular. Это позволяет вам указать

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

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

не уверен, что это будет воспринято, так как это не в духе для angular, но для меня это полезно


Право на! Еще не пользовался, но ДЕЙСТВИТЕЛЬНО нужен. Есть ли другие предостережения, которых я должен остерегаться? Кроме того, есть какие-нибудь слова о его реализации в Angular? - Мне нравится использовать CDN.
Cody

Понятия не имею, мне так и не удалось подписать документы, так что это тупик, но вы можете взять сдачу и попытаться втянуть ее в себя (я больше не работаю в компании, с которой я работал, когда я это делал, а они не продолжить angularjs)
Джейми Пейт

Хорошо, спасибо за информацию и за ваш вклад в проблему - я вытащу это и поиграю с ним через минуту.
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 могут быть любыми в соответствии с вашими потребностями.


0

У меня была аналогичная проблема, и я использовал $stateParamsвместоrouteParam

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.