I'm trying to do angular (1.3.14) directive to handle scrolling event on element like this
var app = angular.module('myApp', []);
app.directive("scroll", function ($window) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
console.log(element.className); // return 'undefined'
element.on('scroll', function(e) {
console.log('scroll'); //not working
});
element.on('click', function(e) {
console.log('click'); //working
});
}
}
});
My problem is that scroll event doesn't fire. Every other event like clicking is normaly working, but scrolling not. Also when I try to get class of element I get 'undefined' and my element has class. It's html:
<body ng-app="myApp" ng-controller="myCtrl" ng-keydown="keyListener($event)">
<section class="dark content second" scroll="">
</section>
</body>
I don't know what can be wrong here.
Your directive is right, I've made a test with an internal div in your section with some classes to make it scrollable
<section class="dark content second" scroll="">
Hi
<div class="internal">
Something
</div>
</section>
CSS
.second{
background-color: red;
max-height: 150px;
overflow-y:scroll;
}
.internal{
height: 200px;
}
And the event works perfectly! You just have to make your <section> scrollable or apply the directive in the body/html tag. Here's the Plunker example that I've tested http://plnkr.co/edit/hp2BbnLeGjtwIbfi2mqZ?p=preview
Try this
console.log(attrs.class);
element.bind('scroll', function() {
console.log('scroll');
});
Related
Whenever any element inside my DIV is clicked I want to execute a function in Angular controller.
How to do this?
Basically I am looking to place a ng-click on DIV element and expect the ng-click event be called when any/all elements nested inside the div are clicked.
How to achieve this requirement?
Here both the container and the button has click events. When you click the button, the click event of its parent will also be triggered. This is called Event Bubbling in JavaScript
var app = angular.module('myApp', []);
app.controller('myCtrl', function ($scope) {
$scope.clicked = function() {
console.log("Clicked Me");
};
$scope.secondclick = function() {
console.log("Button Clicked")
}
});
.container {
width: 100%;
height: 300px;
background: cyan;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<div class="container" ng-click="clicked()">
<button ng-click="secondclick()">Click Me</button>
</div>
</div>
I implementing infinite scroll in my web app using angularjs. I found this useful directive on net Infinite Scroll, but the problem is this can only be implemented inside div not in the scroll bar body:
app.directive('infinityscroll', function () {
return {
restrict: 'A',
link: function (scope, element, attrs) {
element.bind('scroll', function () {
if ((element[0].scrollTop + element[0].offsetHeight) == element[0].scrollHeight) {
//scroll reach to end
scope.$apply(attrs.infinityscroll)
}
});
}
}
});
Here is my html codes:
<div infinityscroll="NextPage()" style="height:700px; overflow:auto;" >
<div ng-repeat="item in listItems">
<img ng-src="{{item.picture}}" alt="broken" style="">
</div>
</div>
when i remove the inline css it won't work.so how can i change the infinite scroll in the body instead of div?
Try this:
<body infinityscroll="NextPage()" style="height: 1000px; overflow:auto;">
and remove infinitescroll initialization from your div.
You might need to adjust height a bit, based on your screen-size.
Hope this solves your issue.. :)
Here, I would like to select the .accept element from within the .header element. Is this possible? The documentation is inconclusive and I have tried some variations to no avail, is there a trick I'm not aware of?
'click .header .accept': function (event) { ... },
In jQuery I might use this: $('.header .accept')
What you shared will work assuming you don't have a conflict elsewhere. Try using the code below. The event fires only if you click the second div, as you want.
template:
<body>
{{> page}}
</body>
<template name="page">
<div class="header">.header
<div class="accept">.header .accept</div>
</div>
</template>
js:
if (Meteor.isClient) {
Template.page.events({
'click .header .accept': function(event) {
console.log('accept clicked');
}
});
}
jQuery
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
$('.box').bind('mousedown', function(){
alert('box class clicked');
});
angular
<div ng-app="myApp" >
<div data-ng-controller="myCtrl">
<div ng-click="boxClick()" class="box"></div>
<div ng-click="boxClick()" class="box"></div>
<div ng-click="boxClick()" class="box"></div>
</div>
</div>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.boxClick = function(){
alert('box class clicked');
}
});
Now I am learning AngularJS, if we see this, short and crispy will be jQuery, for a single click event we are writing these much of line code in AngularJS, can anyone help me to write short as much as jQuery, how to select DOM element in AngularJS like jQuery, I am using ng-click to trigger click event in AngularJS, without that can I able to trigger click event in script tag itself. Thanks for replies in advance
You can do it by using directive. this is a standard way in angularjs for this kind of situation.
The sample look like
var app = angular.module('myApp', []);
app.directive('myDomDirective', function () {
return {
link: function ($scope, element, attrs) {
element.bind('click', function () {
alert('You clicked me!');
});
element.bind('mouseenter', function () {
alert('You mouse entered me!');
});
element.bind('mouseleave', function () {
alert('You mouse leaved me!');
});
}
};
});
app.controller('myCtrl', function($scope) {
// do what you want like service calls and binding
});
then call the directives in your any tag
<div ng-app="myApp" >
<div data-ng-controller="myCtrl">
<div my-dom-directive class="box"></div>
<div my-dom-directive class="box"></div>
<div my-dom-directive class="box"></div>
</div>
</div>
Please take a look at this document for more details
Some of the things i want you to notice that when you are working on DOM objects then it is better to do all the stuff in angular directives. As suggested in the answer.
i have created a demo and used this way:
<div ng-app="myApp" >
<div data-ng-controller="myCtrl">
<div ng-btn class="box">Btn1</div>
<div ng-btn class="box">Btn2</div>
<div ng-btn class="box">Btn3</div>
</div>
</div>
and controller in app.js:
app.controller('myCtrl', function($scope) {
$scope.boxClick = function(){ alert('clicked'); };
});
and directive in the app.js:
app.directive('ngBtn', function(){
return {
link:function(scope, element, attrs){
angular.element(element).on('click', scope.boxClick);
}
};
});
Check this sample demo at plunkr
In this answer you can see we have a controller myCtrl in the js and function boxClick is in the $scope of current controller, which alerts a message.
Now if you see the markup you can see a directive named ng-btn which we have used in the directive with the camelCase naming convention in angular with ngBtn in the module.
Now in the directive you can see it returns an object which links to a callback function with three params (scope, element, attrs), where scope is the current controller's scope, element is the one which has the ng-btn attribute. Now using jqLite in the angular.element() you can bind the event on the element and you can see the message poping out.
I recently made a website in AngularJs. I am still in the learning phase.
I wish to fix an element on a page after it reaches the top. I have tried all sorts of Javascript and Jquery functions. However, they don't seem to be working.
I also tried using Angular UI's ui-scrollfix but it is also not working.
I am sharing my code. It is a partial page. Please advise me a method to achieve the above mentioned effect.
<div class="row pdiv">
<div class="col-md-8 pdiv col-md-offset-2">
<h3><b>About Us</b></h3>
<ul class="nav nav-justified">
<li role="presentation">What are we?</li>
<li role="presentation">Brands Associations</li>
<li role="presentation">Know Us</li>
<li role="presentation">Our Motto</li>
</ul>
</div>
<div id="weAre" class="col-md-8 pdiv col-md-offset-2">
<br>
<h4><b>What are we?</b></h4>
<p>Some content goes here.</p>
<br>
<br>
<br>
<br>
<br>
<br>
</div>
<div id="brandsAssociation" class="col-md-8 pdiv col-md-offset-2">
<br>
<h4><b>Brands Associations</b></h4>
<p>Some content goes here.</p>
<br>
<br>
<br>
<br>
<br>
<br>
</div>
<div id="knowUs" class="col-md-8 pdiv col-md-offset-2">
<br>
<h4><b>Know Us</b></h4>
<p>Some content goes here.</p>
<br>
<br>
<br>
<br>
<br>
<br>
</div>
<div id="motto" class="col-md-8 pdiv col-md-offset-2">
<br>
<h4><b>Our Motto</b></h4>
<p>Some content goes here.</p>
<br>
<br>
<br>
<br>
<br>
<br>
</div>
</div>
<span id="toTop" class="glyphicon glyphicon-chevron-up"></span>
I need to fix the ul class .nav .nav-justified after it hits the top of the page.
I am using bootstrap.
here are the javascript dependencies.
<script src="angular/angular.min.js"></script>
<script src="angular/angular-route.js"></script>
<script src="js/jquery.js"></script>
<script src="js/bootstrap.min.js"></script>
Please help...
To fix your ul to the top when it hits the top of the page on scroll, you can put a directive on it that checks for the window's scrollTop() exceeding the ul element's offset top. When that occurs, the directive can just add a class to the element that fixes it to the top.
So your ul markup would look like this, with new directive set-class-when-at-top on it:
<ul class="nav nav-justified" set-class-when-at-top="fix-to-top">
That directive would add the CSS class fix-to-top to the element when the element hits the top of the page. The directive definition would look like this:
app.directive('setClassWhenAtTop', function ($window) {
var $win = angular.element($window); // wrap window object as jQuery object
return {
restrict: 'A',
link: function (scope, element, attrs) {
var topClass = attrs.setClassWhenAtTop, // get CSS class from directive's attribute value
offsetTop = element.offset().top; // get element's offset top relative to document
$win.on('scroll', function (e) {
if ($win.scrollTop() >= offsetTop) {
element.addClass(topClass);
} else {
element.removeClass(topClass);
}
});
}
};
});
If you wanted to get a bit cheeky, you could even reduce your scroll handler to just one line:
$win.on('scroll', function (e) {
element[($win.scrollTop() >= offsetTop) ? 'addClass' : 'removeClass'](topClass);
});
And the fix-to-top CSS class would just be something like this:
.fix-to-top {
position: fixed;
top: 0;
}
Here's a fiddle.
I started using MikeJ's great answer to get started, but quickly realized a few shortcomings:
Didn't account for when content above the element changes dynamically after the directive is first parsed
Content below the fixed element moved up the height of the element when it became fixed and was removed from the normal document flow
If this element is being fixed below something else (like a top menu) you may have some trouble calculating the right spot; you need to fix it before the offset top is past where the $win.scrollTop() is, so that it doesn't disappear behind that menu and then get fixed after.
To fix these, I came up with a modified version:
function setClassWhenAtTop($window) {
var $win = angular.element($window);
return {
restrict: "A",
link: function (scope, element, attrs) {
var topClass = attrs.setClassWhenAtTop,
topPadding = parseInt(attrs.paddingWhenAtTop, 10),
parent = element.parent(),
offsetTop;
$win.on("scroll", function () {
// dynamic page layout so have to recalculate every time;
// take offset of parent because after the element gets fixed
// it now has a different offset from the top
offsetTop = parent.offset().top - topPadding;
if ($win.scrollTop() >= offsetTop) {
element.addClass(topClass);
parent.height(element.height());
} else {
element.removeClass(topClass);
parent.css("height", null);
}
});
}
};
}
This requires the element you are fixing to be wrapped in an empty parent that only contains the element to fix. This is to handle both knowing where the original offset of the element was (for putting it back into the document flow) and to have the height of the original element to keep the document flow as it was. In addition, pass in an attribute for paddingWhenAtTop to fix it sooner (or later if desired).
Usage in the HTML changes like so:
<div>
<ul class="nav nav-justified" set-class-when-at-top="fix-to-top" padding-when-at-top="50">
</div>
Here is my attempt to make it full angularjs :
JS
.directive('setClassWhenAtTop', ['$window', function($window) {
var $win = angular.element($window); // wrap window object as jQuery object
return {
restrict: 'A',
link: function (scope, element, attrs)
{
var topClass = attrs.setClassWhenAtTop, // get CSS class from directive's attribute value
topPadding = parseInt(attrs.paddingWhenAtTop, 10),
offsetTop = element.prop('offsetTop'); // get element's offset top relative to document
$win.on('scroll', function (e) {
if ($window.pageYOffset + topPadding >= offsetTop) {
element.addClass(topClass);
} else {
element.removeClass(topClass);
}
});
}
};
}])
CSS
.fix-to-top {
position: fixed;
top: 55px;
height: 50px;
z-index: 999;
width: 100%;
}
HTML
<div class="navigation-bar" set-class-when-at-top="fix-to-top" padding-when-at-top="55">
...
Main changes to skip jquery :
parent.offset().top => element.prop('offsetTop')
$win.scrollTop() => $window.pageYOffset
Tip of the day :
Would you please stop always giving angularjs title questions jquery answers ! Or at least indicate it clearly in your title or in your answer requirements ;-)