Hi I'm adding a popover to UI grid in AngularJS. The idea is when the user mouse-over a row a popover will show up, and the popover contains a directive. I've successfully implemented this part, but now the problem is that part of the popover is blocked by the ui grid table, like this:
I want to bring the popover to the front, and I've tried setting z-index for both the ui grid table and the popover. Related code is here:
JS part:
function rowTemplate() {
var template = [];
...
template.push('popover-template="\'popover.html\'" popover-placement="bottom" popover-trigger="click"></div>');
return template.join(' ' );
}
HTML:
<div class="gridStyle" ui-grid="vm.grid" ui-grid-resize-column ui-grid-selection style="margin-top:0px; height:200px; z-index: 4; position: relative">
</div>
<script type="text/ng-template" id="popover.html">
<div style="height: 150px; width: 600px; overflow-x: auto; overflow-y: hidden; z-index: 10; position: relative">
<directive-related part />
</div>
</script>
But after I set the z-index it's still not working. How can I resolve this?
Some of my references are here: popover: popover, z-index: z-index.
Thanks!
Note: I am making the assumption here that you are using ui-bootstrap.
I have found that usually you need to use the append-to-body attribute with ui-grid custom formats.
Try changing the template like so to add that attribute:
template.push('popover-template="\'popover.html\'" popover-append-to-body="true" popover-placement="bottom" popover-trigger="click"></div>')
I am using ng-dialog to display the popup. The problem i am facing with ng-dialog is there is no vertical scroll bar on the dialog box when the message is huge but scroll bar appearing for the entire html page.
Is there a way i can bring the scroll bar on the ng-dialog box.
I am using the ngdialog.js from https://github.com/likeastore/ngDialog
I googled my best but not getting any idea about how to bring the scrollbar. Please i am just bigger in the css.
below is the code which i am using to bring the popup.
ngDialog.open({ template: 'resources/views/popup.html', className: 'ngdialog-theme-default' , scope: $scope });
any suggestion much appreciated.
You should set overflow-y: scroll; on your content element within your dialog template.
HTML:
<div class="modal-content">
<ul class="list-group">
<li class="list-group-item" ng-repeat="item in items">{{::item.name}}</li>
</ul>
LESS:
.modal-content {
.choose-modal-content {
height: 100%;
width: 100%;
ul {
&.list-group {
overflow-y: scroll;
}
}
}
}
This way the ul will be scrollable when the content overflows.
Trying hard to implement the Formstone Wallpaper JQuery plugin into my AngularJS application. I followed the instructions on the site just to learn that AngularJS and JQuery don't work well together. In many articles in the net it was mentioned that I had to wrap jquery plugins in AngularJS directives to use it the right way. I found this tutorial by David Boike on how to warp the Knob jquery plugin into an AngularJS directive.
I tried to follow along and achieve that for the Formstone Wallpaper plugin. This is my attempt:
'use strict';
angular.module('app').directive('formstoneWallpaper',[function() {
return {
restrict: 'E',
link: function (scope, elem, attrs) {
elem.wallpaper({
source: {
poster: attrs.poster,
mp4: attrs.mp4,
ogg: attrs.ogg,
webm: attrs.webm
}
});
}
};
}]);
Then my html markup changes to:
<div class="container-fluid">
<div class="row wall">
<formstone-wallpaper
poster="modules/launch/videos/ocean.jpg"
mp4="modules/launch/videos/ocean.mp4"
ogg="modules/launch/videos/ocean.ogv"
webm="modules/launch/videos/ocean.webm"
></formstone-wallpaper>
</div><!--row-->
</div><!--container-->
Yet this does not result in the desired full-width responsive video wallpaper. Instead the width and height is somehow set to 0px. I therefore do not see anything on my website. However, when I kill the wallpaper-container and wallpaper-media classes, the problem is partially resolved in that the video finally appears (however, it is not responsive and fittet to screen size-the reason why we are doing this exercise in the first place). Here is a screenshot from my chrome inspector.
Can someone help me to improve the code for the directive?
friends, it turned out the above directive is actually alright. The real problem that I had was my lack of understanding of nested relative positioning. I used this "resize" directive to dynamically set the height of my container to the height of the viewport.
This is the css that finally fixes the my issue:
formstone-wallpaper {
display: block;
position: relative;
width: auto;
height: auto;
padding: 100px 0;
min-height: 100%;
background: no-repeat center center;
background-attachment: scroll;
background-size: cover;
}
Set the "resize" attribute on your container like so:
<div class="container-fluid" data-ng-style="style()" resize>
<div class="row">
<formstone-wallpaper
poster="modules/launch/videos/ocean.jpg"
mp4="modules/launch/videos/ocean.mp4"
ogg="modules/launch/videos/ocean.ogv"
webm="modules/launch/videos/ocean.webm"
></formstone-wallpaper>
</div><!--row-->
</div><!--container-->
I've created a JSFiddle demonstration of a problem I've been facing, where my template-expanding directives are not functioning correctly.
In the JSFiddle, there are three buttons, where each toggles a different colored box.
redBox {
height: 50px;
width: 50px;
background-color: red;
border: 2px solid black;
}
// etc, etc.
Clicking a button toggles the display of one of the colored boxes.
<body ng-app="boxApp">
<div ng-controller="NavCtrl">
<nav>
<button ng-click="shownSection = 'red'">Show red box</button>
<button ng-click="shownSection = 'blue'">Show blue box</button>
<button ng-click="shownSection = 'green'">Show green box</button>
</nav>
<article>
<redBox ng-show="shownSection == 'red'"></redBox>
<blueBox ng-show="shownSection == 'blue'"></blueBox>
<greenBox ng-show="shownSection == 'green'"></greenBox>
</article>
</div>
</body>
Lastly, each fooBox element corresponds to an AngularJS directive that I would like to create a new DOM element based on a simple template.
var app = angular.module("boxApp", []);
app.controller("NavCtrl", function ($scope) {
$scope.shownSection = "";
});
app.directive('redBox', function() {
return {
restrict: "E",
template: '<div>red box</div>',
}
});
app.directive('greenBox', function() {
return {
// etc.
}
});
It doesn't work. In fact, the application behaves the same way regardless of whether or not I define the directives in the first place: it toggles each DOM element as intended, but displays the element as empty - ignoring the height and width properties but not the border property.
I assumed that the fooBox elements would render on the page because AngularJS would recognize these directives when it initially traverses the DOM, but it doesn't seem to do anything, and I don't get any console errors.
What am I doing incorrectly?
A few things.
You named your directives redBox / blueBox / greenBox the camel-case means a - goes between the letters.
So in the html it needs to look like this:
<red-box />
<blue-box />
<green-box />
Your CSS also needs to change to red-box { }.
Also put display:block; within your CSS for the blocks. That's why the height & width are being ignored.
jsFiddle updated*
What would be the best way to achieve a flip over effect using AngularJS animations?
I would like the flip over effect to occur on click. Every time it's clicked, it should flip over to the other side.
Ideally, I guess, I'm looking for a directive implementation that uses Angular animations.
PLNKR - here is a seed of a configurable angular directive that provides 3d flipping functionality. I do not see any good reason why to use ngAnimate for it.
basic usage
<flip flip-width="200px" flip-height="100px">
<flip-panel>
content-front
</flip-panel>
<flip-panel>
content-back
</flip-panel>
</flip>
Comments
It appends css-styles on its own, to be fully independent.
In a proper, generic directive all names should be configurable.
flip-width and flip-height sets style of flip and both flip-panels.
Directive makes some basic check, if both front and back are set.
First flip-panel is front and the second is back.
Due to usage of transclusion content of the flip-panel may be arbitrary html. (you are right Misha no transclusion needed)
It only works in -webkit. (update to make it work in Firefox, just duplicate all pieces with -webkit with no prefix - you do not need -moz)
UPDATE
PLNKR - here is an updated and extended version. It shows what I meant by making the directive configurable. In more details:
Introduced flipConfig via provider, that allows to set in app.config:
default dimensions
css class names
speed of the transition
if the flip action is triggered by a click on the panel
Introduced flip-show attribute that specifies which side to show.
Changing flip-show we can trigger the flip action from outside of the directive.
It works in Firefox and [almost:-)] in IE11.
(btw: it is just a seed and it may be improved in a lot of ways. E.g: specifying axis, specifying origin of the transform, specifying radius and margin of the panels, allowing flip on hover, defaults colors, margins and so on)
I had the same usecase just recently for an angular memory game.
My implementation is the same by the idea of the other answers. I also released the flipping code along with a DEMO.
Github: https://github.com/zwacky/angular-flippy
P.s.: Looks i'm late to the party ;)
You can use ng-click and ng-class to add a class when the flip container is clicked.
<div class="flip-container" ng-click="flip = !flip" ng-class="{'flip': flip}">
<div class="flipper">
<div class="front" style="background: lightblue;">
front
</div>
<div class="back" style="background: lightgreen;">
back
</div>
</div>
</div>
This is essentially the angular way of doing what Walsh suggested in his article:
Adding the flip class to the container element will flip the card using JavaScript -- no user hover required. A JavaScript comment like document.querySelector("#myCard").classList.toggle("flip") will do the flip!
The only change to David Walsh's css was removing the :hover selector - the html structure is unchanged. It works nicely in chrome and firefox.. but the flip isn't as pretty in IE.
Here is a working demo: http://plnkr.co/edit/0dn775vpuoOeh2PS1T6k?p=preview
Update
I created a simple directive to encapsulate this basic technique. It allows you to flip over a black card, to reveal a picture on the other side.
app.directive("flipReveal", function() {
return {
restrict: 'E',
replace: true,
templateUrl: 'template.html',
scope: {
url: '=',
flip: '='
}
}
})
Here is a link to a new demo: http://plnkr.co/X4pSav
Disclaimer Based on #artur's answer https://stackoverflow.com/a/23139242/1319998 , but hopefully both simplified and made more flexible.
A custom directive is the way to go, one that can be used as:
<flip flip-side="{{side}}">
<flip-front>
Front side contents
</flip-front>
<flip-back>
Rear contents
</flip-back>
</flip>
I think it should have certain properties:
Programatically controlled by an attribute. In this case, a string that is equal to 'front' or 'back'
<flip flip-side="{{side}}">....</flip>
this would allow programmatic access via the surrounding scope.
Integrated with ngAnimate/$animate. Specifically, if ngAnimate is removed or disabled, the animation should not occur, but the reveal of the other side happen immediately. Using $animate.addClass/$animate.removeClass would achieve this, adding/removing a flip-visible class together with display:block and display:none styles to make sure the right side is visible/hidden when the animations are disabled.
flip > flip-front, flip > flip-back {
display: none;
}
flip > .flip-visible {
display: block;
}
Controlled by CSS, with defaults. So if you want to change the duration of the flip, it's a CSS, and not a Javascript, addition.
So it will have a style sheet to add styles required for the various stages of $animate.addClass / $animate.removeClass CSS animations explained at Year of Moo and $animate docs . The class will be flip-visible, so the extra classes will be .flip-visible-add, .flip-visible-add-active, .flip-visible-remove, and .flip-visible-remove-active classes.
The full set of styles can be seen at http://plnkr.co/edit/bbYbMhiURnm6FqC9patp?p=preview, but the main construction is of the form:
.flip-visible-add {
// Initial setup: time and initial, pre-animation, transform
}
.flip-visible-add.flip-visible-add-active {
// Target transform
}
Putting all this together, the directive is quite short:
app.directive("flip", function($animate) {
return {
restrict : "E",
controller: function($scope, $element, $attrs) {
var elements = {
'front': $element.find('flip-front'),
'back': $element.find('flip-back')
};
$attrs.$observe('flipSide', function(visibleSide) {
visibleSide = visibleSide || 'front';
var otherSide = visibleSide == 'front' ? 'back' : 'front';
$animate.removeClass(elements[otherSide], 'flip-visible');
$animate.addClass(elements[visibleSide], 'flip-visible');
});
}
}
});
This can all be seen in an example, together with the stylesheets to make it all work, at http://plnkr.co/edit/bbYbMhiURnm6FqC9patp?p=preview
I realise there is a benefit to not integrating with the $animate service, and having a purely class-based solution.
If you use $animate with addClass and removeClass, but interrupt the animation (say, by clicking quickly and repeatedly on the element), the animation will 'jerk' to its end/starting point, and then animate from that position, at least on Chrome. Using a pure CSS solutions avoids this issue, and always animates from the exact current point, giving a smoother effect.
An added benefit is the solution is also simpler, and you don't need a custom directive.
For example, the HTML can be as follows:
<flip class="{{side === 'front' ? 'flip-front' : 'flip-back'}}">
<flip-front>
Front side contents
</flip-front>
<flip-back>
Rear contents
</flip-back>
</flip>
I use custom elements, but they don't need to have any directives attached: they are just for CSS to hook into:
flip > flip-front, flip > flip-back {
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
/* Time can be overriden */
transition: -webkit-transform 0.5s;
transition: transform 0.5s;
}
/* Front visible */
flip > flip-front {
-webkit-transform: perspective(800px) rotateY(0);
transform: perspective(800px) rotateY(0);
}
flip > flip-back {
-webkit-transform: perspective(800px) rotateY(180deg);
transform: perspective(800px) rotateY(180deg);
}
/* Back visible */
flip.flip-back > flip-front {
-webkit-transform: perspective(800px) rotateY(-180deg);
transform: perspective(800px) rotateY(-180deg);
}
flip.flip-back > flip-back {
-webkit-transform: perspective(800px) rotateY(0);
transform: perspective(800px) rotateY(0);
}
This can be seen in a demo at http://plnkr.co/edit/A7IeGa1JEsZishmTDTaK?p=preview
I would simply add / remove a class on click.
If you want to hook into the angular animation system then take a look at the $animate service, in particular add/remove/setClass(). The service is usually used in directives. You might want to create a directive that reacts on a click event and triggers the animation. You even get informed when the animation has completed.
Chances are that it's not worth it ;)
You are going to want to create 3 divs.
<div class="wrapper">
<div class="front"></div>
<div class="back"></div>
</div>
You then position back behind front using z-index, and flip it upside down using rotateX (-180deg or so). Set a transition on wrapper as well.
Then, on click of wrapper, rotateX(+180deg). This will pretty much infinitely flip it over.
** Update: For angular, bind to click and use setClass to toggle between two classes on wrapper, one at rotateX(0deg) , the other at rotateX(180deg)
Here is a slightly modified version of artur's answer:
DEMO
angular.module('FlipDemo', []).directive("flip", function() {
return {
restrict : "A",
scope: true,
link: function(scope, element) {
var $panels = element.css({ position: 'relative' }).children().addClass("flip-panel");
var frontPanel = $panels.eq(0);
var backPanel = $panels.eq(1);
scope.showFrontPanel = function() {
frontPanel.removeClass("flip-hide-front-panel");
backPanel.addClass("flip-hide-back-panel");
};
scope.showBackPanel = function() {
backPanel.removeClass("flip-hide-back-panel");
frontPanel.addClass("flip-hide-front-panel");
};
scope.showFrontPanel();
}
}
});
.flip-panel {
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-webkit-transition: -webkit-transform .4s;
-moz-transition: -moz-transform .4s;
-webkit-transform: perspective(800px) rotateY(0deg);
-moz-transform: perspective(800px) rotateY(0deg);
}
.flip-hide-back-panel {
-webkit-transform: perspective(800px) rotateY(180deg);
-moz-transform: perspective(800px) rotateY(180deg);
}
.flip-hide-front-panel {
-webkit-transform: perspective(800px) rotateY(-180deg);
-moz-transform: perspective(800px) rotateY(-180deg);
}
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.1/angular.min.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body ng-app="FlipDemo">
<div style="width: 100px; height: 150px">
<div flip style="width: 100%; height: 100%">
<div style="background-color: green">
<div>Front</div>
<button ng-click="showBackPanel()">Show Back</button>
</div>
<div style="background-color: blue">
<div>Back</div>
<button ng-click="showFrontPanel()">Show Front</button>
</div>
</div>
</div>
<br>
<div style="width: 150px; height: 100px">
<div flip style="width: 100%; height: 100%">
<div style="background-color: green">
<div>Front</div>
<button ng-click="showBackPanel()">Show Back</button>
</div>
<div style="background-color: blue">
<div>Back</div>
<button ng-click="showFrontPanel()">Show Front</button>
</div>
</div>
</div>
</body>
</html>
Main differences:
Works in Chrome and Firefox.
More flexibility with when the flip happens.
Just one directive rather than two. Less code.
I took the CSS outside of the directive for clarity sake.