I have a website, where I have multiple buttons. Once a button is pressed I populate a list, though my problem is that the last pressed button keeps to be looking pressed (has the :active class). I thought about using angular's $timeout to reset the button, though the removeClass function doesn't do the trick.
My view looks like this:
div(ng-controller='productButtonController')
div(ng-repeat='product in products')
div.col-md-4
button.btn.btn-block.sell-button(id='{{product._id}}' ng-click='sell()'){{product.name}}
and my controller:
app.controller('productButtonController', ['$scope', '$timeout', 'productServices', 'flash',
function($scope, $timeout, productServices, flash) {
productServices.getProducts()
.success(function(result) {
$scope.products = result.data
})
.error(showErrorMessage(flash))
$scope.sell = function() {
console.log(this.product)
that = this
$('#' + that.product._id).removeClass('active')
}
}
])
Add the angular $window service to your dependencies for the
controller
Call the blur method on the document's active element, which will be
your button.
$window.document.activeElement.blur();
See How do you clear the focus in javascript?.
This code from Justin Poehnelt's handy GIST solves this elegantly.
app.directive('blur', [function () {
return {
restrict: 'A',
link: function (scope, element) {
element.on('click', function () {
element.blur();
});
}
};
}]);
Add the blur attribute to a button/element you need blurred after click. Eg.
<button type="button" blur>Click me</button>
If you simply want to override the focus status of the bootstrap buttons you could do it with:
.btn:focus{
outline: none;
}
Then your buttons should look like:
<button class="btn btn-default">My button 1</button>
It's also important that the stylesheet which overrides the button status is loaded after the bootstrap stylesheet.
EDIT:
Sorry, but the previous step only removes the outline. The background-color of the button still remains the same.
Since bootstrap doesn't append any active classes to the clicked element as far as i know you need to change the :focus status of the button:
$('#' + that.product._id).blur();
Let me know if this works for you.
Related
I am trying to make custom directive in angular .I try to add input field in my view when I click on button .In other words I am trying to make one custom directive in which when user press the button it add one input field in the browser .I think it is too easy if I am not use custom directive Mean If I use only controller then I take one array and push item in array when user click on button and button click is present on controller.
But when need to make custom directive where I will write my button click event in controller or directive
here is my code
http://play.ionic.io/app/23ec466dac1d
angular.module('app', ['ionic']).controller('appcontrl',function($scope){
$scope.data=[]
}).directive('inputbutton',function(){
return {
restrict :'E',
scope:{
data:'='
},
template:'<button>Add input</button> <div ng-repeat="d in data"><input type="text"></div>',
link:function(s,e,a){
e.bind('click',function(){
s.data.push({})
})
}
}
})
I just need to add input field when user click on button using custom directive ..could you please tell me where i am doing wrong ?
can we make button template and click event inside the directive
The reason it doesn't work is because your registering your click handler with jQuery. So when the click handler fires it is out of the scope of angular so angular does not know it needs to update its bindings.
So you have two options, the first is to tell angular in the click handler, 'yo buddy, update your bindings'. this is done using $scope.$apply
$apply docs: https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$apply
e.bind('click',function(){
s.$apply(function() {
s.data.push({});
});
});
However angular already has built in directive for handling things like mouse clicks you can just use that and let angular do the work for you. This would be the better option.
so first in your view register a click handler on your button
<button ng-click="add()">Add input</button> <div ng-repeat="d in data"><input type="text"></div>
Then in your link simply add the add() method of your scope
s.add = function () {
s.data.push({});
}
Heres a working fiddle showing both examples. http://jsfiddle.net/3dgdrvkq/
EDIT: Also noticed a slight bug in your initial click handler. You registering a click but not specifying the button to apply it to. So if you clicked anywhere in the directive, not just the button, the handler would fire. You should be more specific when registering events manually, using ids, class names attributes etc.
The e or element property of the link function is a jqlite or full jQuery object of the entire directive. If you have jQuery included before angular it will be a full jQuery object. If not it will a jqlite object. A thinned out version of jQuery.
Here is a basic example for your logic .
var TestApp = angular.module('App', []);
// controller
TestApp.controller('mainCtrl', function mainCtrl($scope) {
$scope.data = [];
$scope.addDataItem = function () {
$scope.data.push({
someFilield: 'some value'
});
console.log('pushing value ... ');
}
});
// view
<div ng-app="App" class="container" ng-controller="mainCtrl">
<button type="button" ng-click="addDataItem()">Add an input</button>
<div ng-repeat="d in data track by $index">
<custom-directive model="d"></custom-directive>
</div>
</div>
// directive
TestApp.directive('customDirective', function customDirective() {
return {
restrict: 'E',
scope: {
model: '='
},
template: 'item -> <input type = "text" />',
link: function (scope, elem, attrs) {
console.log('scope.model', scope.model);
},
controller: function ($scope) {
// do staff here
}
}
});
I am using ionic to build an app. I've written a global img directive that displays an alert box whenever an img is loaded. The problem I am facing is this directive is called for all views, but if I display an image inside an ionic-modal, the directive is not called.
My directive code is:
.directive('img', function () {
return {
restrict: 'E',
link: function (scope, element, attrs) {
console.log ("********** IMG DIRECTIVE ");
}
}
})
I've added a codepen here so you can see what is going on. It's a fork from a standard ionic modal example, so has some redundant code.
http://codepen.io/asker/pen/YXXyZj?editors=101
a) Click on the link at the bottom of the home page that says "CLICK ON IMAGE TO SEE DIRECTIVE" and you will see just before the image loads, the directive alert displays
b) Click on "Sign In" on home page and in the next page, click "Open Modal" button - and you will see the image show up but my directive not called
Thanks
I think it is because your img directive is called when you click "Sign In", the home tab loaded the modal.html in your HomeTabCtrl before you click "Open Modal".
You can make changes like following:
Changes to home.html: use ng-click="openModal()" instead of ng-click="modal.show()"
Changes to HomeTabCtrl:
$scope.openModal = function(){
$ionicModal.fromTemplateUrl('modal.html', function($ionicModal) {
$ionicModal.show();
}, {
// Use our scope for the scope of the modal to keep it simple
scope: $scope,
// The animation we want to use for the modal entrance
animation: 'slide-in-up'
}); }
I am using the angular modal service and I am trying to implement some keypress functionality for a smooth UX.
<button type="button" autofocus ng-click="close('Yes')" class="btn btn-primary" data-dismiss="modal">Yes</button>
The problem is that when the modal pops up, it doesn't have focus. Focus remains on the button clicked to activate the modal.
Is there some way to reset autofocus without reloading the page? Or is there some way to grab focus when the modal activates, but have it do so each time the modal opens?
I tried implementing the focus service as described in the answer to this post, but I couldn't get it to work with the modal.
Here is a plunker that demonstrates the behavior:
Plunker
Here is the working demo:
Plunker
I ended up finding this example:
Programmatically Setting Focus
It accomplishes it with a directive on whatever element you want to get focus:
app.directive('syncFocusWith', function($timeout, $rootScope) {
return {
restrict: 'A',
scope: {
focusValue: "=syncFocusWith"
},
link: function($scope, $element, attrs) {
$scope.$watch("focusValue", function(currentValue, previousValue) {
if (currentValue === true && !previousValue) {
$element[0].focus();
} else if (currentValue === false && previousValue) {
$element[0].blur();
}
})
}
}
});
Getting it to work for my modal was easy. I just added this little timeout function to the modal's controller, giving it a half a second to display the modal before trying to set the focus:
$timeout(function() {
$scope.isFocused = true;
},500)
and this attribute on the element we want to get focus:
sync-focus-with="isFocused"
I am trying to use class directive to attach click event to the next page button on the kendo grid.
Directive:
.directive('kPagerNav', function () {
return {
restrict: 'C',
controller: function ($scope, $element, $attrs, $location) {
if (typeof $scope.testFunc === "function") {
$element.click(function () {
$scope.testFunc();
});
}
}
}
})
Example
http://dojo.telerik.com/AKiqO
I have exactly the same directive working for a 'cancel changes' button , but I can't get next page click working.
I think that the directives do not work because the pager is updated asynchronously, and the arrows do not match the directive CSS class at compilation time.
I'm trying to make a directive angularJS directive for Twitter Bootstrap Modal.
var demoApp = angular.module('demoApp', []);
demoApp.controller('DialogDemoCtrl', function AutocompleteDemoCtrl($scope) {
$scope.Langs = [
{Id:"1", Name:"ActionScript"},
{Id:"2", Name:"AppleScript"},
{Id:"3", Name:"Asp"},
{Id:"4", Name:"BASIC"},
{Id:"5", Name:"C"},
{Id:"6", Name:"C++"}
];
$scope.confirm = function (id) {
console.log(id);
var item = $scope.Langs.filter(function (item) { return item.Id == id })[0];
var index = $scope.Langs.indexOf(item);
$scope.Langs.splice(index, 1);
};
});
demoApp.directive('modal', function ($compile, $timeout) {
var modalTemplate = angular.element("<div id='{{modalId}}' class='modal' style='display:none' tabindex='-1' role='dialog' aria-labelledby='myModalLabel' aria-hidden='true'><div class='modal-header'><h3 id='myModalLabel'>{{modalHeaderText}}</h3></div><div class='modal-body'><p>{{modalBodyText}}</p></div><div class='modal-footer'><a class='{{cancelButtonClass}}' data-dismiss='modal' aria-hidden='true'>{{cancelButtonText}}</a><a ng-click='handler()' class='{{confirmButtonClas}}'>{{confirmButtonText}}</a></div></div>");
var linkTemplate = "<a href='#{{modalId}}' id= role='button' data-toggle='modal' class='btn small_link_button'>{{linkTitle}}</a>"
var linker = function (scope, element, attrs) {
scope.confirmButtonText = attrs.confirmButtonText;
scope.cancelButtonText = attrs.cancelButtonText;
scope.modalHeaderText = attrs.modalHeaderText;
scope.modalBodyText = attrs.modalBodyText;
scope.confirmButtonClass = attrs.confirmButtonClass;
scope.cancelButtonClass = attrs.cancelButtonClass;
scope.modalId = attrs.modalId;
scope.linkTitle = attrs.linkTitle;
$compile(element.contents())(scope);
var newTemplate = $compile(modalTemplate)(scope);
$(newTemplate).appendTo('body');
$("#" + scope.modalId).modal({
backdrop: false,
show: false
});
}
var controller = function ($scope) {
$scope.handler = function () {
$timeout(function () {
$("#"+ $scope.modalId).modal('hide');
$scope.confirm();
});
}
}
return {
restrict: "E",
rep1ace: true,
link: linker,
controller: controller,
template: linkTemplate
scope: {
confirm: '&'
}
};
});
Here is JsFiddle example http://jsfiddle.net/okolobaxa/unyh4/15/
But handler() function runs as many times as directives on page. Why? What is the right way?
I've found that just using twitter bootstrap modals the way the twitter bootstrap docs say to is enough to get them working.
I am using a modal to house a user edit form on my admin page. The button I use to launch it has an ng-click attribute that passes the user ID to a function of that scope, which in turn passes that off to a service. The contents of the modal is tied to its own controller that listens for changes from the service and updates values to display on the form.
So.. the ng-click attribute is actually only passing data off, the modal is still triggered with the data-toggle and href tags. As for the content of the modal itself, that's a partial. So, I have multiple buttons on the page that all trigger the single instance of the modal that's in the markup, and depending on the button clicked, the values on the form in that modal are different.
I'll take a look at my code and see if I can pull any of it out to build a plnkr demo.
EDIT:
I've thrown together a quick plunker demo illustrating essentially what I'm using in my app: http://embed.plnkr.co/iqVl0Wb57rmKymza7AlI/preview
Bonus, it's got some tests to ensure two password fields match (or highlights them as errored), and disables the submit button if the passwords don't match, or for new users username and password fields are empty. Of course, save doesn't do anything, since it's just a demo.
Enjoy.
There is a working native implementation in AngularStrap for Bootstrap3 that leverages ngAnimate from AngularJS v1.2+
Demo : http://mgcrea.github.io/angular-strap/##modals
You may also want to checkout:
Source : https://github.com/mgcrea/angular-strap/blob/master/src/modal/modal.js
Plunkr : http://plnkr.co/edit/vFslNmBAoKPVXtdmBXgv?p=preview
Well, unless you want to reinvent this, otherwise I think there is already a solution.
Check out this from AngularUI. It runs without twitter bootstrap.
I know it might be late but i started trying to figure out why the handler got called several times as an exercise and I couldn't stop until done :P
The reason was simply that each div you created for each modal had no unique id, once I fixed that everything started working. Don't ask me as to what the exact reason for this is though, probably has something to do with the $('#' + scope.modalId).modal() call.
Just though I should post my finding if someone else is trying to figure this out :)