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-адресу у контролері, використовуючи $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.
пн

18
Вам фактично не потрібно створювати "однорядний html-файл" - просто використовуйте клавішу "template:" замість "templateUrl" та надайте їй рядок, що містить
однорівневий

1
Не могли ви просто використовувати templateзамість цього templateUrl?
кайзер

1
Це насправді буде працювати, але як щодо застосування контролера для кожного вибраного шаблону? Використання цього методу дозволить вам отримати лише один "головний" контролер: "RouteController"
Yaniv Efraim

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

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

як щодо динамічного контролера на основі параметрів?
Дуб

Будь ласка, будь ласка (будь ласка!) Скажіть мені, що це можливо зробити за допомогою 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/');

});
...

Це може бути більше інформації, ніж те, що було потрібно ...

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

  • Тоді ви можете просто використати routeProviderі створити НОВИЙ маршрут (ви не можете 'СКИНУТИ маршрут' / 'ПЕРЕСМОТРИТИ'; ви повинні створити новий), я просто додав скісну риску (/) в кінці, щоб вона була максимально семантичною як перший.

  • Потім (всередині контролера) встановіть templateUrlдля подання, яке потрібно натиснути.

  • Вийміть controllerвластивість .when()об’єкта, щоб не отримати нескінченний цикл запитів.

  • І нарешті (все ще знаходиться всередині Контролера), використовуйте $location.path()для переадресації на щойно створений маршрут.

Якщо вас цікавить, як застосувати програму Angular на програму Express, ви можете розкласти моє репо тут: 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

Я додав підтримку для цього у своїй вилці angular. Це дозволяє вказати

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

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

не впевнений, що це підіб'ється, оскільки це на зразок проти зерна для кутових, але мені це корисно


Прямо! Хавент це використовував ще, але ДЕЙСТВІрно це потрібно. Чи є інші застереження, на які я повинен бути уважним? Також будь-яке слово про Angular його реалізує? - Мені подобається використовувати CDN.
Коді

Не маю ідеї, я ніколи не підписував папери так, що це глухий кут, але ви можете прийняти зміну і спробувати її втягнути в себе (я більше не працюю в компанії, з якою я був, коли я це робив, і вони не переслідувати angularjs далі)
Джеймі Пейт,

Гаразд, дякую за інформацію та ваш внесок у випуск - я витягну це та пограю з ним за хвилину.
Коді

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.