UI Bootstrap control uib-carousel bind to next event - angularjs

I am using the angular-bootstrap's (ui.bootstrap) uib-carousel component with custom template to change the style, text, and functionality of the back and next buttons. I have to perform other actions when the "next" button is touched, in addition to the component's original functionality. Following the method of "capturing" the select event in this answer: How do you Bind to Angular-UI's Carousel Slide Events?, I modified the answer to use the next event.
the html declaration
<uib-carousel template-url="/tpl.html" active="vm.wizardStep" no-wrap="true" on-carousel-next="vm.onNext()" style="height: 395px;">
and the directive like so
.directive('onCarouselNext', function($parse) {
return {
require: '^uibCarousel',
link: function(scope, element, attrs, carouselCtrl) {
var callBack = $parse(attrs.onCarouselNext);
var origNext = carouselCtrl.next;
carouselCtrl.next = function() {
callBack(scope);
return origNext.apply(this, arguments);
};
}
};
});
The uib-carousel's next event does get fired, but it is not calling it through my directive. Just to compare apples to apples, I tried using the code in the answer as-is (i.e. capturing the "select" event), and that does work perfectly and calls my callback function. The reason I need to capture the "next" and can't use the "select" is because I'm using this to set up a "wizard" type framework, and the final "next" is a "done" that needs to do different code.
Anyone done something like this and get it to work?

So seeing as how I was trying to "hijack" the carousel control to turn it in to a wizard control, I ended up just taking the carousel code and changing it completely to fit my needs. If anyone would like to see the code, let me know and I'll put it out on github.

Related

Targeting keydown events to an angularJS custom directive

I am working on a problem wherein I am required to pick-up keydown events (specifically ctrl+p and then point to a print function which already exists) on a certain custom directive and under certain conditions (a certain tab should be selected). My current approach is to bind the keydown event on the document itself, broadcast it and then listen to it in the required custom directive. Following is the code I have placed in the app.run.. block -
angular.element($document).on('keydown', function(evt) {
if(evt.ctrlKey && evt.key==='p'){
$rootScope.$broadcast('printOnKeyPress');
}
});
This part is working as expected, the problem arises when I try to handle it in the required controller of the custom directive as follows:
$scope.$on('printOnKeyPress', function() {
//point to existing print function
}
This is where the problem arises. It goes into the print function but still the output is incorrect. I am missing something and I can't figure out what.
Also, this is not a good approach but I have searched and am unable to find a possible solution to just bind the keydown event on that custom directive itself (the component only appears if a document is selected).
(ng-keydown won't also work here)
Any help is appreciated!
You could put it in the directive and use the scope destroy event to remove the listener.
Within directive link function:
function keyHandler(evt) {
if (evt.ctrlKey && evt.key === 'p') {
// do your print
}
}
angular.element($document).on('keydown', keyHandler);
scope.$on('$destroy', function() {
angular.element($document).off('keydown', keyHandler);
});

How to write a logic when double clicking on page using angularjs

I have a page in which I have a few elements. My scenario is, when I double click on the background i.e., not clicking on any of the elements. I need to go 1 page back using angular. I am pretty new to angular. I am trying to figure out a way to implement. Any suggestions/help is appreciated.
Javascript has a native dblclick event, which is described here.
You'll need to check that the event is coming from the body itself, instead of one of the elements generating an event that then bubbles up to the body.
Try something like this, passing the body as the element:
link: function(scope, element, attrs) {
element.on('dblclick', function(e) {
if(e.target === element){
$window.history.back();
}
});
}

focus on last input ng-repeat

I have been looking at a lot of focus directives, especially those posted here.
But none seem to work for my scenario. I have a tabset and a table inside with an ng-repeat that creates rows with inputs on it. The way I create them is using ng-blur at the end of the last row checkbox so the ng-blur fires the addNewRow method. What I want is to focus the first input on the newly created row but the focus goes to the browser search bar instead.
I created a fiddle to show the problem using a directive from the first posted link.
I tested this directive:
soccerApp.directive('setfocus', function () {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var focus = !! attrs.setfocus && !attrs.setfocus.replace(/true/, '');
if (focus === true) {
//alert(element);
element[0].focus();
}
}
};
});
and the element[0].focus(); actually fires when I create a new row but doesn't set the focus.
Can someone please take a look and tell me what could be wrong?
NOTE: The idea is to use the TAB key to loop through the inputs until the last one.
As Deblaton Jean-Philippe pointed out
The problem is that, at the moment you "tab" from the last input, your browser sets the focus out of the page. So you don't have any control on it anymore. I don't know if it's possible to override that without creating a fake invisible input below to keep the focus into the page
i was missing a fake input so i added a fake at the bottom after my table and it worked

Set focus when another element is clicked or other event occurs

I have a tab-like view on my page and I have a variety of events which need to set the focus to one of the tabs. (showing/hiding the div is easy since I just use a model variable.) The events that cause a div to be focused are clicking on the tab header, data load completion, and initial loading. I know where to intercept all these events, but I'm not sure how I tell the other element to set the focus (none of the intercept sites know about the other element, only about the model).
I've looked around but can't find a good reference for this. I assume I want to listen for some message and post it from the various other locations.
How does one setup this type of messaging event?
ANSWER: I built on the answer and came up with the below directive. It combines both a focus and show state for the div.
newsendApp.directive('showAndFocus', function() {
return {
link: function(scope, element, attr){
scope.$on('SetArticlesListFocus',function() {
if( scope.$eval( attr.showAndFocus ) ) {
$(element).focus();
}
})
scope.$watch(attr.showAndFocus, function(value) {
if( value ) {
$(element).show();
setTimeout( function() { $(element).focus(); }, 0 );
} else {
$(element).hide();
}
})
}
}
});
If an event occurs which may require resetting the focus then I do: $rootScope.$broadcast( 'SetArticlesListFocus' );
You can broadcast an event, and also have listeners that perform an action once such a broadcast has occured.
You can use $scope.$broadcast('changed-tab', objectSentWithBroadcast). The second parameter is an object you can optionally send, like the tab you want to focus on.
Then you would have a listener like this where you can select the tab wanted:
$scope.$on('changed-tab', function(e, objectSentWithBroadcast) {
// do something here to select the tab
});
Have a look at this issue raised in angularjs.
https://github.com/angular/angular.js/issues/1277#issuecomment-16012024
Here is the final plunk that creates a ng-focus directive that manages two way data binding between a variable and an element's focus state.
http://plnkr.co/edit/bntEsfngnJKuneg2raD1
This will allow you to bind a model to an elements focus state and then setting or unsetting this variable will make the element gain / lose focus. You will have to note that if you are using div's etc ( which are non-focusable by default! ) you will need to set tabIndex = -1 on them. Apart from that it should work fine and suit your need for manipulating models pretty well.

Help wrap onClick toggle checkbox into a function

I have a page with 50 hidden checkboxes, and I want to be able to toggle each checkbox by clicking on a visible link. The actual checkboxes have to stay hidden...so... Is there a better way to do this, with a JS function so I don't have to include the entire onclick in each link? And I use mootools, not jQuery.
This works to activate a checkbox:
Select
But to toggle it, this works:
onclick="if (event.target.tagName != 'INPUT') document.getElementById('field_select_temp_professional_10').checked = !document.getElementById('field_select_temp_professional_10').checked"
None of what you posted is actually mootools code, you may as well not use mootools...
Markup:
Select
js in your domready:
document.getElements("a.add_app").addEvents({
click: function(e) {
if (e.target.get("tag") != 'input') {
var checkbox = document.id("field_select_p" + this.get("data-id"));
checkbox.set("checked", !checkbox.get("checked"));
}
}
});
If you have 100+ then I suggest you look at using event delegation from mootools-more and add just one event to the parent instead of creating 100 events and storing 100 functions that deal with it.
This is coding to patterns, and it involves changing your markup to make things work. You can also make the change based upon walking the DOM in relation to the clicked item, e.g. this.getParent().getElement("input[type=checkbox]"), or something can mean you don't need to store a relative id in the element itself.

Resources