Make a div focused and everything else dark using AngularJS - angularjs

I need this widget for Angular:
https://github.com/zzarcon/focusable
I need to be able to focus a div, make everything outside it dark and not able to click outside. I need to draw my user attention only to the div.
Is that possible?

The best way would be to create a directive which uses the jQuery lib you suggested:
myApp.directive('myFocusableDirective', function() {
return {
link: function(scope, elem) {
Focusable.setFocus(elem);
}
};
});
<div my-focusable-directive>
I AM FOCUSABLE!
</div>

Related

How to hook to "OnOpen" listener for uib-popover?

Context: I am using angular 1 and this UIB Popover control.
Since there is a text field in the popover template I called, my target is to focus on that text field whenever the popover is opened.
Unfortunately, there is no popover listener/event for "onOpen".
So I tried to do a
scope.$watch(()=>{return scope.isOpen}, (obj) ={
// where scope.isOpen is the local var in the popover-is-open
// expecting to write some code here to manipulate the element
// to realise the focus operation
// but there is no popover element yet when this is called
})
I was just wondering what other options I might have?
Thanks
I found nothing on the documentation talked about events and found this issue on the ui-bootstrap github stating that they do not support events nor do they ever plan to implement them. https://github.com/angular-ui/bootstrap/issues/5060
If you're looking for a different option that would give you access to the events would be to implement your own popover directive that simply wraps bootstrap popovers. In theory, they can function the same as the ui-bootstrap and allows you to tap directly into the events provided by bootstrap.
HTML
<div my-popover="Hello World" popover-title="Title" popover-shown="myCallback()">...</div>
JavaScript ('my-popover.directive.js')
angular
.module('myModule')
.directive('myPopover', myPopover);
function myPopover() {
return {
scope: {
popoverTitle: '#',
popoverShown: '&'
},
restrict: 'A',
link: function(scope, elem, attr) {
$(elem).popover({
title: scope.popoverTitle,
content: attr.myPopover
});
$(elem).on('shown.bs.popover', function () {
if(scope.popoverShown && typeof scope.popoverShown === 'function'){
scope.popoverShown();
}
});
}
};
}
Similar to uib-popover, you can add support for additional configurations by adding additional scoped properties.

AngularJS parent div directive wait for children div stacked directives to complete

I have a portion of html that is like this
<div my-custom-security-directive>
<button ng-if={{some constraints}} ng-click={{logic}}>cancel</button>
<button ng-disabled={{some logic}} ng-click={{some logic}}>submit<button>
</div>
My custom security directive does dom manipulation to the buttons to show/hide them via css. The issue I am having is with timing and perhaps directive precedence? When all the code is finished executing I only see the submit button and not the cancel button. I believe this is because of the ng-if and I attempted to set the priority of my custom directive to a negative number to run last but I think that is only for stacked directives on the same element? I only have a link function defined in my directive which my understanding is that is the same as a post link function and should run once the children complete? Ultimately, my goal is to run my directive 'last' so that I can show both buttons if all the logic in the directive passes.
The shell of my directive :
angular.module('myModule')
.directive("myCustomSecurityDirective", function(a,b) {
//
return {
restrict: "A",
priority: -1,
link: function(scope, element, attrs, ctrl) {
//custom security role/perm logic using injected services a&b etc
if (userHasPermission ) {
element.find('input, textarea, button').addClass('my-show-css');
}
}
};
});
I did recently /today put that priority on the directive but I don't think it does anything in this particular scenario.
Even if my-custom-security-directive is able to attach a CSS class to the button and hide or show it, the button has its own ng-if condition. This means it's possible that the button could be destroyed and recreated later, and it wouldn't have the CSS class anymore. If the button uses ng-show instead of ng-if you may have more control, since the button would become hidden but remain in the DOM.
But I think my-custom-security-directive might want to have more control. You can use transclusion so that my-custom-security-directive acts as a container for each set of elements which should be destroyed or created based on userHasPermission.
Directive:
.directive('myCustomSecurityDirective', function () {
return {
transclude: true,
link: function (scope) {
scope.userHasPermission = true;
},
template: '<div ng-if="userHasPermission" ng-transclude></div>'
}
});
HTML:
<div my-custom-security-directive>
<button ng-if="...">cancel</button>
<button ng-disabled="...">submit</button>
</div>

Angular directive to swap ng-click function

I have an app where a person can build lists of 'favorites.' On the page for a particular item there is a button that you can click to add the item to your list of favorites.
What I would like to happen is: Click the button, item is added to favorites, now the button is a different color and if you were to click it again it would remove the item from your favorites.
I think it would be best to build a directive to handle this but I am completely lost.
In my html I have:
<md-button class="md-icon-button" aria-label="Favorite" ng-click="addFavorite(item.id)">
<md-icon md-svg-icon="heart"></md-icon></md-button>
My addFavorite and deleteFavorite functions work correctly, but I can't figure out how to toggle which one happens and how to update that after the request fires.
So lets address a few different things.
Most likely this is going to be a div styled to look like a button to achieve the effect you want. You could go the easy route and use http://getbootstrap.com/css/?#buttons or something else. Styling buttons is just not going to be the best cross browser support.
You could do this entirely with ng-class in a directive, some example code below. Assuming you are using bootstrap. This just becomes what class do you want to change it to kinda thing. Below I have used an icon but the principal is the same.
Directive
.directive('toggleClass', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
element.bind('click', function() {
if(element.attr("class") == "glyphicon glyphicon-pencil") {
element.removeClass("glyphicon glyphicon-pencil");
element.addClass(attrs.toggleClass);
addFavorite(element.id);
} else {
element.removeClass("glyphicon glyphicon-ok");
element.addClass("glyphicon glyphicon-pencil");
removeFavorite(element.id);
}
});
}
};
});
Template
<i class="glyphicon glyphicon-pencil" toggle-class="glyphicon glyphicon-ok"></i>

How to open Jquery Bootstrap Confirm Box on clicking on button using AngularJS

I am new to AngularJS so not aware of events of this. I have a requirement that I have jQuery bootstrap library. I want to open that bootstrap confirmbox when I click on a button and based on ok and cancel want to take further action But want to call using AgularJS
First if at all possible, if you intend to use angular try not to use jQuery functionality, unless it is a last resort.
In order to accomplish what you want you would need to write a angular directive that handles the confirm box and then use it any where you need confirmations. The directive can be setup to further handle actions on ok and cancel. Something similar to this might give you a stating point.
app.directive('ngConfirm', [
function(){
return {
restrict: 'A',
link: function (scope, element, attrs) {
element.bind('click',function () {
var message = attrs.ngConfirmMessage || "Are you sure?"
if (message && confirm(message) ) {
scope.$apply(attrs.ngConfirm)
}
});
}
};
}])
and then in the html
<tag ng-Confirm-Message="Some message" ng-Confirm="someAction()"></tag>

Running code after an AngularJS animation has completed

I have an element whose visibility is toggled by ng-show. I'm also using CSS animations - the automatic ones from ng-animate - on this element to animate its entry.
The element will either contain an image or a video.
In the case that the element contains a video, I want to play it, but I don't want to play the video until it's finished animating in.
As such, I was wondering if there's an easy way to bind a callback to the end of a CSS animation in AngularJS?
The docs reference a doneCallback, but I can't see a way to specify it...
One workaround(?) I have thought of is $watching element.hasClass("ng-hide-add-active") and waiting for it to fire with (true, false), implying it's just been removed..
Is there a nicer way?
#michael-charemza answer worked great for me. If you are using Angular 1.3 they changed the promise a little. I got stuck on this for a little bit but here is the change that got it to work:
if (show) {
$animate.removeClass(element, 'ng-hide').then(scope.afterShow);
}
if (!show) {
$animate.addClass(element, 'ng-hide').then(scope.afterHide);
}
Plunker: Code Example
As #zeroflagL has suggested, a custom directive to replace ngShow is probably the way to go. You can use & to pass callbacks into the directive, which can be called after the animations have finished. For consistency, the animations are done by adding and removing the ng-hide class, which is the same method used by the usual ngShow directive:
app.directive('myShow', function($animate) {
return {
scope: {
'myShow': '=',
'afterShow': '&',
'afterHide': '&'
},
link: function(scope, element) {
scope.$watch('myShow', function(show, oldShow) {
if (show) {
$animate.removeClass(element, 'ng-hide', scope.afterShow);
}
if (!show) {
$animate.addClass(element, 'ng-hide', scope.afterHide);
}
});
}
}
})
Example use of this listening to a scope variable show would be:
<div my-show="show" after-hide="afterHide()" after-show="afterShow()">...</div>
Because this is adding/removing the ng-hide class, the points about animating from the docs about ngShow are still valid, and you need to add display: block !important to the CSS.
You can see an example of this in action at this Plunker.
#michal-charemza solution works great, but the directive creates an isolated scope, so in some cases it cannot be a direct replacement for the default ng-show directive.
I have modified it a bit, so that it does not create any new scopes and can be used interchangeably with the ng-show directive.
app.directive('myShow', function($animate) {
return {
link: function(scope, element, attrs) {
scope.$watch(attrs['myShow'], function(show, oldShow) {
if (show) {
$animate.removeClass(element, 'ng-hide').then(function(){
scope.$apply(attrs['myAfterShow']);
});
} else {
$animate.addClass(element, 'ng-hide').then(function(){
scope.$apply(attrs['myAfterHide']);
});
}
});
}
}
})
Usage:
<div my-show="show" my-after-hide="afterHide()" my-after-show="afterShow()">...</div>
Plunker

Resources