Waypoints.js not working as expected with angular views - javascript

I am trying to apply some css animation to some of the elements in my views when they reach the top of the window (offset 70%) with the help of waypoints.js.
I've created a directive as shown below.
angular.module("myApp")
.directive("clWaypoints",function(){
return{
restrict:"A",
link: function(scope,element,attrs)
{
var wayp=new Waypoint({
element:element,
handler:function(direction){
if(direction=="down")
{
var animation = scope.$eval(attrs.clWaypoints).animation;
element.css('opacity', '1');
element.addClass("animated " + animation);
}
},
offset:'70%',
})
}
}
})
Below is my app.js file
angular
.module('myApp', [
'ngRoute',
])
.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/home.html',
controller: "mainCtrl"
})
.when('/about', {
templateUrl: 'views/about.html'
})
.otherwise({
redirectTo: '/'
});
});
Both the views contain elements which use the cl-waypoints="{animation:'fadeInUp'}" directive.
When the app is loaded on a browser, the animations work as expected, but when I navigate to another view and begin to scroll down the elements in that view are not animated. Anyhow if I refresh the page, it works just fine.
Looks like the page needs to be refreshed for waypoint.js to do its magic. Please let me know if there is a solution to this problem.
Would appreciate any help.
Thanks.

Was able to find a solution to this problem. Waypoint requires us to call a function (Waypoint.refreshAll()) every time we make changes to the DOM, in our case changing the view content.
Added an $viewContentLoaded event listener (in the parent controller) to call the method whenever the view changes.
$scope.$on('$viewContentLoaded', function(event){
$timeout(function() {
Waypoint.refreshAll()
},0);
});
Hope this helps others.

Related

Why wont ngRoute now work and breaks all other Angular functionality?

I am trying to us ngRoute to inject HTML into my web page but it doesn't work.
I have the below in my main html document.
<main ng-view></main>
next i created a folder call views with two HTML files (news.html & sectors.html)
I have also included angular-route.min.js into my project correctly. All paths for all files are correct.
Next I set up my routes as below, but it renders a blank page and even breaks the rendering of any ng-includes I have implemented which previously worked. In addition, it also breaks all other Angular functionality like filtering. There are no errors in the console, it just seems that ngRoute wont work.
var app = angular.module('app', ['ngRoute']);
app.config(['$routeProvider', function($routeProvider){
$routeProvider
.when('/sectors', {
templateUrl: 'views/sectors.html'
})
.when('/news', {
templateUrl: 'views/news.html',
controller: 'primaryController'
}).otherwise({
redirectTo: '/sectors'
});
}]);
Any help welcome.
You can check templateUrl for the path to your html templates. Everything else seems correct.

angular.js:13424 Error: [$injector:unpr]

I am using the angular-ui-bootstrap library to implement the bootstrap modal - see here.
All is good, the modal is opening, but it will not close. I have tried to use $uibModalInstance but when I attempt to close the modal, as per the example in the link above this I get the following message:
angular.js:13424 Error: [$injector:unpr] http://errors.angularjs.org/1.5.3/$injector/unpr?p0=%24uibModalInstanceProvider%20%3C-%20%24uibModalInstance%20%3C-%20testCtrl
I am using Angular version 1.5.3, ui-bootstrap-tpls v1.3.1 and bootstrap css 3.3.6
My code looks like the following. I have attempted all answers dealing with the same issue on this, but cannot resolve the issue. I think there is an issue with the angular version, but before I go and play around with the version of angular I want to make sure there is nothing I am missing out. I thought this answer would work, but no such luck.
app.js
var app = angular.module('testApp', ['ui.bootstrap'])
.config(function($routeProvider) {
$routeProvider.
when('/', {
templateUrl: 'app/views/address-book.html',
controller: 'testCtrl as ctrl'
}).
otherwise({
redirectTo: '/'
});
})
.controller('testCtrl', ['$uibModal', '$uibModalInstance', function ($uibModal, $uibModalInstance) {
this.open = function () {
testCtrl.modalInstance = $uibModal.open({
templateUrl: 'app/views/partials/form.html',
controller: 'testCtrl as ctrl'
});
}
this.close = function() {
console.log(testCtrl.modalInstance) //this shows undefined
testCtrl.modalInstance.close();
}
}]);
html
<a class="enterNewAddressBtn" ng-click="ctrl.open()">Enter new address</a>
form.html
<form>
<input ng-model="ctrl.name" type="text">
<button class="cancel-btn" ng-click="ctrl.close()">Cancel</button>
</form>
This error shown because you want to inject $uibModalInstanceProvider before create modal Instance .If you use different controller and inject $uibModalInstance in modalInstance controller then this error will be remove.
Better to use different controller for $uibModal and $uibModalInstance. The $uibModalInstance represents a modal window (instance) dependency it is not the same as the $uibModal service. Modal open using $uibModal and close using $uibModalInstance.
You can get Idea from this question and for more details can visit plunker example from here.
It may will help you
If i recall correctly you can't inject $uibModalInstance before you've created the modal using $uibModal.open();
move the injection of $uibModalInstance to the touchnoteCtrl and it should work fine.

Angular-ngRoute: force ng-view contents, allow navigation afterwards

While using ngRoute, I want to have Angular configured so that the current contents of ng-view are left as the contents for the current route, and allow the user to navigate away to different routes, rendering their respective templates afterwards:
Plunker
HTML
<ul class="menu">
<li>view1</li>
<li>view2</li>
</ul>
<div ng-view>
<ul>
<li>Some</li>
<li>Soon obliterated</li>
<li>Content</li>
</ul>
</div>
JavaScript
angular.module('myApp', ['ngRoute'])
.config(function($routeProvider) {
$routeProvider
.when('/view1', {
templateUrl: 'view1.html',
controller: 'View1Ctrl'
})
.when('/view2', {
templateUrl: 'view2.html',
controller: 'View2Ctrl'
})
.otherwise({
redirectTo: '/view1'
})
})
.controller('View1Ctrl', function() {
})
.controller('View2Ctrl', function() {
});
When the user first sees the page, I want him to see the following:
Note: Angular needs to be bootstrapped at this point, with directives functioning in this area.
Note 2: This content should be in the actual HTML of the page, not in a template or script tag.
Then, when the 'view2' link is clicked:
And then, when the 'view1' link is clicked:
My first thought was using $route.updateParams(newParams) but I think that's not really its purpose.
EDIT
I ended up using
//Server-side rendered code
myModule
.config(['$routeProvider', function($routeProvider){
$routeProvider.when('<# my current route #>',
{
templateUrl: '/server-static',
});
angular.bootstrap(myModule);
In app.js:
myModule
.config('$routeProvider', function($routeProvider){
$routeProvider.when('/my-client-routes',
{
templateUrl: '/my-template.html',
}); // etc.
How can I trick Angular into thinking that the contents of ng-view are the appropiate contents for the current entry route? Can I just cancel route resolution/ngView directive (or make it transclude) rendering for first load? Or if not possible, what's the preferred method to do this?
Thanks
EDIT: See this answer that proposes adding the contents of ng-view to $templateCache through a custom directive.
It's possible for templateUrl to be a function. In which case you can actually change the view based on some kind of state:
var initialized = false;
$routeProvider
.when('/view1', {
templateUrl: function(){
if(initialized){
return 'view1.html';
}
initialized = true;
return 'view-initial.html';
},
controller: 'View1Ctrl'
})
Here is a working Plunker based on yours.
The task you're asking help for can be achieved in a number of ways. #Josh offers a good one. Using $templateCache is another option. But, as you correctly said, these are tricks.
Correct and only recommended approach is to use dedicated template for a default route. You can specify it via external file, via template cache or even script tag, but it's much better, clear and easy to support.
If it's your own code - just choose any preferred way you like. If you want it to be shared with community, used as open-source or enterprise solution - I'd suggest to use the only recommended approach.
Or... look into ui-router )) . May be it's nested views support is the option you need.

Link to #ID element from another page in AngularJS

I've tried all the solutions presented here:
How to handle anchor hash linking in AngularJS
But none worked for me.
In my header.html I have a link: <a id="button" href="#/views/home#page"> Contact</a></li>
To an ID in home.html
When I am in /home it works, but when I am in another page it doesn't work.
I tried using ##page with no success.
Or putting this in app.js:
app.run(function($rootScope, $location, $anchorScroll, $routeParams) {
$rootScope.$on('$routeChangeSuccess', function(newRoute, oldRoute) {
$location.hash($routeParams.scrollTo);
$anchorScroll();
});
});
and customizing my link:
href="#/views/home/?scrollTo=page"
Can someone explain which files should I edit and how?
Edit:
I started from Angular-Seed
My app.js is:
'use strict';
// Declare app level module which depends on views, and components
angular.module('myApp', [
'ngRoute',
'myApp.view1',
'myApp.view2',
'myApp.training',
'myApp.faq',
'myApp.media',
'myApp.contact',
'myApp.home',
'myApp.apply',
'myApp.classes',
'myApp.version'
]).
config(['$routeProvider', function($routeProvider) {
$routeProvider.otherwise({redirectTo: '/views/home'});
}]);
And in every view I have another js file like training.js which looks like:
'use strict';
angular.module('myApp.training', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/views/training', {
templateUrl: 'views/training/training.html',
controller: 'TrainingCtrl'
});
}])
.controller('TrainingCtrl', [function() {
}]);
It is configured based on angular-seed model.
So, when, I am in view /faq that has the partial header with the menu and all the links, how can I link to a specific ID in view /home?
I think that the problem is that you have the logic for scrolling to that hash in the $routeChangeSuccess and as the documentation says, this event is:
Broadcasted after a route dependencies are resolved. ngView listens
for the directive to instantiate the controller and render the view.
So the view is not rendered yet, therefore the DOM element with that id doesn't exist yet.
Try putting that logic in the onload event of the ngView directive instead.
I've created this plunker: http://plnkr.co/edit/S7bUT8iYY7UEti71X5Z8?p=preview that shows that if you add that logic into the onload event of the ngView directive everything works fine.

AngularJS have ng-view display a dynamic footer outside of its div

I'm fairly new to angular.js so I'm seeking advice on how to best implement the functionality described here. I have an html body with header, sidebar and a content area provided by <div class="container-fluid" ng-view></div>. Because this is a standard twitter-bootstrap layout , the ng-view is not a direct descendant of the body element.
I have one view that shall contain an infinitely scrollable list. When at least one element of the list is selected, I want to slide-up a footer that contains contextual actions (the footer shall be position:fixed so that it's always displayed on top of the list). In essence this is similar to what happens on the Windows 8 Metro home-screen when you right click a tile.
The problem I now have is that the footer can't be part of the ng-view partial because it needs to live directly under the body in the DOM. What's a good way to handle this with Angular.js and ng-view when I'd want to keep a single controller for the list and the dynamic footer? If there's a CSS solution to this, I'd be happy to hear about it too.
It sounds like you need to have the footer outside the ng-view element in order to handle the layout you are wanting. I'll leave the layout/CSS to you but the following example demonstrates a way to communicate with the directive if it were to live outside ng-view.
Here's a plunkr (http://plnkr.co/edit/NpoIrOdfvn9XZiXY9YyV?p=preview).
HTML
<body ng-app="someApp">
<div ng-view></div>
<footer-directive></footer-directive>
</body>
JS
angular.module('someApp', []).config(function($routeProvider) {
$routeProvider.when('/', {
template: '<p>template</p>',
controller: 'SomeCtrl'
}).otherwise({
redirectTo: '/'
});
}).service('broadcastService', function($rootScope, $log) {
this.broadcast = function(eventName, payload) {
$log.info('broadcasting: ' + eventName + payload);
$rootScope.$broadcast(eventName, payload);
};
}).controller('SomeCtrl', function(broadcastService, $log, $timeout) {
//fire off showfooter message
broadcastService.broadcast('ShowFooter', {
some: 'data'
});
// wait 3 seconds and hide footer
$timeout(function() {
//fire off hide message
broadcastService.broadcast('HideFooter');
}, 3000);
}).directive('footerDirective', function(broadcastService, $log) {
return {
restrict: 'E',
link: function(scope, elm, attr) {
elm.hide();
scope.$on('ShowFooter', function(payload) {
$log.info('payload received');
$log.debug(payload);
// assuming you have jQuery
elm.show();
});
scope.$on('HideFooter', function() {
// assuming you have jQuery
elm.hide();
});
}
}
});

Categories

Resources