I have a button which on click will save the form information.
The problem is, user instead of clicking 1's on the "Save" button clicks on it multiple times as long as it disappears on the screen. With this, I am saving same form which inturn throw duplicate exceptions.
Please help me. Thanks in advance.
<button ng-click="myFunc()">Save</button>
In above code, myFunc() is triggered with the number of times user clicks.
Use a $scope variable and ng-disabled to update the click and check for the variable,
<button ng-click="myFunc()" ng-disabled="buttonClicked"></button>
Controller
$scope.buttonClicked = true;
I think disable the button after the first click will help you to solve this issue.
That's in case you want this feature related to multiple buttons:
JS:
$scope.disabled = {};
$scope.myFunc = function(identifier) {
$scope.disabled[identifier] = 1;
...
}
HTML:
<button ng-click="myFunc(identifier)" ng-disabled="disabled.identifier"></button>
In case that you want this feature only on one button:
JS:
$scope.disabled = 0;
$scope.myFunc = function() {
$scope.disabled = 1;
...
}
HTML
<button ng-click="myFunc()" ng-disabled="disabled"></button>
You can disable your submit button after the first click to prevent duplicate entry.
For Example, you have HTML something like,
<div ng-app="mydemo" ng-controller="myController">
<button type="submit" ng-disabled="isDisabled" ng-click="myFunc()"> Submit</button>
</div>
angular.module('mydemo', [])
.controller('myController',function($scope){
$scope.isDisabled = false;
$scope.disableButton = function() {
$scope.isDisabled = true; // To disable Button
}
});
This way you can disable button. It will surely work for you. Thanks.
create a directive for this, so that it can be reused
app.directive('clickAndDisable', function() {
return {
scope: {
clickAndDisable: '&'
},
link: function(scope, iElement, iAttrs) {
iElement.bind('click', function() {
iElement.prop('disabled',true);
scope.clickAndDisable().finally(function() {
iElement.prop('disabled',false);
})
});
}
};
});
so use click-and-disable="myFunc()" rather than ng-click
Hiding the form after first click resolved this issue.
Related
I have this in my HTML. Ignore any inline style, I'm testing,
<label class="toggle" style="float: right;">
<input id="check" type="checkbox" ng-model="check" ng-change="funCheck(check)">
<div class="track">
<div class="handle"></div>
</div>
</label>
<div ng-init="fromClock='01:00'; toClock='03:30';">
<clock-editor from="fromClock" to="toClock"
on-change="fromClock = from; toClock = to; funClock(from, to);">
</clock-editor>
<strong>{{fromClock}}</strong>
<strong>{{toClock}}</strong>
</div>
That's a toggle radio button and a clock.
Then I have these two functions in my controller:
$scope.funCheck = function(check) {
alert(check);
};
$scope.funClock = function(f_from, f_to) {
console.log(f_from + "---" +f_to)
$scope.check = false;
}
};
When the toggle is turned on I send the time from the clock somewhere. This works alright. However, what I want to do is uncheck the toggle if the time was changed.
I can do that with document.getElementById('check').checked = false; and the toggle moves back, but the ng-change on that radio won't fire again until I double check it. Like the value didn't change even if I can see how it's turned off visually.
ng-model does not work on strong element and there is no ng-change event for strong element. So basically you can achieve this by using two watch variables like this, Hope this will help you.
$watch(function(){
return $scope.fromClock;
}, function() {
$scope.funCheck();
})
$watch(function(){
return $scope.toClock;
}, function() {
$scope.funCheck();
})
The whole point of using angular is the fact that you shouldn't have to edit the DOM manually like you're doing.
Change this part of your code which unchecks the checkbox
$scope.funClock = function(f_from, f_to) {
if (document.getElementById('check').checked) {
document.getElementById('check').checked = false;
}
};
to
$scope.funClock = function(f_from, f_to) {
if($scope.check){
$scope.check = false;
}
};
Also, you shouldn't care about checking if it's already checked or not as if you set the checked to false and it's already false there will be no change so just remove the if statement completely.
Edit
Seems like ng-change will only fire if there is a change on the input itself and not if that change has happened programmatically, so there are two ways to do this.
Call the change function inside of the funClock.
This would be the code for that
$scope.funClock = function(f_from, f_to) {
if($scope.check){
$scope.check = false;
funCheck($scope.check);
}
};
Add a watch for check.
Or the code for the watch
$scope.$watch('check', function(newValue, oldValue) {
if (newValue != oldValue) {
funCheck(newValue);
}
});
In angularjs , we cann't directly change elements value. we need to
use $compile . First include it in controller and then make use of
it like wise -
var list = '<input id="check" type="checkbox" ng-model="check" checked ng-change="funCheck(check)">';
var selctr = $("#selector");
var ele = angular.element(list);
compiled = $compile(ele);
selctr.html(ele);
compiled($scope);
I'm totally new to angular and I try to use angular-bootstrap-datetimepicker in my project. My html code is:
<span class="input-group-btn" ng-class="{open: openedDP}">
<button type="button" class="btn btn-default btn-sm" ng-click="open()">
<i class="glyphicon glyphicon-calendar"></i>
</button>
<ul class="dropdown-menu" role="menu">
<datetimepicker ng-model="abc"
on-set-time="close(new, old)">
</datetimepicker>
</ul>
</span>
<input id="abc" ng-model="abc" class="form-control" date-time-input="DD-MM-YYYY HH:mm:SS" />
I wanted to close a calendar when user clicks anywhere outside it. I almost copy-pasted the code from ui.bootstrap. Original one is inside directive and looks like this:
var documentClickBind = function(event) {
if (scope.isOpen && event.target !== element[0]) {
scope.$apply(function() {
scope.isOpen = false;
});
}
};
scope.$watch('isOpen', function(value) {
if (value) {
scope.$broadcast('datepicker.focus');
scope.position = appendToBody ? $position.offset(element) : $position.position(element);
scope.position.top = scope.position.top + element.prop('offsetHeight');
$document.bind('click', documentClickBind);
} else {
$document.unbind('click', documentClickBind);
}
});
My version (inside controller):
var documentClickBind = function (event) {
if ($scope.openedDP) {
$scope.$apply(function () {
$scope.openedDP = false;
});
}
};
$scope.$watch('openedDP', function (value) {
if (value) {
$timeout(function() {
$document.bind('click', documentClickBind);
}, 0, false);
} else {
$document.unbind('click', documentClickBind);
}
});
I removed "element" variable because I don't have it in my controller and it seems to work, but I don't know why. Maybe it works just by chance? Why clicking inside calendar is different than clicking anywhere else? In addition I'd like to avoid creating multiple functions like this when I have multiple datepickers on a page.
The behavior you want is built-in to the bootstrap dropdown, if you have bootstrap already in your project you might consider making use of its dropdown.
If not, you could create a custom directive on the page that broadcasts a 'page-clicked' event when the user clicks on another part of the page, then each controller can listen for that event on their scope and react accordingly.
I'm dynamically building a set of checkboxes. Clicking any of the checked boxes should uncheck the first (index wise) checked box. Clicking any of the unchecked boxes should check the last unchecked box.
I'm building the checkboxes using ng-repeat like this:
<input
type="checkbox"
ng-checked="values[$index]"
ng-repeat="n in values track by $index"
ng-click="click($event,$index)" />
And my controller looks like this:
.controller("myCtrl", function ($scope) {
$scope.values = [true,true,true,true];
$scope.click = function (event,n) {
event.preventDefault();
if ($scope.values[n] === true) {
$scope.values[$scope.values.indexOf(true)] = false;
} else {
$scope.values[$scope.values.lastIndexOf(false)] = true;
}
}
Here's a codepen of it all together http://codepen.io/anon/pen/rVLewJ
The problem that I'm running into is that using preventDefault seems to prevent ng-checked from updating the rendering of the box you click on (the others boxes re-render correctly). This causes the display to become out of sync with $scope.values.
Likewise, removing preventDefault doesn't prevent the box you're clicking on from changing its rendering, but (I believe because of ng-repeat's conservative re-rendering) ng-checked doesn't fire so it also gets out of sync.
I'm not using ng-changed because I'm specifically trying to prevent the checkboxes from changing if you're clicking on the "wrong" one. Regardless, I've tried using it instead of ng-clicked and it didn't fix anything.
I've tried using ng-model instead of ng-checked, but that seemed to prevent $scope.values from changing at all. Using $scope.$apply(), didn't help. Some of the things I've read have lead me to think I may need to use $watch but I'm teaching myself Angular with this project so I'm not sure exactly how to apply that.
Update
Nagasimha Iyengar provided a working solution here which I've simplified thusly
<input
type="checkbox"
ng-model="values[$index]"
ng-repeat="n in values track by $index"
ng-change="click($index)" />
Controller:
.controller("myCtrl", function ($scope) {
$scope.values = [true,true,true,true];
$scope.click = function (n) {
if ($scope.values[n] === true) {//clicking on unchecked box
$scope.values[n] = false;
$scope.values[$scope.values.lastIndexOf(false)] = true;
} else {//clicking on checked box
$scope.values[n] = true;
$scope.values[$scope.values.indexOf(true)] = false;
}
}
Codepen: http://codepen.io/anon/pen/zGBKxr
This solution is based on allowing the click event to happen, then undoing it before proceeding with the custom logic. It's certainly a simple solution but feels somewhat improper. Is it the most correct way of solving this problem?
Another small update. I dropped in ngTouch to try and make the app feel a bit quicker on mobile. At least in iOS Safari 8, ngTouch broke this solution. Still works fine on desktop, but the overridden ngClick prevents this solution form working. If you switch back to the original proposed logic it fixes iOS, but of course doesn't work on the desktop. I feel like this confirms my suspicion that the solution was not the correct one.
Here it is - the logic was reversed. And I used $apply with a timeout. Modified codepen: http://codepen.io/nagasimhai/pen/VLjjPe
angular
.module("myApp", [])
.controller("myCtrl", function ($scope) {
$scope.values = [true,true,true,true];
$scope.click = function (event,n) {
//event.preventDefault();
//console.log("b", n, $scope.values,$scope.values.indexOf(true), $scope.values.lastIndexOf(false));
if ($scope.values[n] === true) {//clicking on unchecked box
$scope.values[n] = false;
$scope.values[$scope.values.lastIndexOf(false)] = true;
//console.log("11");
} else {//clicking on checked box
$scope.values[n] = true;
$scope.values[$scope.values.indexOf(true)] = false;
//console.log('22');
}
//console.log("a",n, $scope.values);
setTimeout(function () {
$scope.$apply(function () {
});
}, 2000);
}
});
Your answer was a bit confusing but I believe I'm on the correct path. The problem. What you want to use is event.stopPropagation() to stop the event from propagating. In other words, you only want the event to apply to the specific element. If you use event.preventDefault() it cancels the event if cancelable, without stopping further propagation of the event.
angular
.module("myApp", [])
.controller("myCtrl", function ($scope) {
$scope.values = [true,true,true,true];
$scope.click = function (event,n) {
event.stopPropagation();
if ($scope.values[n] === true) {
$scope.values[$scope.values.indexOf(true)] = false;
$scope.values[n] = false;
} else {
$scope.values[$scope.values.lastIndexOf(false)] = true;
}
}
});
Try the code out at the codepen http://codepen.io/anon/pen/bdepPW
I currently have a lightbox popup attached to a submit button that shows only the first time the submit button is clicked. Basically before someone submits a form, we want them to see this popup when they hit the submit button. And that all works fine, but now I need to make it to where on that first click, the form doesn't submit/process. However, after that first click, the submit button would need to be enabled to where they can submit the form.
Any idea how to change the below code to where the submit button does not process the form only the first time the submit button is clicked?
<script type="text/javascript">
$('#Submitbutton').one("click",function(e) {
$('#lp').lightbox_me({
centered: true,
overlayCSS:{background: '#481d33', opacity: .45},
overlaySpeed:0,
lightboxSpeed:0
});
});
</script>
var hasClicked = false;
$('#Submitbutton').on('click',function(e) {
if (hasClicked === true) {
//submit form here
} else {
e.preventDefault();
hasClicked = true;
$('#lp').lightbox_me({
centered: true,
overlayCSS:{background: '#481d33', opacity: .45},
overlaySpeed:0,
lightboxSpeed:0
});
}
});
Sets a variable on first submit, then on second submit does something different because of that variable.
Edit: Consistent quotes and code cleanup.
Change .on() from .one(). You can declare a variable to track whether button was clicked or not.
var isAlreadytClicked = false;
$('#Submitbutton').on("click", function (e) {
if (isAlreadytClicked == false) {
isAlreadytClicked = true;
return;
}
if (isAlreadytClicked) {
//Do whatever you want on subsequent click
}
});
add the line
$('#SubmitBtn').attr('disabled',false);
inside the if block.
You can use the counter to determine clicked count:
var count = 0;
$('#Submitbutton').click(function(e) {
count++;
if(count==1)
return;//return if clicked first time
$('#lp').lightbox_me({centered: true,overlayCSS:{background: '#481d33', opacity: .45},overlaySpeed:0,lightboxSpeed:0});
});
<input type="button" id="SubmitBtn" value="Submit" onclick="return submitData();" disabled="disabled" >
In Script
//create a global variable for clicked or not
var submitBtnClicked = false;
function submitData()
{
if(submitBtnClicked )
{
$('#SubmitBtn').attr('disabled',false);
submitBtnClicked =true;
}
}
simply a return false should do.
alternatively e.perventDefault() may help for event bubbling.
$('#Submitbutton').one("click",function(e) {
$('#lp').lightbox_me({
centered: true,
overlayCSS:{background: '#481d33', opacity: .45},
overlaySpeed:0,
lightboxSpeed:0
});
e.perventDefault();
return false;
});
While working on basic angular examples ng-click is not working as expected
the following is my html code :
<form ng-submit="requestFunding()" ng-controller="StartUpCalculator">
Starting :
<input ng-change='ComputeNeeded()' ng-model='funding.StartingEstimate'>Recommedation : {{needed}}
<button>Fund me</button>
<button ng-click="reset()">Reset</button>
</form>
Javascript code :
function StartUpCalculator($scope)
{
$scope.funding = {
StartingEstimate: 0
};
ComputeNeeded = function ()
{
$scope.needed = $scope.funding.StartingEstimate * 10;
};
$scope.requestFunding = function ()
{
window.alert("Whoa!");
};
}
whenever i click Reset(reset()) button it executes requestFunding function
Thre is no $scope.reset() in controller. You are triggering the ng-submit by clciking the button.
You can change <button> to <button type="button"> so it won't be bound to form submit. By default any button in a form with no type, and no click handler to preventDefault(), will trigger submit, however type="button" will not.
You also need to change ComputeNeeded to $scope.ComputeNeeded if you want it to work with ng-change
Because on ng-submit you are calling requestFunding. Add a new button and call requestFunding from there or else remove reset from form tag and place it putside.