AlexG AlexG - 2 months ago 22
AngularJS Question

Javascript not accessible from inside Angular ui-view

I have a main template (index.html) with an Angular ui-view. Inside this main template I import a bunch of Javascript files. I expect these files to be available to the content inside the html templates that will be loaded inside the ui-view, but the JS functions are seemingly inaccessible.

/sample-app/index.html:

<html ng-app="otr">
<head></head>
<body>
<div ui-view></div>

<!-- JS imports -->
<script src="//code.jquery.com/jquery-2.1.3.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>

<!-- Angular Dependencies -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0-rc.1/angular.min.js"></script>
<script src="https://code.angularjs.org/1.4.0-rc.1/angular-route.min.js"></script>
<script src="https://code.angularjs.org/1.4.0-rc.1/angular-cookies.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.14/angular-ui-router.min.js"></script>

<!-- Custom scripts -->
<script src="/sample-app/js/login.js"></script>

<!-- Angular app scripts -->
<script src="app/app.js"></script>
<script src="app/services/authentication.service.js"></script>
<script src="app/services/flash.service.js"></script>
<script src="app/common/cases-model.js"></script>

<script src="app/home/home.controller.js"></script>
<script src="app/login/login.controller.js"></script>
<script src="app/register/register.controller.js"></script>

</body>
</html>


/sample-app/js/login.js

$(function() {

$('#login-form-link').click(function(e) {
$("#login-form").delay(100).fadeIn(100);
$("#register-form").fadeOut(100);
$('#register-form-link').removeClass('active');
$(this).addClass('active');
e.preventDefault();
});
$('#register-form-link').click(function(e) {
console.log('Inside login.js REGISTER');
$("#register-form").delay(100).fadeIn(100);
$("#login-form").fadeOut(100);
$('#login-form-link').removeClass('active');
$(this).addClass('active');
e.preventDefault();
});

});


/sample-app/app/app.js:

(function () {
'use strict';

angular.module('otr', [
'ngRoute',
'ngCookies',
'ui.router',
])
.config(config)
.run(run);

function config($stateProvider, $urlRouterProvider, $httpProvider) {

$stateProvider
.state('otr', {
url: '',
abstract: true
})
.state('login', {
url: '/login',
controller: 'LoginController as vm',
templateUrl: 'app/login/login.view.html'
})
.state('register', {
url: '/register',
controller: 'RegisterController as vm',
templateUrl: 'app/register/register.view.html'
})
.state('home', {
url: '/',
controller: 'HomeController as vm',
templateUrl: 'pages/home2.view.html'
})
;

$urlRouterProvider.otherwise('/login');
$httpProvider.defaults.withCredentials = true;
}

function run($rootScope, $location, $cookies, $http) {
// keep user logged in after page refresh
$rootScope.globals = $cookies.get('globals') || {};

$rootScope.$on('$locationChangeStart', function (event, next, current) {
// redirect to login page if not logged in and trying to access a restricted page
var restrictedPage = $.inArray($location.path(), ['/login', '/register']) === -1;
var loggedIn = $rootScope.globals.currentUser;
if (restrictedPage && !loggedIn) {
$location.path('/login');
}
});
}

})();



  • The ui-view content loads just fine, but without the JS functions being called.

  • If I copy/paste the content directly into index.html, everything works as expected

  • If I place the JS import inside the partial template, that works as well.



What am I missing?

Answer

I gave up on trying to get the JavaScript to load and the ui-view to recognize it. I ultimately solved this by creating an Angular directive that duplicated the function of the JavaScript.

Directive:

angular.module('otr')
    .directive('loginForm', loginFormDirective)
    .directive('registerForm', registerFormDirective)
;

function loginFormDirective() {
    return function(scope, element, attrs) {

        element.bind('click', function() {
            console.log('element: ', element[0].id);
            console.log('attributes: ', attrs);

            $('#' + attrs.loginForm).delay(100).fadeIn(100);
            $("#register-form").fadeOut(100);
            $('#register-form-link').removeClass('active');
            $('#' + element[0].id).addClass('active');
        })
    }
}

function registerFormDirective() {
    return function(scope, element, attrs) {

        element.bind('click', function() {
            $('#' + attrs.registerForm).delay(100).fadeIn(100);
            $("#login-form").fadeOut(100);
            $('#login-form-link').removeClass('active');
            $('#' + element[0].id).addClass('active');
        })
    }
}

My view now has the following code snippet:

<div class="row">
    <div class="col-xs-6">
        <a href="#" class="active" id="login-form-link" login-form="login-form">Login</a>
    </div>
    <div class="col-xs-6">
        <a href="#" id="register-form-link" register-form="register-form">Register</a>
    </div>
</div>

Thanks to all of you who took the time to read my question and post answers!