In Angularjs / Bootstrap why does my cancel button invoke the submit event - angularjs

I have an Angular / Bootstrap form with a button type=submit and a plain button to cancel - and hide the form. When I click on the cancel, it calls the cancel event handler and then it calls the submit handler. ?? Here's the code as if have it in Plunker: http://plnkr.co/edit/Nsqy4DuVaoI04VObS2Zd?p=preview
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example - example-example33-production</title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.14/angular.min.js"></script>
</head>
<body ng-app="submitExample">
<script>
angular.module('submitExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.list = [];
$scope.text = 'hello';
$scope.cancel = function(){
alert('cancelling');
}
$scope.submitNewAccountForm = function(isValid){
alert('in submit');
}
}]);
</script>
<form ng-controller="ExampleController" name="newAccountForm" ng-submit="submitNewAccountForm(newAccountForm.$valid)" class="form-horizontal" novalidate>
<fieldset>
<!-- Form Name -->
<legend>Account</legend>
<!-- Text input-->
<div class="control-group">
<label class="control-label" for="name">Account name</label>
<div class="controls">
<input ng-model="name" id="name" name="name" type="text" placeholder="account" class="input-medium" required="">
<p class="help-block">Required.</p>
</div>
</div>
<!-- Select Basic -->
<div class="control-group">
<label class="control-label" for="type">Account type</label>
<div class="controls">
<select ng-model="type" id="type" name="type" class="input-medium">
<option>client</option>
<option>provider</option>
</select>
</div>
</div>
<!-- Button (Double) -->
<div class="control-group">
<label class="control-label" for="cancelaccountadd"></label>
<div class="controls">
<button type="submit" id="doaccountadd" name="doaccountadd" class="btn btn-success">Save</button>
<button ng-click="cancel()" id="cancelaccountadd" name="cancelaccountadd" class="btn btn-danger">Cancel</button>
</div>
</div>
</fieldset>
</form>
</body>
</html>

On button elements, submit is the default type attribute. change that to type="button" and it will no longer call the submit event.
Plunker

Related

AngularJS - ng-change only firing once when the page loads

I am writing an app with Angular 1.5. I have a form with a time input.
<div class="item item-input" ng-class="{ 'has-error' : accvm.addForm.time.$invalid }">
<span class="input-label" ng-i18next="TIME"></span>
<input name="time" type="time" max="{{ accvm.data.maxTime | date:'HH:mm' }}" ng-model="accvm.data.time" ng-change="accvm.timeChange()" style="text-align: right" required />
</div>
<div ng-messages="accvm.addForm.time.$error">
<div class="form-error" ng-message="required"><span ng-i18next="VALIDATION_PROJECT"></span></div>
<div class="form-error" ng-message="max"><span ng-i18next="VALIDATION_TIME_FUTURE"></span></div>
</div>
For some reason, the ng-change function is only called once when the page loads and never again even if I type a new value in. I am not sure what I am doing wrong.
Here is my JSFiddle: http://jsfiddle.net/aubz88/j25jwtL2/
ng-change is not firing method due to invalidation. Check this working code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Example - example-date-input-directive-production</title>
<script data-require="angular.js#1.3.15" data-semver="1.3.15" src="https://code.angularjs.org/1.3.15/angular.js"></script>
</head>
<body ng-app="dateInputExample">
<script>
angular.module('dateInputExample', [])
.controller('DateController', ['$scope', function($scope) {
$scope.changed = 0;
$scope.example = {
value: new Date(1999, 0, 1, 15, 30, 0)
};
$scope.change = function(){
$scope.changed ++;
}
}])
</script>
<form name="myForm" ng-controller="DateController as dateCtrl">
<label for="exampleInput">Picktime:</label>
<input type="time" time id="exampleInput" name="input" ng-model="example.value" placeholder="yyyy-MM-dd" required="" ng-change="change();" />
<div role="alert">
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
<span class="error" ng-show="myForm.input.$error.time">
Not a valid date!</span>
</div>
<tt>value = {{example.value | date: "HH:mm"}}</tt>
<br />
<div>The time has been changed
<ng-pluralize count="changed" when="{'0': '{} times.',
'one': '1 time.',
'other': '{} times.'}"></ng-pluralize>
</div>
</form>
<!--<form name="myForm" ng-controller="DateController as accvm">-->
<!-- <div class="item item-input" ng-class="{ 'has-error' : accvm.addForm.time.$invalid }">-->
<!-- <span class="input-label" ng-i18next="TIME"></span>-->
<!-- <input name="time" type="time" ng-model="accvm.data.time" ng-change="accvm.timeChange()" style="text-align: right" required />-->
<!-- </div>-->
<!-- <div ng-messages="accvm.addForm.time.$error">-->
<!-- <div class="form-error" ng-message="required"><span ng-i18next="VALIDATION_PROJECT"></span></div>-->
<!-- <div class="form-error" ng-message="max"><span ng-i18next="VALIDATION_TIME_FUTURE"></span></div>-->
<!-- </div>-->
<!-- {{changed}} {{accvm.addForm.time.$invalid}}-->
<!--</form>-->
I think the problem is with the different abbreviation that you are using in your controller and in your template, changing accvm for vm it's working fine for me.
Here's your JSFiddle updated: http://jsfiddle.net/j25jwtL2/58/

AngularJS Simple click counter not working

I'm trying to build a counter functionality. I'm using AngularJS with Bootstrap button group and I'm not sure where the conflict is. Below is my code. Can someone please help?
<!DOCTYPE html>
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-route.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<body>
<div ng-app="meetingDetail" ng-controller="meetingDetailCtrl">
<div class="col-md-12">
<div class="btn-group" data-toggle="buttons">
<label class="btn btn-success btn-sm">
<input type="radio" name="radioSecondBy" ng-click = "yesCount = yesCount+1" id="vYes" autocomplete="off">Yes
</label>
<label class="btn btn-warning btn-sm">
<input type="radio" name="radioSecondBy" ng-click = "yesCount = yesCount+1" id="vNo" autocomplete="off"> No
</label>
<label class="btn btn-info btn-sm">
<input type="radio" name="radioSecondBy" ng-click = "yesCount = yesCount+1" id="vAbstain" autocomplete="off"> Abstain
</label>
</div>
{{yesCount}}
</div>
<script>
var app = angular.module('meetingDetail', []);
app.controller('meetingDetailCtrl', function($scope) {
$scope.yesCount= 0;
});
</script>
</body>
</html>
Radio buttons don't have click event.
Put click event on label instead of radio button
Like this
<label ng-click = "yesCount = yesCount+1" class="btn btn-info btn-sm">
<input type="radio" name="radioSecondBy" id="vAbstain" autocomplete="off"> Abstain
</label>
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-route.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
</head>
<body>
<div ng-app="meetingDetail" ng-controller="meetingDetailCtrl">
<div class="col-md-12">
<div class="btn-group" data-toggle="buttons">
<label class="btn btn-success btn-sm" ng-click = "yesCount = yesCount+1">
<input type="radio" name="radioSecondBy" id="vYes" autocomplete="off">Yes
</label>
<label class="btn btn-warning btn-sm" ng-click = "yesCount = yesCount+1" >
<input type="radio" name="radioSecondBy" id="vNo" autocomplete="off"> No
</label>
<label ng-click = "yesCount = yesCount+1" class="btn btn-info btn-sm">
<input type="radio" name="radioSecondBy" id="vAbstain" autocomplete="off"> Abstain
</label>
</div>
{{yesCount}}
</div>
</div>
<script>
var app = angular.module('meetingDetail', []);
app.controller('meetingDetailCtrl', function($scope) {
$scope.yesCount= 0;
});
</script>
</body>
</html>
ng-click does not work on radio buttons. You can use either ng-change or watch the variable
1) ng-change
<input type="radio" name="radioSecondBy" ng-change= "yesCount = yesCount+1" id="vYes" autocomplete="off">Yes
2) $watch
$scope.$watch('yesCount', function(value) {
$scope.yesCount = $scope.yesCount + 1;
});
here is the similar question

Error message not displayed on form submit when pristine

I have following code for form validation. It shows error messages when I enter some value in textbox (dirty) and the value is invalid. But when I do not make any change (pristine) and click submit, the error messages are not shown. How to fire error messages in this scenario?
Note: When I removed pristine check, the error message is displayed even before submitting.
<!DOCTYPE html>
<html>
<head>
<!-- bootstrap -->
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css">
<style>
body{padding-top: 30px;}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular-resource.js"></script>
<script type="text/JavaScript">
var myApp = angular.module('myApp', []);
myApp.controller('myController', function ($scope) {
//Call function on form submit
$scope.submitForm = function (isValid) {
if (isValid) {
alert('Valid');
}
else {
alert('Invalid');
}
};
});
</script>
</head>
<body ng-app="myApp" ng-controller="myController">
<div class="myDiv">
<div class="col-sm-8 col-sm-offset-2">
<div class="page-header">
<h1>Validation</h1>
</div>
<form name="userForm" ng-submit="submitForm(userForm.$valid)" novalidate>
<!-- Prevents HTML5 validation using novalidate-->
<div class="form-group" ng-class="{ 'has-error' : userForm.name.$invalid && !userForm.name.$pristine }">
<label>Name</label>
<input type="text" name="name" class="form-control" ng-model="user.name" required>
<p ng-show="userForm.name.$invalid && !userForm.name.$pristine" class="help-block">
Name required.</p>
</div>
<div class="form-group" ng-class="{ 'has-error' : userForm.location.$invalid && !userForm.location.$pristine }">
<label>Location</label>
<input type="text" name="location" class="form-control" ng-model="user.location"
ng-minlength="3" ng-maxlength="8">
<p ng-show="userForm.location.$error.minlength" class="help-block">
Location is less than min length.</p>
<p ng-show="userForm.location.$error.maxlength" class="help-block">
Location more than max length.</p>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</div>
</div>
</body>
</html>
Try using userForm.$submitted instead of $pristine
For a good learning exercise and debugging try the following in view
<pre>{{userForm|json}}</pre>

Button flickering on mouseover with ng-clip and ng-show/ng-hide

I'm seeing weird flickering when mousing over the ng-clip enhanced button. I've got the ng-clip enhanced button being shown/hid when the enclosing div is moused over. As the user moves the mouse over the button, it flickers. I'm assuming it's something to do with event handling between Zeroclipboard and the Angular code?
Here is a Plunker page displaying the issue: http://plnkr.co/4gFy9U
The code from Plunker:
<!doctype html>
<html>
<head>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.14/angular.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/zeroclipboard/2.1.6/ZeroClipboard.min.js"></script>
<script src="//rawgit.com/asafdav/ng-clip/master/src/ngClip.js"></script>
</head>
<body>
<div ng-app="myapp">
<div class="container" ng-controller="myctrl" ng-mouseover="isHovering = true" ng-mouseout="isHovering = false">
<div class="page-header">
<h1>ngClip <small>example</small></h1>
</div>
<form>
<div style="background:red;" class="form-group">
<label >Copy #1</label>
<input type="text" class="form-control" placeholder="Enter text to copy" ng-model="copy1">
<button ng-if="isHovering" class="btn btn-default" clip-copy="copy1">Copy!</button>
</div>
<br/><br/><br/>
<textarea class="form-control" rows="3" placeholder="paste here"></textarea>
</form>
</div>
</div>
<script>
var myapp = angular.module('myapp', ["ngClipboard"]);
myapp.config(['ngClipProvider', function(ngClipProvider) {
ngClipProvider.setPath("//cdnjs.cloudflare.com/ajax/libs/zeroclipboard/2.1.6/ZeroClipboard.swf");
ngClipProvider.setConfig({
bubbleEvents: false
})
}]);
myapp.controller('myctrl', function ($scope) {
$scope.fallback = function(copy) {
window.prompt('Press cmd+c to copy the text below.', copy);
};
$scope.showMessage = function() {
console.log("clip-click works!");
};
});
</script>
</body >
</html>
I was also having this issue. I fixed by using ng-mouseenter on an outer div instead of using ng-mouseover and ng-mouseleave on an inner div instead of ng-mouseout. No flicker!
So:
<div ng-app="myapp" ng-mouseenter="isHovering = true">
<div class="container" ng-controller="myctrl" ng-mouseleave="isHovering = false">
<div class="page-header">
<h1>ngClip <small>example</small></h1>
</div>
<form>
<div style="background:red;" class="form-group">
<label >Copy #1</label>
<input type="text" class="form-control" placeholder="Enter text to copy" ng-model="copy1">
<button ng-if="isHovering" class="btn btn-default" clip-copy="copy1">Copy!</button>
</div>
<br/><br/><br/>
<textarea class="form-control" rows="3" placeholder="paste here"></textarea>
</form>
</div>
</div>

Why does ng-messages for form validation not work when using $rollbackViewValue

I have a form using ng-messages for form validation error messages. Im also using the new ng-model-options with $rollbackViewValue to rollback all changes to the form. Problem is ng-mesages will not work if I use the rollbackViewValue on the form.
I really like this new function in angular1.3 using ng-model-options to reset a form as I have not found anything that works as well as $rollbackViewValue()
Heres is the code and plunker
<!DOCTYPE html>
<html data-ng-app="App">
<head lang="en">
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css"/>
</head>
<body>
<div class="container" data-ng-controller="formCrtl as vm">
<div class="col-lg-5">
<form name="form" novalidate="novalidate" role="form"
data-ng-submit="vm.submit()"
data-ng-model-options="{updateOn: 'submit'}" >
<!---->
<div class="form-group" data-ng-class="{ 'has-error': form.fname.$invalid && form.fname.$touched }">
<label for="fname">First Name</label>
<input type="text" required class="form-control" name="fname" id="fname" placeholder="Enter text" data-ng-model="vm.names.fname">
<div data-ng-if="form.fname.$touched" data-ng-messages="form.fname.$error">
<span class="help-block" data-ng-message="required">required field</span>
</div>
</div>
<div class="form-group" data-ng-class="{ 'has-error': form.lname.$invalid && form.lname.$touched }">
<label for="lname">Last Name</label>
<input type="text" required class="form-control" name="lname" id="lname" placeholder="Enter text" data-ng-model="vm.names.lname">
<div data-ng-if="form.lname.$touched" data-ng-messages="form.lname.$error">
<span class="help-block" data-ng-message="required">required field</span>
</div>
</div>
<div class="col-sm-offset-2 col-sm-10 btn-group">
<button type="submit" class="btn btn-primary" data-ng-disabled="form.$invalid">Submit</button>
<button type="button" class="btn btn-default" data-ng-click="form.$rollbackViewValue()">reset</button>
<!---->
</div>
</form>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.8/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.8/angular-messages.js"></script>
<script src="scripts.js"></script>
</body>
</html>
controller
var App = angular.module("App", ['App', 'ngMessages']);
App.controller('formCrtl',function ($scope, $rootScope) {
var vm = this;
vm.names = {
fname: "Albert",
lname: "Capone"
}
});
You would need to make the form pristine and revert back the touched state as well. You can do so by calling the special functions, $setPristine() and $setUntouched() , on the formController. But it appears rollBackViewValue works with ngSubmit, but it is only to revertback during some action, (like esc key, another button). But if the form field has contraint errors it appears it updated viewvalue to nullify the entered value. You could try this way by resetting to default field values.
In your view:-
<button type="button" class="btn btn-default"
data-ng-click="vm.reset(form)">reset</button>
In your controller:-
var vm = this;
var defModel = {
fname: "Albert",
lname: "Capone"
};
vm.names = angular.copy(defModel);
vm.reset = function(form) {
form.$rollbackViewValue();
form.$setPristine(); //Set pristine state
form.$setUntouched(); //Set state from touched to untouched
vm.names = angular.copy(defModel); //reset model
}
var App = angular.module("App", ['App', 'ngMessages']);
App.controller('formCrtl', function($scope, $rootScope) {
var vm = this;
var defModel = {
fname: "Albert",
lname: "Capone"
};
vm.names = angular.copy(defModel);
vm.reset = function(form) {
form.$rollbackViewValue(); //Probably can be removed
form.$setPristine();
form.$setUntouched();
vm.names = angular.copy(defModel);
}
});
<div data-ng-app="App">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
<div class="container" data-ng-controller="formCrtl as vm">
<div class="col-lg-5">
<form name="form" novalidate="novalidate" role="form" data-ng-submit="vm.submit(form)" data-ng-model-options="{updateOn: 'submit'}">
<!---->
<div class="form-group" data-ng-class="{ 'has-error': form.fname.$invalid && form.fname.$touched }">
<label for="fname">First Name</label>
<input type="text" required class="form-control" name="fname" id="fname" placeholder="Enter text" data-ng-model="vm.names.fname">
<div data-ng-if="form.fname.$touched" data-ng-messages="form.fname.$error">
<span class="help-block" data-ng-message="required">required field</span>
</div>
</div>
<div class="form-group" data-ng-class="{ 'has-error': form.lname.$invalid && form.lname.$touched }">
<label for="lname">Last Name</label>
<input type="text" required class="form-control" name="lname" id="lname" placeholder="Enter text" data-ng-model="vm.names.lname">
<div data-ng-if="form.lname.$touched" data-ng-messages="form.lname.$error">
<span class="help-block" data-ng-message="required">required field</span>
</div>
</div>
<div class="col-sm-offset-2 col-sm-10 btn-group">
<button type="submit" class="btn btn-primary" data-ng-disabled="form.$invalid">Submit</button>
<button type="button" class="btn btn-default" data-ng-click="vm.reset(form)">reset</button>
<!---->
</div>
</form>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.8/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.8/angular-messages.js"></script>
</div>

Resources