Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular component based approach and working with resolve in Router

So I'm working with the component based approach in angular, lets say I have A directive called <home></home>;

import template from  './home.html'; import controller from './home.controller.js';  angular.module('myApp')    .directive('home', homeDirective);  let homeDirective = () => {     return {         restrict: 'E',         template,          controller,         controllerAs: 'vm',         bindToController: true     }; }; 

Now I'm able to use the component <home></home> in my routing as follow:

angular.module('myApp')     .config(($routeProvider) => {         $routeProvider.when('/', {             template: '<home></home>'         })     }) 

I really like this approach, but with the "old" approach I was used to using "resolve" in my routeconfig to render the component only when a promise was resolved:

angular.module('myApp')     .config(($routeProvider) => {         $routeProvider.when('/', {             templateUrl: './home.html',             controller: './home.controller.js',             resolve: {             message: function(messageService){                 return messageService.getMessage();             }         })     }) 

Question

How can I use resolve with a component based approach in angular? aaj

like image 665
koningdavid Avatar asked Dec 02 '15 14:12

koningdavid


People also ask

What is resolver in angular routing?

So what is Angular Resolver? Angular Route Resolver is used for pre-fetching some of the data when the user is navigating from one route to another. It can be defined as a smooth approach for enhancing user experience by loading data before the user navigates to a particular component.

What is the use of resolve object in routing?

Resolvelink A data provider class can be used with the router to resolve data during navigation. The interface defines a resolve() method that is invoked right after the ResolveStart router event. The router waits for the data to be resolved before the route is finally activated.


2 Answers

There is a closed issue about that: support resolve option for directives.

The conclusion is that they don't want arbitrary directives being loaded asynchronously, because it would cause too much flicker.

The good news is that Angular 2 supports this (and much more) at the DI layer in a way that's cohesive and doesn't introduce a ton of additional complexity.

In Angular 1.x you could attribute the directive with some information from where the message is to be obtained, and handle the asynchronous loading in your controller. This way you can show some nice loader screen too.

angular.module('myApp')     .config(($routeProvider) => {         $routeProvider.when('/', {             template: '<home my-datasource="feed1"></home>'         }).when('/other', {             template: '<home my-datasource="feed2"></home>'         })     })     .factory('DataSources', (messageService) => {         return {             feed1: messageService.getMessage,             feed2: messageService.getError         };     }); 

Or, if you want message to be from always the same source, you can burn messageService.getMessage().then(...) into your controller.

If you don't want the directive to be visible at all before the promises resolve, you can introduce a scope variable initially set to false and then set it to true on resolution, e.g.:

app.controller('HomeController', ($scope, messageService) => {    $scope.loaded = false;    messageService.getMessage().then(message => {        ...        $scope.loaded = true;    });    ... }); 

and hide the directive until loaded with ng-if="loaded" at the root element. Yes, that is a bit too much user code, but you have control over everything at least.

like image 88
Tamas Hegedus Avatar answered Oct 11 '22 18:10

Tamas Hegedus


As it turns out, the angular $routeProvider passes the resolved locals on to the $routeChangeSuccess event (nextRoute.locals). So you could create a service that listens for route changes and exposes the locals:

angular.module('myApp', ['ngRoute']) .factory('$routeLocals', function($rootScope) {   var locals = {};   $rootScope.$on('$routeChangeSuccess', function(_, newRoute) {     angular.copy(newRoute.locals, locals);   });   return locals; }) .run(function($routeLocals) {}); 

Then you can inject $routeLocals into your directive and use them.

Example: http://codepen.io/fbcouch/pen/eJYLBe

https://github.com/angular/angular.js/blob/master/src/ngRoute/route.js#L614

like image 20
Jami Couch Avatar answered Oct 11 '22 19:10

Jami Couch