AngularJS - Come utilizzare $ routeParams nella generazione di templateUrl?


96

La nostra applicazione ha una navigazione a 2 livelli. Vogliamo utilizzare AngularJS $routeProviderper fornire dinamicamente modelli a un file <ng-view />. Stavo pensando di fare qualcosa sulla falsariga di questo:

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

Non so come popolare le parti all'interno del file <<>>. So che il primaryNav e il secondaryNav vengono associati a $ routeParams, ma come posso accedere a $ routeParams qui per servire dinamicamente il modello?

Risposte:


84

Non sono riuscito a trovare un modo per iniettare e utilizzare il $routeParamsservizio (che presumo sarebbe una soluzione migliore) Ho provato questo pensando che potrebbe funzionare:

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

Che ha prodotto questo errore:

Provider sconosciuto: $ routeParams da myApp

Se qualcosa del genere non è possibile, puoi cambiare il tuo templateUrlin modo che punti a un file HTML parziale che ha ng-includee quindi impostare l'URL nel tuo controller usando $routeParams come questo:

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

Con questo come tuo urlRouter.html

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

7
Il problema per cui il primo non funziona è documentato groups.google.com/forum/?fromgroups=#!topic/angular/qNi5lqm-Ps8 . Poiché config()vengono passati i target di injection solo ai provider, non le istanze di servizio effettive come $routePrams.
nre

18
In realtà non è necessario creare il "file html di una riga" - basta utilizzare il tasto "template:" invece di "templateUrl" e fornirgli una stringa contenente la riga di testo html ;-)
DominikGuzei

1
Non potresti semplicemente usare al templateposto di templateUrl?
Kaiser

1
Funzionerà effettivamente, ma per quanto riguarda l'applicazione di un controller per ogni modello selezionato? L'utilizzo di questo metodo ti lascerà con un solo controller "master": "RouteController"
Yaniv Efraim

9
se si imposta templatea una funzione, è possibile passare $routeParamsin quella funzione: $routeProvider.when('/:pNav/:sNav', { template: fn($routeParams) { return $routeParams.pNav + '/' + $routeParams.sNav + '.html' } });. Tuttavia, non è possibile definire dinamicamente un controller in questo modo :(
jacob

131

Questa funzionalità molto utile è ora disponibile a partire dalla versione 1.1.2 di AngularJS. È considerato instabile ma l'ho usato (1.1.3) e funziona bene.

Fondamentalmente puoi usare una funzione per generare una stringa templateUrl. Alla funzione vengono passati i parametri di route che è possibile utilizzare per creare e restituire la stringa 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:'/'});
    }
);

Mille grazie a https://github.com/lrlopez per la richiesta pull.

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


5
Questo è ora completamente supportato nella 1.2 e probabilmente è il modo migliore: docs.angularjs.org/api/ngRoute/provider/$routeProvider
Stu

che dire di un controller dinamico basato sui parametri?
Quercia

Per favore, per favore (per favore!) Dimmi che questo è possibile fare con controllers...?
Cody

come si accede al controller dal template in questo caso (fornito da $ routeProvider)? Normalmente, se il controller è vincolato dalla direttiva ng-controller = "myController", puoi fare riferimento a myController come myCtrl. Come definisco myCtrl in questo caso?
FlavorScape

@FlavorScape Anch'io ho appena avuto questo problema - la soluzione è fare qualcosa come $ routeProvider.when ("/ foo", {controller: "FooController", controllerAs: "foo", templateUrl: "foo.html"});
Erin Drummond

18

templateUrl può essere utilizzato come funzione con la restituzione dell'URL generato. Possiamo manipolare l'URL passando l'argomento che accetta routeParams.

Guarda l'esempio.

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

Spero che questo aiuto.


7

Va bene, penso di aver capito ...

Prima un po 'di background: il motivo per cui avevo bisogno di questo era attaccare Angular su Node Express e fare in modo che Jade elaborasse i miei parziali per me.

Quindi ecco cosa devi fare ... (bevi birra e trascorri più di 20 ore prima !!!) ...

Quando imposti il ​​tuo modulo, salva $routeProviderglobalmente:

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

});
...

Potrebbe trattarsi di più informazioni di quelle necessarie ...

  • Fondamentalmente, vorrai memorizzare $routeProviderglobalmente la variabile del tuo modulo , ad esempio in routeProvidermodo che possa essere accessibile dai tuoi controller.

  • Quindi puoi semplicemente usare routeProvidere creare una NUOVA rotta (non puoi 'RESETTARE una rotta' / 'REpromettere'; devi crearne una nuova), ho appena aggiunto una barra (/) alla fine in modo che sia semantica come il primo.

  • Quindi (all'interno del controller), imposta templateUrlla visualizzazione che desideri colpire.

  • Elimina la controllerproprietà .when()dell'oggetto, per evitare di ottenere un ciclo di richieste infinito.

  • E infine (sempre all'interno del Controller), utilizzare $location.path()per reindirizzare al percorso appena creato.

Se sei interessato a come inserire un'app Angular su un'app Express, puoi eseguire il fork del mio repository qui: https://github.com/cScarlson/isomorph .

E questo metodo ti consente anche di mantenere le associazioni di dati bidirezionali AngularJS nel caso in cui desideri associare il tuo HTML al tuo database utilizzando WebSocket: altrimenti senza questo metodo, le tue associazioni di dati angolari verranno semplicemente emesse {{model.param}}.

Se lo cloni in questo momento, avrai bisogno di mongoDB sulla tua macchina per eseguirlo.

Spero che questo risolva questo problema!

Cody

Non bere l'acqua del bagno.


3

Router: -

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

Controllore: -

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

Credo che sia una debolezza in angularjs che $ routeParams NON è visibile all'interno del router. Un piccolo miglioramento farebbe la differenza durante l'implementazione.


3

Ho aggiunto il supporto per questo nel mio fork di angular. Ti permette di specificare

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

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

non sono sicuro che verrà raccolto perché è un po 'controcorrente per angolare, ma mi è utile


Proprio su! Non l'ho ancora usato ma ne ho davvero bisogno. Ci sono altri avvertimenti a cui dovrei prestare attenzione? Inoltre, qualche parola su Angular che lo implementa? - Mi piace usare il CDN.
Cody

Non ne ho idea, non ho mai fatto firmare i documenti, quindi questo è un vicolo cieco, ma potresti prendere il resto e provare a farlo da solo (non lavoro più nell'azienda con cui ero quando l'ho fatto, e loro non l'hanno fatto perseguire angularjs ulteriormente)
Jamie Pate

Ok, grazie per le informazioni e il tuo contributo al problema: lo tirerò su e ci giocherò tra un minuto.
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 e secondParam possono essere qualsiasi cosa in base alle tue esigenze.


0

Stavo riscontrando un problema simile e ho usato $stateParamsinvece dirouteParam

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.