Nested directive within ng-view doesn't work AngularJs - javascript

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>.

Related

dynamic nested view with angular component

i have an angularjs app with components and i want to add a view as child of another view using ui.router. i honestly dont think that ui.router fully support component, this may happen in upcomping 1.0 version. But in the meanwhile is anything that i can do to use display view dynamically?
this is my $stateProvider (i've done my attempts)
$stateProvider
.state('home', {
url :'/home',
template :'<home></home>'
})
.state('projects', {
url:'/projects',
template: "<project-list></project-list>"
})
.state('projectDetails',{
url:'/:projectId',
template : '<project-detail projectDetails="projectDetails"></project-detail>'
, views :{
'chat':{
template : '<chat></chat>'
}
}
});
$urlRouterProvider.otherwise('home');
i have created a component in this way:
(function() {
'use strict';
function ChatController($scope, $element, $attrs, $firebaseArray) {
var ctrl = this;
console.log("it works");
}
angular.module('myapp').component('chat', {
templateUrl: '/app/component/project/chat.html',
controller: ChatController
});
})(window.angular);
and then i've added the view in projectDetails
<div ui-view="chat"></div>
My understanding of your requirement is that you have a component called 'Chat' which you want to load in the state 'project-details' as a nested/child view.
As you have already observed ui-router does not support this.
But this can be achieved by making your 'project-details' as a parent state and load other components included as a child state.
Plunker Demo
angular.module('app', [
'ui.router'
]).config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider.state('home', {
template: '<home></home>'
}).state('home.parts', {
url: '/',
views: {
'about-view#home': {
template: "<about></about>"
},
'chat-view#home': {
template: "<chat></chat>"
}
}
});
}).component('app', {
templateUrl: 'app.html'
}).component('home', {
templateUrl: 'home.html',
controller: homeController,
controllerAs: 'vm'
}).component('about', {
templateUrl: 'about.html',
controller: aboutController,
controllerAs: 'vm'
}).component('chat', {
templateUrl: 'chat.html',
controller: chatController,
controllerAs: 'vm'
});
function chatController() {
this.name = "chat";
}
function aboutController() {
this.name = "about";
}
function homeController() {
this.name = "home";
}
Hope this is what you wanted.Please do not add url to the parent state.Consider making it a abstract state.

Animation in AngularJS Directive, event not firing

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);
});

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}}">

Get parameters from routeProvider in element directive

I have an element directive and I want to know if I can get parameters from routeProvider to render my template and set it up in my controller.
adminDash.directive('hospitals', function() {
return {
restrict: 'E',
templateUrl: 'www/partials/admin/hospitals.html',
controller: 'AdminHospitalsController',
controllerAs: 'hospitalsCtrl',
};
});
How can I get any parameters in my element directive?
You can isolate the scope of the directive, like this:
adminDash.directive('hospitals', function() {
return {
restrict: 'E',
templateUrl: 'www/partials/admin/hospitals.html',
controller: 'AdminHospitalsController',
controllerAs: 'hospitalsCtrl',
scope: {
paramValue: '&',
paramVariable: '=',
},
};
});
check this to understand better https://thinkster.io/egghead/isolate-scope-am/
There are 2 ways to do it: both involve using $routeParams service that allows you to retrieve current set of route parameters.
Given that you have an url: http://example.com/#/hospitals/foobar and a route /hospitals/:hospital/ configured in your $routeProvider, you can:
1.Inject $routeParams into your directive:
adminDash.directive('hospitals', function($routeParams) {
return {
restrict: 'E',
templateUrl: 'www/partials/admin/hospitals.html',
controller: 'AdminHospitalsController',
controllerAs: 'hospitalsCtrl',
link: function(scope, element){
scope.hospital = $routeParams.hospital;
}
};
});
2.Inject $routeParams into AdminHospitalsController
adminDash.controller('AdminHospitalsController', function($scope, $routeParams) {
$scope.hospital = $routeParams.hospital;
}
Both method will result in having hospital=foobar in your directive's scope;

Categories

Resources