I am working on a UI issue. There is a misfire in load order that happens 1 out of every 50 times or so. The Angular JS app has a shared directive as a navigation button panel and that part is used by most of the other controllers.
Normal firing order
ButtonController.init() <--Set all buttons to hidden
EditGroupController.init() <--Set all buttons based on service call data
When the problem happens firing order
EditGroupController.init() <--Set all buttons based on service call data
ButtonController.init() <--Set all buttons to hidden
In scenario 2 above the EditGroupController tries to invoke an event on the ButtonController via:
$rootScope.$broadcast('setHeadersButtons', buttons);
However, when I trace into the angular internal code there is a logic branch where it looks for a registered listener with that name and it does not find one to fire because the module has not been loaded.
I remember in an Angular 7 app I used the APP_INITIALIZER to force a core piece to load first. Sorry if my wording is not precise front end / angular is not my specialty and this somewhat fell into my lap. Is there a way to ensure a directive in Angular JS is loaded before any other pieces?
There is an app.route.js, can I force the directive to load there?
Related
I am currently developing an administrative dashboard for my place of work using the BlurAdmin template. While this template contains many great features and great functionality, I found that this dashboard was not quite optimized for my use case. The dashboard that I am developing is completely based on a RESTful API built separately by one of my colleagues. Every page loads in its data through this API using AJAX and have found that most of the time, the page shows up before the API completes. This means that things just sporadically show up as the calls complete. In order to make for a smoother UI experience, I have began working on a solution for this.
Current Solution
While a route is being loading, a rootScope variable $isLoading is set to true which displays a loading overlay stretched over the page. In order to determine completion, I watch $http.pendingRequests.length until it is equal to 0 which tells me that the page has loaded successfully (based solely on http calls).
Desired Solution
While a route is being loaded, I would like the page not to change but instead utilize a top-bar loader and only when the page is loaded, should the routes change.
The routing is currently done by BlurAdmin using the ui-router module and the view is always instantly displayed by the ui-view directive.
My question then is: How do I preload an angular route into a hidden view while it builds, and only once I detect that all API calls have completed on this new route, should the hidden view switch to the visible view and the old visible view be removed?
You could do this by using a resolve on your state declaration. The basic idea would be to call your API from your resolve functions on the relevant state declarations. If you return promises from these functions the state will not be entered until the promises are all resolved. The values will then be bound into your component.
To show the spinner/loading bar on state transitions you could register a Transition Hook for 2 events: onStart and onFinish. Inside your onStart hook set some state on a service. Let's say isTransitioning = true;. Inside your onFinish hook, set this to false. Your spinner component could then watch this state and show itself when appropriate.
I want to start by saying that this is something I have to live with and I didn't made any decision on this.
We have an Angular Application in which we implement a Knockout component.
We apply the bindings to the component in the angular controller after all promises are resolved.
As it is a single page application if we go to another page and try to get back to the page with the knockout component we are getting the error:
you cannot apply bindings multiple times to the same element.
This is manily because the first time we loaded the page all the bindings were applied.
We tried using the ko.cleanNode() but it doesn't work. I think because it is a componend and not a ko element.
I am wondering if the right approach is to recreate the knockout component or force a reload of the angular module (which I know works b/c if we hit refresh on the browser the bindings work just fine).
I want to execute a piece of code every time a new the page in navigated to. I am using the <page-router-outlet>.
As mention here, while using page-router-outlet the component is cached. So when it is navigated back into view no Init lifecycle events of angular 2 are executed.
I tied using just the , which does not cache the component and as a result call the Init Lifecycle events. But using it exits the app when I press the Hardware back button.
The site you linked to also mentions this: "What you can do is inject Page inside your component and attach to page navigation events (for example navigatedFrom) and do the cleanup there." Those events are listed here, especially the "navigatedTo" event seems relevant for your usecase.
I have a small requirement. We have a application controller and a custom dijit which work together with each other.
I want to publish a event from the dijit and subscribe the same in controller. But the problem is the controller is not loaded first time when publish event is triggered, so the subscribe is not working first time.
Once the controller is loaded, if we publish again, then subscribe works perfectly fine.
Is there any solution to this problem ?
Have you tried dojo/ready to make sure, all necessary Parts are loaded? Check your loading hierarchy. Is it possible to load the controller in the init-phase at the start?
Regard
Thanks for your answers Dimitri and Ken Franqueiro & MiBrock. Dimitri's solution sound useful to me. The controller and the Widget which publish the event are not on same page also the controlller is not always loaded whereas the Widget is part of my Menu so its present on every page.
What I tried is used Memory to pass the data and first time called the function where the event and data will be used. So my widget sets data in Memory store and in controller, once its loaded we retrieve the value and use it. So this happens only first time, from second time onwards my published calls are working as Controller is loaded on page.
I have an AngularJS single-page app displaying 3 views (which are actually 3 directives). To illustrate my question, let's assume my UI is identical to that of GMail and that my 3 views are:
Navigation Pane (left) -- where GMail displays folders like "Inbox", "Drafts"...
Toolbar (top right) -- where GMail displays buttons
Content Pane (bottom right) -- where GMail displays messages
These 3 views need to update themselves whenever the path changes. For example:
The Navigation Pane needs to highlight a specific item.
The Toolbar needs to show/hide certain buttons.
The Content Pane needs to load and display specific data from the server.
What's the best way to do this in AngularJS?
So far, I have:
Ruled out the use of $routeProvider.when() because I need to update three views, and $routeProvider only supports one ngView.
Created a SERVICE that watches the current path and uses $rootScope.$broadcast() to warn the controllers that the path changed.
(OR, IN LIEU OF #2) Created a CONTROLLER that does the same as #2.
Caught the event broadcasted by #2 or #3 with $scope.$on() (I do this in a view controller).
This kind of works, but I have several issues:
The "path change" event is often broadcasted BEFORE my event listeners are in place, especially at initial page load. This is probably due to the fact that my view templates are loaded from the server and the listeners can't be set up before the templates have finished loading.
Isn't there a more efficient/automated way to watch for path changes in AngularJS? (See my code below, it seems pretty "manual".)
Does the code that watches for path changes belong in a SERVICE or in CONTROLLER? (I'd lean towards a service, since a controller is more to add behavior to a view.)
How to guarantee that my views will catch the "path changed" event? Should I use an event at all? (maybe I could store the path in a service, and have my views watch the service instead?)
My code to watch for path changes (I put this in a service or in a controller):
var watchExpression = function() { return $location.path(); };
var listener = function(newPath, oldPath) {
// Broadcast event on $rootScope
$rootScope.$broadcast('PathChanged', newPath);
};
$rootScope.$watch(watchExpression, listener);
Then, in a view controller, I catch the event:
$scope.$on('PathChanged', function(event, path) {
// Update view based on new path.
});
Any help appreciated. Thanks.
Your final version seems fine with the locationChangeSuccess, but for others reading this, I think you ruled out the $routeProvider too quickly. You can have one ng-view for the main content pane that changes with the path, and then other independent ("static") controllers/templates for the navigation pane and toolbar.
Now to listen to route changes in these other 2 controllers:
$rootScope.$on('$routeChangeSuccess', function(evt, cur, prev) {
...do what you have to do here, maybe set a $rootScope.path as you did
})
All using native Angular functionality. I actually do this in http://provok.in, a website I built using Angular, and I have a similar layout (well, not exactly, but I have "static" sections and an ng-view for the main content, dynamically updated based on the path, by the routeProvider).