0

I have a site that are using AngularJS and UI-Router. In order to have a separate login-page (that is not injected into the main view), I have separated the index.html (with both layout and scripts include) into an index.html (with only scripts include) and a layout.html (with only layout) as per AngularJS UI-Router multiple pages.

However my problem is that I have quite a lot of UI-logic in the script.js file (the theme is bought) and when I split up my index.html, then the UI elements in the scripts.js file, wont work in the layout.html file.

Index.html

<!DOCTYPE html>
<html lang="en" ng-app="myApp">
    <head>
        <link rel="stylesheet" href="style.css" />
    </head>
    <body>
        <div ui-view></div>
        <!-- Angular, JQuery and App specific scripts -->
        <script src="script.js"></script>
    </body>
</html>

Layout.html

<div>
    <!-- Navigation layout that requires functions in script.js and some controller layout (showing currently logged in user) -->
    <div ui-view></div>
</div>

I have created a Plunker to show my problem: http://plnkr.co/edit/O1G179cu5AZeVURxPgPq?p=preview

Is it possible to split up the index as I have, and still use the script.js file in layout?

Community
  • 1
  • 1
andreasnauta
  • 638
  • 7
  • 18

1 Answers1

0

Your problem is one of timing. Your script is run right on window load, not when your state has finished loading. I.E. at the time when the script is run the element you are looking for (layoutColor) doesn't exist, it has not been rendered yet.

What you need to do is to make sure the script is run after the state changes. The easiest way is probably to trigger script.js after each route change, but you could also do it in each controller if you don't want it to run all the time.

Still, I would suggest using the $viewContentLoaded event to do this. This event is fired after a view has finished loading and you can bind it on the rootScope if you always want to trigger the script. Note that even in this case there might be instances where you need to trigger it manually if you are adding things to the DOM after a view has loaded.

app.run(['$rootScope', function ($rootScope) {
    $rootScope.$on('$viewContentLoaded ', function(){
        // Trigger the script
    })
}]);

You will need to create a way to manually trigger the script.js, how to do that depends a lot on what you actually have in there so I can't really comment on it.

Edit

Changed to $viewContentLoaded instead of $stateChangeSuccess since the former is always run after the DOM has loaded, and thereby doesn't need any timeouts.

Erik Honn
  • 7,576
  • 5
  • 33
  • 42
  • Thank you for your reply! Your solution worked in my Plunker, if I removed windows.load. This led me to believe that my structure was wrong (as it would be impossible to rewrite all the external JavaScript). I recreated the index.html with both the layout and script loading, added a ng-controller along with ng-app (so now index had a controller), and created a second named ui-view in Index.html. This view shows my login form and while the user is not authenticated, the navigiation is hidden with ng-show. Maybe not the prettiest solution, but it works. – andreasnauta Mar 23 '15 at 10:51
  • Yea, files that lack a way of manually starting the scripts can be a pain to use in single page applications. One way is usually to wrap all of it in a function (as in the *entire* external script) just so you have something to call. Doesn't always work though, depends on the script. – Erik Honn Mar 23 '15 at 10:58