Animation in AngularJS Directive, event not firing - javascript

I'm trying to do something after an 'enter' event in a directive. The event isn't firing when the template is loaded in.
Here is the app declaration
angular
.module('MyApp', [
'ngAnimate',
'ngCookies',
'ngResource',
'ngRoute',
'ngSanitize',
'ngTouch'
])
.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/home.html',
controller: 'HomeCtrl'
})
.when('/in-the-community', {
templateUrl: 'views/in-the-community.html',
controller: 'CommunityCtrl'
})
.otherwise({
redirectTo: '/'
});
});
Initially I am using the routing provider to give me a template page. I am then trying to use a directive inside these templates to provide another view. This works by using the following in my template page
<div class="flex">
<div class="fc fci image-wrapper" id="home-banner">
</div>
<div class="fc fcc">
<section show-and-hide-content="{{ sub_content }}">
</section>
</div>
</div>
This loads in the following directive
angular.module('rubisApp')
.directive('showAndHideContent', function ($animate) {
return {
templateUrl: 'views/community-sub.html',
controller: 'CommunitySubCtrl',
link: function(scope, element, attributes) {
$animate.on('enter', element,
function callback(element, phase) {
console.log('attributes.showAndHideContent');
}
);
}
};
});
The console log isn't running and I can only presume that is because it isn't firing the $animate.on event.
Does angular apply the ng-enter class to a templateUrl in a directive?
I'm pretty new to angular so if this is the wrong way of doing this, an alternative would really help also.

The $animate dependency as not being pulled into the directive.
angular.module('MyApp')
.directive('showAndHideContent',['$animate', function ($animate) {
return {
templateUrl: 'views/community-sub.html',
controller: 'CommunitySubCtrl',
link: function(scope, element, attributes) {
$animate.on('enter', element,
function callback(element, phase) {
console.log('attributes.showAndHideContent');
}
);
}
};
}]);

i see you are using an controller. can't you create the event there?
I checked my code and have this snippet on controller, to destroy an interval when route changes, notice that i use $on and '$destroy', with $. can it be that?
$scope.$on('$destroy', function () {
$interval.cancel($scope.interval);
});

Related

AngularJS directive templateUrl not loading into view

So I am using ui-view to route me to a partial.
//route.provider.js
(function() {
'use strict';
angular
.module('app')
.provider('RouteService', RouteService);
RouteService.$inject = ['$stateProvider', '$urlRouterProvider'];
function RouteService ($stateProvider, $urlRouterProvider) {
var service = {};
this.$get = function() { return service; };
this.initialize = function() {
$urlRouterProvider.otherwise('/login');
$stateProvider
.state('home', {
url: '/home',
controller: 'HomeController',
templateUrl: 'home/home.view.html',
controllerAs: 'viewModel'
})
.state('login', {
url: '/login',
controller: 'LoginController',
templateUrl: 'login/login.view.html',
controllerAs: 'viewModel'
})
//TODO Impliment the following partial pages...
.state('gensim', {
url: '/gensim',
templateUrl: 'general-simulation/simulation.view.html',
controller: 'TabsController',
controllerAs: 'tabs'
})
<...more routes...>
}
}
})();
The issue I am having is once it routes to
// general-simulation/simulation.view.html
I'd like it to use a custom directive to insert more html into the page.
Inside simulation.view.html I have this.
<div class="container">
<div class="row center">
<div class="col-xs-12">
<h1>General Simulation</h1>
<gs-tabs><h1>TEST!!!!</h1></gs-tabs>
</div>
</div>
</div>
The directive is constructed in
// tabs.directives.js
(function(){
'use strict';
angular
.module('app')
.directive('gsTabs', gsTabs);
function gsTabs () {
return {
restrict: "E",
templateURL: 'tabs.view.html'
};
}
})();
Finally, my tabs.view.html looks like this.
<h1>YOU HAVE ENTERED TABS PARTIAL</h1>
When I navigate to the page that displays simulation.view all I can see is:
General Simulation
TEST!!!!
So what am I doing wrong here. I checked for camelCasing and the page is not showing in errors. Any help would be greatly appreciated!
Update:
I viewed the network calls in chrome's dev tools.
simulation.view.html is being loaded but tabs.view.html isn't.
Request URL:http://sdc-stagt01/AngularJS/general-simulation/simulation.view.html
Request Method:GET
Status Code:200 OK
Remote Address:10.19.8.96:80
The file substructure is:
/general-simulation/tabs/tabs.controller.js
/general-simulation/tabs/tabs.directives.js
/general-simulation/tabs/tabs.view.html
/general-simulation/simulation.view.html
putting comment as answer
change templateURL to templateUrl
So entre's comment was a big help. That got chrome dev to start spitting out errors.
charlietfl Was on the right track with mentioning my file structure as well. I needed to change my directive to look like this:
templateUrl: 'general-simulation/tabs/tabs.view.html'
Thank you!
You have a typo here. templateUrl not templateURL
function gsTabs () {
return {
restrict: "E",
templateURL: 'tabs.view.html' // change this to templateUrl
};
}

AngularJS, How about multiple routes with different templates but the same controller?

i'm investigating if i can have what the title says.
Here's my thought.
Let's assume that i've got this routes:
.when('/', {
templateUrl : 'partials/homepage.html',
})
.when('/test', {
templateUrl : 'partials/test.html',
})
.when('/page/:pageID', {
templateUrl : 'partials/page.html',
})
.when('/page/single/:pageID', {
templateUrl : 'partials/page-single.html',
})
Until now i had the opportunity to add the templateUrl as also the controller details in the route and everything was working just fine.
Now the app is changed and there is only one controller with all the information needed and must remain one controller. And the routes will be something like that:
.when('/:templateName/:pageID', {
controller: 'myCtrl'
})
Can i set from the controller the template id by getting the templateName parameter? And if so how about the last route example /page/single/:pageID? How can i know that there is a second option in route?
I can take the templateName parameter and see it changing with the $routeChangeSuccess method but i cannot find any way to set the template on the fly.
Any ideas?
One solution could be the following one:
angular.module('myapp', []).
config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/:templateName/:pageId', {
templateUrl: function(urlattr){
return '/pages/' + urlattr.templateName + '.html';
},
controller: 'YourCtrl'
});
}
]);
From the AngularJs 1.3 Documentation:
templateUrl – {string|function()} – path or function that returns a path to an html template that should be used by ngView.
If templateUrl is a function, it will be called with the following parameters:
Array.<Object> - route parameters extracted from the current $location.path() by applying the current route
I would move your singleton logic from your controller to a service. Since you didn't provide much code below is an example to give you an idea how it could work.
app.config(function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'partials/homepage.html',
controller: 'SingleController'
})
.when('/test', {
templateUrl: 'partials/test.html',
controller: 'SingleController'
})
.when('/page/:pageId', {
templateUrl: 'partials/page.html',
controller: 'SingleController'
});
});
app.provider('appState', function() {
this.$get = [function() {
return {
data: {}
};
}];
});
app.controller('SingleController', function ($scope, appState) {
$scope.data = appState.data;
});
But if it must be a singleton controller you actually could use the ng-controller directive before your ng-view directive so it becomes a $rootScope like scope for all your views. After that just add empty function wrappers in your $routeProvider for the controllers.

How do i can run directive function before controller?

I need call directive function ( i need scope ) before controller.
var app = angular.module('docsRestrictDirective', []);
app.controller('Controller', ['$scope', function($scope ) {
$scope.changeDerictive();
}]);
app.directive('ngMyDer', function() {
return {
restrict: 'A',
compile: function compile(tElement, tAttrs, transclude) {
return {
pre: function preLink(scope, iElement, iAttrs, controller) {
scope.changeDerictive = function() {
console.log("changed");
};
}
}
}
}
});
http://plnkr.co/edit/NWb23rScg8zvPluGBWH5?p=preview
as requested this is the example with ui-router.
first we will define a controller for the base of the app.
<body ng-app="myApp" ng-controller="AppBaseCtrl">
<main role="main">
<overlay-spinner></overlay-spinner>
<invite-success></invite-success>
<div ui-view></div>
</main>
</body>
now in the ui router we will define our base route:
.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/desiredRoute');
$stateProvider
.state('desiredRoute', {
url: '/desiredRoute',
templateUrl: 'views/pathToTemplate.html',
controller: 'MyViewCtrl'
})
});
so what will happen? the base controller runs, we can initialize desired scope variables, then we run the directives and then we run our required controller.
so you have the directive which runs before the needed controller.
if we want this to be cleaner with ui-router we can define the routes like this:
in the routes config:
.state('dashboard', {
url: '/dashboard',
templateUrl: 'views/templates/dashboard/dashboard-base.html',
controller: 'DashboardBaseCtrl',
abstract: true
})
.state('dashboard.main', {
url: '/main',
templateUrl: 'views/templates/dashboard/dashboard-main.html',
controller: 'DashboardMainCtrl'
})
then in the view for the dashboard-base:
<div myDirective></div>
<div ui-view></div>
and of course define in the base controller what ever you want and as you can see... base controller runs then directive then our desired controller so directive runs before the controller...
EDIT
I have created a small plunker like you asked... you will see here that with no timeout the directive is called before our main controller does using a base controller my example is the first example in the answer
plunker with answer
Your ng-controller is written before your directive ,so if you want to call directive frist write ng-controller after your directive
like this
<body ng-app="docsRestrictDirective">
<div ></div>
<div ng-my-der></div>
<div ng-controller="Controller"></div>
</body>
Then it will show result according to you
Plunker: http://plnkr.co/edit/0qccTyPADwDaq05KKmao?p=preview
There is a priority between angularjs directives.ng-controller is directive too,try that priority.Maybe it can help you.
Thanks for answers.
I did it this way
var app = angular.module('app', []);
app.controller( "Ctrl",[ "$scope", function ( $scope ) {
$scope.$watch ( "ngExchange", function ( ) {
$scope._ngExchange[0].remove()
$scope._ngExchange[1].after( $scope._ngExchange[0] );
} );
} ] );
app.directive('ngExchange', function(){
return {
restrict: 'A',
controller: function ( $scope, $element, $attrs ) {
if ( $scope._ngExchange === undefined ) {
$scope._ngExchange = [];
}
$scope._ngExchange.push( $element );
}
}
});
http://plnkr.co/edit/fagINqNafPp6vEhawNbl?p=preview

AngularJS dynamically set class on <html> tag based on route

I'm not sure the best way to approach this.
I want to dynamically set a class on my /login route so that my login page can have a large background image.
What is the best way to approach this?
Here's my current code:
<!DOCTYPE html>
<html class="SOME_DYNAMIC_CLASS_HERE_BASED_ON_ROUTE">
...
</html>
<body ng-app="myApp">
<div ng-view=""></div>
</body>
angular.module('myApp', ['ngRoute']).config(function ($routeProvider) {
$routeProvider
.when('/login', {
templateUrl: 'login.html',
controller: 'LoginCtrl'
})
.when('/', {
templateUrl: 'dashboard.html',
controller: 'DashboardCtrl'
})
You must have your ng-app attached in the <html> element, to have any sort of connection between angular and the view. Since you want something to change base on the current route of your application, then why not use those routes as a reference for your configuration, e.g. the $routeProvider configuration. Attach all your configuration, including configuration from classes to styles or any other configuration within the route object. You can then create a directive that listens to route changes via $routeChangeSuccess and then get the current route and other properties using the $route object defined as the second parameter of the $routeChangeSuccess listener, once you have those properties, you can do whatever you want with it e.g. append a class to that directive element.
DEMO
Javascript
Configuration
.config(function ($routeProvider) {
$routeProvider
.when('/dashboard', {
templateUrl: 'dashboard.html',
'class': 'bg-dashboard'
})
.when('/login', {
templateUrl: 'login.html',
'class': 'bg-login'
})
.otherwise({redirectTo: '/login'});
});
Directive
.directive('classRoute', function($rootScope, $route) {
return function(scope, elem, attr) {
var previous = '';
$rootScope.$on('$routeChangeSuccess', function(event, currentRoute) {
var route = currentRoute.$$route;
if(route) {
var cls = route['class'];
if(previous) {
attr.$removeClass(previous);
}
if(cls) {
previous = cls;
attr.$addClass(cls);
}
}
});
};
});
HTML
<html ng-app="myApp" class-route>...</html>
Using a directive is one way to go.
.directive("routeClass", function($location, $parse) {
var mapping = {};
return {
restrict: "A",
scope: {},
link: function(scope, element, attrs) {
mapping = $parse(attrs["routeClass"])(scope);
// do something with mapping and $location or $routeParams
}
}
});
<any route-class="{'/': 'default', '/Book': 'book'}" />
Another - is to set it via $rootScope.
I know this is an old thread, but I came across it looking for some pointers. I have gone for the following method which feels more "Angular". Note, it is using a controllerAs-based directive:
ngModule.directive('routeClass', routeClass);
function routeClass($state, $log) {
function controllerFn($scope) {
var routeClass = this;
$scope.$on('$stateChangeSuccess', function(){
// I have a different class name assignment as the
// setup of my states is relatively complex,
// but this should demonstrate the idea
routeClass.current = 'page-' + $state.current.name;
});
}
return {
controller: controllerFn,
controllerAs: 'routeClass',
restrict: 'A'
};
}
And it is used as follows in index.html:
<body ng-app="app" route-class ng-class="{{routeClass.current}}">

Nested directive within ng-view doesn't work AngularJs

I developing a SPA using the native directive from angular ng-view to change views, the problem is that One of those views there is a custom directive I've wrote and when the route is loaded the directive doesnt work.
Here it is the config method of the App and the custom directive that doesn't fire up :S
climbingApp.config(
function( $routeProvider ){
$routeProvider.
when('/', {
controller: 'AppCtrl'
}).
when('/newSector', {
template: '<formNewSector></formNewSector>',
controller: 'addSector',
}).
otherwise({ redirectTo: '/'});
}
);
climbingApp.directives
.directive(
'formNewSector',
function() {
return {
restrict: 'E',
template: "<div>gato</div>",
replace: true,
link: function( scope, iElement, iAttrs ){
}
}
});
You misspelled markup for directive in your template. For directive named formNewSector it should be <form-new-sector>, not <formNewSector>.

Categories

Resources