AngularJS - Wie verwende ich $ routeParams beim Generieren der templateUrl?

96

Unsere Anwendung verfügt über eine zweistufige Navigation. Wir möchten AngularJS verwenden $routeProvider, um Vorlagen dynamisch für eine bereitzustellen <ng-view />. Ich dachte daran, etwas in dieser Richtung zu tun:

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

Ich weiß nur nicht, wie ich die Teile innerhalb der füllen soll <<>>. Ich weiß, dass das PrimaryNav und das SecondaryNav an die $ routeParams gebunden werden, aber wie greife ich hier auf $ routeParams zu, um die Vorlage dynamisch bereitzustellen?

dnc253
quelle

Antworten:

84

Ich konnte keinen Weg finden, den $routeParamsService zu injizieren und zu nutzen (was meiner Meinung nach eine bessere Lösung wäre). Ich habe versucht, diesen Gedanken zu nutzen:

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

Was diesen Fehler ergab:

Unbekannter Anbieter: $ routeParams von myApp

Wenn so etwas nicht möglich ist, können Sie Ihren templateUrlVerweis auf eine teilweise HTML-Datei ändern , die gerade vorhanden ist, ng-includeund dann die URL in Ihrem Controller wie folgt festlegen $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';
    }

Mit diesem als Ihrem urlRouter.html

<div ng-include src="templateUrl"></div>
Gloopy
quelle
7
Das Problem, warum Ersteres nicht funktioniert, ist in groups.google.com/forum/?fromgroups=#!topic/angular/qNi5lqm-Ps8 dokumentiert . Da Injektionsziele config()nur an Anbieter übergeben werden, werden keine tatsächlichen Dienstinstanzen wie z $routePrams.
nre
18
Sie müssen die "einzeilige HTML-Datei" eigentlich nicht erstellen - verwenden Sie einfach den Schlüssel "template:" anstelle von "templateUrl" und geben Sie eine Zeichenfolge ein, die den HTML-
Einzeiler enthält ;-)
1
Könnten Sie nicht einfach templatestatt verwenden templateUrl?
Kaiser
1
Dies wird tatsächlich funktionieren, aber was ist mit dem Anwenden eines Controllers für jede ausgewählte Vorlage? Wenn Sie diese Methode verwenden, haben Sie nur einen "Master" -Controller: "RouteController"
Yaniv Efraim
9
Wenn Sie templateeine Funktion einstellen , können Sie $routeParamsdiese Funktion übergeben : $routeProvider.when('/:pNav/:sNav', { template: fn($routeParams) { return $routeParams.pNav + '/' + $routeParams.sNav + '.html' } });. Sie können einen Controller jedoch nicht dynamisch auf diese Weise definieren :(
Jacob
131

Diese sehr hilfreiche Funktion ist ab Version 1.1.2 von AngularJS verfügbar. Es wird als instabil angesehen, aber ich habe es verwendet (1.1.3) und es funktioniert gut.

Grundsätzlich können Sie eine Funktion verwenden, um eine templateUrl-Zeichenfolge zu generieren. Der Funktion werden die Routenparameter übergeben, mit denen Sie die templateUrl-Zeichenfolge erstellen und zurückgeben können.

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

Vielen Dank an https://github.com/lrlopez für die Pull-Anfrage.

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

jlareau
quelle
5
Dies wird jetzt in 1.2 vollständig unterstützt und ist wahrscheinlich der beste Weg: docs.angularjs.org/api/ngRoute/provider/$routeProvider
Stu
Was ist mit einem dynamischen Controller, der auf den Parametern basiert?
Eiche
Bitte, bitte (bitte!) Sag mir, dass dies möglich ist mit controllers...?
Cody
Wie greifen Sie in diesem Fall über die Vorlage (bereitgestellt von $ routeProvider) auf den Controller zu? Wenn der Controller an die Direktive ng-controller = "myController" gebunden ist, können Sie ihn normalerweise als myCtrl auf myController verweisen. Wie definiere ich in diesem Fall myCtrl?
FlavorScape
@FlavorScape Ich hatte gerade auch dieses Problem - die Lösung besteht darin, etwas wie $ routeProvider.when zu tun ("/ foo", {controller: "FooController", controllerAs: "foo", templateUrl: "foo.html"});
Erin Drummond
18

templateUrl kann als Funktion zur Rückgabe der generierten URL verwendet werden. Wir können die URL mit einem übergebenen Argument manipulieren, das routeParams benötigt.

Siehe das Beispiel.

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

Ich hoffe das hilft.

Ravi K.
quelle
7

Okay, denke ich habe es verstanden ...

Wenig Hintergrund zuerst: Der Grund, warum ich das brauchte, war, Angular auf Node Express zu kleben und Jade meine Partials für mich verarbeiten zu lassen.

Also hier ist was du tun musst ... (trinke Bier und verbringe zuerst mehr als 20 Stunden damit !!!) ...

Speichern Sie beim Einrichten Ihres Moduls das $routeProviderglobal:

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

});
...

Das kann mehr Info sein als nötig ...

  • Grundsätzlich möchten Sie die Variablen Ihres Moduls $routeProviderglobal speichern , z. B. routeProviderdamit Ihre Controller darauf zugreifen können.

  • Dann können Sie einfach routeProvidereine NEUE Route verwenden und erstellen (Sie können eine Route nicht 'zurücksetzen' / 'Versprechen'; Sie müssen eine neue Route erstellen). Ich habe am Ende nur einen Schrägstrich (/) hinzugefügt, damit sie so semantisch ist Als der erste.

  • Stellen Sie dann (in Ihrem Controller) templateUrldie Ansicht ein, die Sie treffen möchten.

  • Nehmen Sie die controllerEigenschaft des .when()Objekts heraus, damit Sie keine unendliche Anforderungsschleife erhalten.

  • Und schließlich (noch im Controller) verwenden Sie $location.path(), um zu der gerade erstellten Route umzuleiten.

Wenn Sie daran interessiert sind, eine Angular-App auf eine Express-App zu übertragen, können Sie mein Repo hier aufteilen: https://github.com/cScarlson/isomorph .

Mit dieser Methode können Sie auch die bidirektionalen AngularJS-Datenbindungen beibehalten, falls Sie Ihren HTML-Code mit WebSockets an Ihre Datenbank binden möchten. Andernfalls werden Ihre Angular-Datenbindungen ohne diese Methode nur ausgegeben {{model.param}} .

Wenn Sie dies zu diesem Zeitpunkt klonen, benötigen Sie mongoDB auf Ihrem Computer, um es auszuführen.

Hoffe das löst dieses Problem!

Cody

Trink dein Badewasser nicht.

Cody
quelle
3

Router: -

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

Regler:-

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

Ich glaube, es ist eine Schwäche in anglejs, dass $ routeParams NICHT im Router sichtbar ist. Eine winzige Verbesserung würde während der Implementierung einen großen Unterschied machen.

Ron deBoer
quelle
3

Ich habe dies in meiner Winkelgabel unterstützt. Hier können Sie angeben

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

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

Ich bin mir nicht sicher, ob dies aufgenommen wird, da es für den Winkel irgendwie gegen den Strich ist, aber es ist nützlich für mich

Jamie Pate
quelle
Direkt am! Havent hat es noch benutzt, aber ich brauche es WIRKLICH. Gibt es noch andere Einschränkungen, auf die ich achten sollte? Auch ein Wort zur Implementierung von Angular? - Ich benutze gerne das CDN.
Cody
Keine Ahnung, ich habe die Unterlagen nie unterschrieben bekommen, also ist dies eine Sackgasse, aber Sie könnten das Wechselgeld nehmen und versuchen, es in sich aufzunehmen (ich arbeite nicht mehr in der Firma, mit der ich zusammen war, als ich das tat, und sie taten es nicht Angularjs weiter verfolgen)
Jamie Pate
Ok, danke für die Info und Ihren Beitrag zum Thema - ich werde das in einer Minute herausziehen und damit herumspielen.
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;
    });

in index.html

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

firstParam und secondParam können alles sein, was Ihren Bedürfnissen entspricht.

Aniket Jha
quelle
0

Ich hatte ein ähnliches Problem und benutzte $stateParamsstattdessenrouteParam

mcneela86
quelle