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
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.
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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With