I have a problem with a button which contacts server on click. If you do a double click (or any number of clicks for that matter) you will call the server that number of times.
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'ADMIN.CONTENT.DELIVERIES.BODY.CLOSE' | translate }}</button>
<a class="btn btn-danger" ng-click="vm.markDelivered()" ng-dblclick="return" ng-disabled="flag">{{ 'MANAGER.CONTENT.DELIVERIES.BODY.DELETE_PANEL.CONFIRM' | translate }}</a>
</div>
I have tried with ng-disabled but for some reason it doesn't work, as it is saying that that element is not allowed there. I tried changing a to button, but that seems the same. ng-dblclick="return" does nothing also.
Even I had the same issue,And solved using this approach.
<div class="col-sm-4 form-group pull-right">
<input type="submit" name="Submit" class="btn btn-primary"
value="Submit" data-ng-disabled="myForm.$invalid"
ng-click="myForm.$invalid=true;vm.markDelivered()" />
</div>
So on first click myForm.$invalid=true will be set and button will be disabled. SO you will not have multiple calls to your server side code.
So with Bootstrap buttons you won't be able to use ng-disabled. You would have to do it this way:
<div class="btn btn-default" ng-class="{'disabled': idDisabled}" ng-click="doSomething()">I'm a button!</div>
where you are setting the class disabled on the button. But this does not disable the action itself. So when the button is pressed you would need to check that isDisabled variable and if it is true just return and don't do the intended action.
So for example:
doSomething() {
if (isDisabled) {
return
} else {
// do your server call
// when call is finished set isDisabled = false
}
}
I see a couple of issues here.
First, change the anchor tag to a button.
Second, you seem to be using 'controller as' syntax. So, you are probably setting your flag in the vm. But, in your html, you are looking for the flag in the $scope. Change ng-disabled="flag" to ng-disabled="vm.flag"
Your final button line would look like this:
<button class="btn btn-danger" ng-click="vm.markDelivered()" ng-dblclick="return" ng-disabled="vm.flag">{{ 'MANAGER.CONTENT.DELIVERIES.BODY.DELETE_PANEL.CONFIRM' | translate }}</button>
Adding a working plunker here demonstrating ng-disabled
What about using a simple behaviour directive?
function oneTimeCallDirective($timeout) {
var httpCallMock = (cb = () => 'ok') => $timeout(cb, 5000);
return function oneTimeCallPostLink(iScope, iElement) {
let busy = false;
return iElement
.on('click dblclick', function(event) {
if(busy) {
return event.preventDefault();
}
busy = true;
console.info('Well, Calling.');
return httpCallMock()
.then(() => {
console.log('You Can Start Calling Again');
})
.finally(() => {
busy = false;
})
;
})
;
};
}
angular
.module('test', [])
.directive('oneTimeCall', oneTimeCallDirective)
;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<section ng-app="test">
<button one-time-call>Click Here</button>
</section>
Related
I have one div, initially it is hidden. But on click of the button i am showing it using angular ng-show directive. After showing for 2 seconds i want to hide it. How to do it using angular or css anyone is ok.
HTML code
<div class="subcontent tinyUrlContainer">
<span class="slabel col-md-2">WAP Link :</span>
<div class="input-group col-md-6">
<input type="text" ng-model="wapLink" class="form-control">
<span class="input-group-btn" my-Tooltip>
<button type="button" class="btn btn-default" clipboard supported="supported" text="wapLink" ng-click="clipboard=true" on-error="fail(err)"><img class="clippy" src="./images/surveys/tinyUrl.png" width="13" alt="Copy to clipboard" data-pin-nopin="true"></button>
</span>
</div>
</div>
<span class="copied col-md-offset-6 col-lg-offset-5 col-md-1" ng-show="clipboard">Copied!</span>
on click of the button am setting the clipboard as true and in .copied class element ng-show="clipboard" am setting.
On HTML
ng-show=someCondition()
On your controller
var show = false;
function someCondition(){
return show;
}
function onClick(){
show = true;
$timeout(function(){
show= false
}, 2000);
}
$scope.theClickFunction(){
$scope.theShowFlag = true;
$timeout(function(){
$scope.theShowFlag = false;
}, 2000);
}
I have the following directive
app.directive('replybox', function ($timeout, $window, $compile, $sce) {
var linkFn = function (scope, element, attrs) {
var exampleText= element.find('p');
var btn = element.find('button');
var windowSelection="";
scope.okOrCancel="None";
exampleText.bind("mouseup", function () {
scope.sel = window.getSelection().toString();
windowSelection=window.getSelection().getRangeAt(0);
if(scope.sel.length>0) {
scope.showModal = true;
scope.$apply();
}
});
btn.bind("click", function () {
if(scope.okOrCancel=='ok'){
range = windowSelection;
var replaceText = range.toString();
range.deleteContents();
var div = document.createElement("div");
div.innerHTML = '<poper>' + replaceText + '<button type="button" class="btn btn-danger btn-xs">×</button></poper>';
var frag = document.createDocumentFragment(), child;
while ((child = div.firstChild)) {
frag.appendChild(child);
}
$compile(frag)(scope);
range.insertNode(frag);
scope.showModal=false;
}
if(scope.okOrCancel=='cancel'){
scope.showModal=false;
}
scope.selection="None";
scope.okOrCancel='None';
});
};
return {
link: linkFn,
restrict: 'A',
scope: {
entities: '=',
selection:'='
},
template: `<ng-transclude></ng-transclude>
<div class="modal fade in" style="display: block;" role="dialog" ng-show="showModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
{{sel}}
</div>
<div class="radio">
<div ng-repeat="x in entities">
<div class="radio">
<label>
<input type="radio" name="choice" ng-model="$parent.selection" ng-value = "x">
{{x}}
</label>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" ng-click="okOrCancel='ok'">
Ok
</button>
<button type="button" class="btn btn-primary" ng-click="okOrCancel='cancel'">
Cancel
</button>
</div>
</div>
</div>
</div>`,
transclude: true
};
});
So there is a modal in the template which contains an "Ok" and a "Cancel" button. There is an ng-click on these buttons which sets scope.okOrCancel to the appropriate value. btn binds to a button click and performs different actions depending on the state of scope.okOrCancel. When the "Ok" button is clicked everything works as expected. But the "Cancel" button requires two clicks in order for the modal to dissappear. I would think this would happen immediately within
if(scope.okOrCancel=='cancel'){
scope.showModal=false;
}
Can anyone tell me why the cancel button requires two clicks to close the modal?
Currently you have a mix of jQuery and angularjs for your ok and cancel click. Probably that is the reason to require two clicks to take effect.
If I were you, I would have write click like below:
Template:
<div class="modal-footer">
<button type="button" class="btn btn-primary" ng-click="okClick()"> Ok </button>
<button type="button" class="btn btn-primary" ng-click="cancelClick()"> Cancel </button>
</div>
In JS:
scope.okClick = function() {
range = windowSelection;
var replaceText = range.toString();
range.deleteContents();
var div = document.createElement("div");
div.innerHTML = '<poper>' + replaceText + '<button type="button" class="btn btn-danger btn-xs">×</button></poper>';
var frag = document.createDocumentFragment(), child;
while ((child = div.firstChild)) {
frag.appendChild(child);
}
$compile(frag)(scope);
range.insertNode(frag);
scope.showModal=false;
}
scope.cancelClick = function() {
scope.showModal=false;
}
scope.selection="None";
scope.okOrCancel='None';
I hope this helps you!
Cheers
Completely agree with varit05's answer. Most likely it's because you do not trigger digest cycle in the click event handler. But in any way, the point is: it's not very good idea to mix jquery and angular stuff, unless: a) you absolutely sure it's necessary; b) you understand very well what you're doing and why; otherwise it will lead to such an unexpected consequences.
Just another a small addition. Another problem is here:
$compile(frag)(scope);
range.insertNode(frag);
The correct approach would actually be to insert new nodes into real DOM and only then $compile() them. Otherwise, any directives with require: "^something" in the DOM being inserted will fail to compile because they would not be able to find necessary controllers in upper nodes until new nodes actually make it to the "main" DOM tree. Of course, if you absolutely sure you don't have that then you can leave it as is and it will work... But then the problem will just wait out there for its "finest hour".
I've tried several solutions on other answers but so far none has worked as needed, basically I need to disable a button (anchor) if the form is invalid, disabling is not the problem, avoiding the call to the function is.
For that I tried something like this:
<a class="btn icon-btn btn-success" ng-disabled="myForm.$invalid" novalidate ng-submit="myForm.$valid && submit.addOrEditItem()">
<span class="glyphicon btn-glyphicon glyphicon-save img-circle text-success"></span>Save</a>
And on my controller:
$scope.isCreating = true;
$scope.submit = {
addOrEdit: function() {
if($scope.isCreating){
$scope.items.push({type: $scope.newItem.name, description: $scope.newItem.descriptions, isDone:false, editable:false});
}else{
$scope.eItem.type = $scope.newItem.name;
$scope.eItem.description = $scope.newItem.descriptions;
}
$scope.isCreating = true;
$scope.newItem = {};
}
}
Is there any alternatives for this?
Instead of ng-submit, use ng-click:
<a class="btn icon-btn btn-success" ng-disabled="myForm.$invalid" novalidate ng-click="myForm.$valid && submit.addOrEdit()">
I have the following Modal dialog using ui.boostratp & anuglar modal service
<div id="modalDialog" class="modal-dialog">
<div class="modal-header">
<h2 style="text-align: center">{{modalOptions.headerText}}</h2>
</div>
<div class="modal-body">
<p>{{modalOptions.bodyText}}</p>
</div>
<div class="modal-footer">
<button type="button" class="btn" data-ng-click="modalOptions.close()">{{modalOptions.closeButtonText}}</button>
<button type="button" id="OK" class="btn btn-danger" ng-enter="modalOptions.ok();" autofocus data-ng-click="modalOptions.ok();" data-ng-keyup="$event.keycode == 13 && modaloptions.ok()">{{modalOptions.actionButtonText}}</button>
</div>
</div>
<script type="text/javascript">
$(document).ready(function () {
console.log('Modal Template Loaded');
$('#OK').focus();
$("#modalDialog").keydown(function (event) {
console.log("Event mapped")
if (event.keyCode == 13) {
$(this).parent()
.find("button:eq(0)").trigger("click");
return false;
}
});
}); //document
</script>
I tried out multiple ways, but none of it worked.
after the dialog box loads the 'Modal Template Loaded' is logged to console.
the form works using Mouse though, but want it to work for enter key.
how do i get it working for Enter Key ?
I figured out that the Key event were being captured on the Parent form and not in the dialog box.
So i wrote a JavaScript to trigger click from parent window like shown below.
document.onkeypress = function (e) {
console.log("key Press " + e.keyCode);
if (e.keyCode == 13)
$("#ModalOKButton").trigger("click");
};
You can wrap the modal in form tags and then use ng-submit. Note that you should use ng-submit on its own, without ng-click.
Also see this: Angular-UI $dialog and form submit on enter key
Its loading opening modal and also loading template specified. But not showing anything.
Check out the demo here : http://demo.hupp.in/food-admin
Go to [Products] and Search EnegiKcal >= 3500. Then click on manage. It will open pop up but template content is not loaded.
Also one other thing I noticed is that it returns HTTP 304 for template sometimes.
This is how I open modal :
/** Open Modal For add edit tags */
$scope.open = function (productId) {
var modalInstance = $modal.open({
templateUrl: 'views/some.html',
controller: tagsModalInstanceCtrl,
size: 'lg'
});
modalInstance.result.then(function (msg) {
}, function () {
// $log.info('Modal dismissed at: ' + new Date());
});
};
var tagsModalInstanceCtrl = function ($scope, $modalInstance) {
$scope.ok = function () {
$modalInstance.close("hi");
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
};
Here is template code :
<div class="modal-header">
<h3 class="modal-title">I'm a modal!</h3>
</div>
<div class="modal-body">
<h3>Well, Hello there!</h3>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="ok()">OK</button>
<button class="btn btn-warning" ng-click="cancel()">Cancel</button>
</div>
Ok, it is pretty strange but it seems that your template is based on the master branch of https://github.com/angular-ui/bootstrap/blob/master/template/modal/window.html
and your sources on the tag 0.11.
https://github.com/angular-ui/bootstrap/blob/0.11.0/src/modal/modal.js
It is visible when you type $('.modal-content') in the console, you will see that it needs a modal-transclude directive, but in the sources there is no trace of this directive. Because, on 0.11 it directly uses the ng-transclude directive which is part of angular.
So, your code is correct, but the lib is not, try retrieving a correct version of it (maybe the last build of their repo is broken)
As a matter of fact, I did have a similar problem when switching to angularjs v1.2. The formerly working dialog didn't show, just like yours. Had to change the structure to look something like this to make it visible again:
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<div class="row">
<div class="col-lg-9">
<h3>{{header}}</h3>
</div>
</div>
</div>
<div class="modal-body">
<form name = "kontoForm" szp-focus="sifra">
<!-- Šifra -->
<szp-input id="sifra" text="Šifra" place-holder="šifra" value="konto.sifra" required="!konto.sifra"></szp-input>
<!-- Naziv -->
<szp-input id="naziv" text="Naziv" place-holder="naziv" value="konto.naziv" required="!konto.naziv"></szp-input>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-hide="!kontoForm.$valid || (mode == 'edit')" ng-click="okContinue()">OK i nastavi</button>
<button class="btn btn-primary" ng-hide="!kontoForm.$valid" ng-click="ok()">OK i zatvori</button>
<button class="btn btn-warning" ng-click="cancel()">Odustani</button>
</div>
</div>
</div>
I had to wrap everythin in a div with a modal-content class to make it work.
include .map files for jquery and angular in your /js folder .may be that will help
I have experienced this off and on for some reason as well.
I solved it by adding a CSS statement, after doing an inspection via Chrome's tools I found that for some reason the modal display was still set to hidden.
.modal {
display: block;
}
Take a look this link.
vm_main.showModal = {
mostrarErrores : false,
showModal : function(jsonError) {
var options={
tituloModal: jsonError.titleModal,
textoPrincipal: jsonError.mainMessage,
textoBtnAceptar: "Aceptar",
accionBtnAceptar: "vm_popup.cerrarPopup()",
};
commonPopUpService.getDisclaimerGeneric($scope, 'commonPopUpController', options);
}
};
http://plnkr.co/edit/EYDEG5WSmNwxQflsB21T?p=preview
I think will help you on how load a simple dinamic html as a modal.
Regards