Separating Button Click Behavior - angularjs

Running through an example from the book, AngularJS, why does clicking the Reset button result in the alert, sorry, please get more customers.?
I only want the alert to occur when pressing the Fund my startup! button.
<html ng-app>
<body>
<script src=
"https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js">
</script>
<form ng-submit="requestFunding()" ng-controller="StartUpController">
Starting: <input ng-change="computeNeeded()" ng-model="startingEstimate">
Recommendation: {{needed}}
<button>Fund my startup!</button>
<button ng-click="reset()">Reset</button>
</form>
<script>
function StartUpController($scope) {
$scope.computeNeeded = function() {
$scope.needed= $scope.startingEstimate * 10;
};
$scope.requestFunding = function() {
window.alert("sorry, please get more customers.");
};
$scope.reset = function() {
$scope.startingEstimate = 0;
};
}
</script>
</body>
</html>

You need to prevent the default button on-click behavior (which is submit)
The most explicit way in angular:
Following is a one way. (You could create a directive for this purpose, too.)
template:
<button ng-click="reset($event)">Reset</button>
javascript:
$scope.reset = function( event ) {
event.preventDefault();
$scope.startingEstimate = 0;
};
somewhat implicit way in general html:
<button type="button" ng-click="reset()">Reset</button>
This works by overriding the type attribute of button element
which happens to be 'submit'.

Related

How to set default value of custom radio button in a modal

Background:
So I am working with a modal box for searching through a list of task entries within a database using a form to narrow results. In this modal box, there is a custom radio button that's used for selecting whether or not the task is in progress (simple "Yes" or "No" option). The goal is to set the "No" option as the default value whenever the modal is called. Currently, I am using data-ng-init; however, this only works the first time the modal is opened. If the user closes the modal and reopens it, the default value is no longer set. Below is a sample of what this custom button looks like:
<div class="col-sm-6">
<div style="margin-bottom:10px">
<button type="button" data-ng-init="tr.taskInProgress('No')"
title="Task In Progress: No" data-ng-click="tr.taskInProgress('No')"
style="border:0;background:transparent">
<img src="../images/selected.png" data-ng-switch-when="No" />
<img src="../images/Deselect.png" data-ng-switch-when="Yes" />
<img data-ng-switch-when="" src="/nc/images/Deselect.png" /></button>
<text>No
</div>
(another similar button, but for 'yes')
</div>
In the accompanying .js file, the following is used to help populate this modal:
/*--------- Get Tasks ---------*/
tr.closeGetTaskModal = closeGetTasModal;
tr.displayGetTaskMessage = true;
tr.selectedStatusType = getStatusType;
tr.trackingId = '';
tr.performGetTask = performGetTask;
tr.isTaskInProgess = isTaskInProgress;
And, in the same .js file, the following function is used to modify the radio:
function isTaskInProgress(newValue) {
tr.isTaskInProgress = newValue;
}
I have been looking through others iterations on how they handle such cases, but I have been unlucky and have not found anything similar enough to what I am working with that works. I have tried setting the default in the Get Tasks section by modifying isTaskInProgress('No'), but this only locked the modal and I couldn't modify the option. I have tried setting the default inside the isTaskInProgress function; however, this only worked when the button was clicked, it failed to set a default. I tried seeing if data-ng-default would work; however, this didn't seem to be a recognized parameter. Does anyone have suggestions on how to modify this to get the desired results? Thank you all in advance for your help
Small Disclaimer
I am taking the liberty of assuming you are using UI Bootstrap (since I see bootstrap classes in your sample HTML), so will be using Uib Modal in my example.
Bootstrap Modal docs: https://angular-ui.github.io/bootstrap/#!#modal
Resolver / Callback Solution
You will most likely want to use the controller to set your tr.isTaskInProgress flag rather than using the ng-init directive (a bit more flexibility / readability).
Set tr.isTaskInProgress to false at the top of your target controller function, then pass its value to your modal as a property in a "Modal Resolve Object".
Bootstrap's explanation of the Resolve Object: https://angular-ui.github.io/bootstrap/#!#ui-router-resolves
Code
function MainController($scope, $uibModal) {
let vm = this;
vm.isTaskInProgress = false;
// When you open the modal, pass in the isTaskProgress value
let modalInstance = $uibModal.open({
templateUrl: 'myModalContent.html', // Points to the script template
controller: 'ModalController', // Points to the controller
controllerAs: 'mc',
windowClass: 'app-modal-window',
backdrop: 'static',
resolve: {
isTaskInProgress: function() {
// pass the task state to the Modal
return vm.isTaskInProgress;
}
}
});
// handle the value(s) passed back from the modal
modalInstance.result.then(returnedTaskState => {
// reassign the returned value of the modal
if (returnedTaskState !== null) {
vm.isTaskInProgress = returnedTaskState;
}
});
}
Working Example
https://plnkr.co/ryK7rG
In the interest of time, I've changed some of the variable / method names from what you have in your snippets. In the example, you can...
Set the In Progress value before you open the modal and the modal reflects the In Progress value.
Change the In Progress value inside the modal. On closing the modal, the value will be updated in the main page.
SO Snippet
I realize the SO Snippet window is not exactly the best place for this example, but just tossing my example code in here in case Plunker is inconvenient for some reason.
(function() {
"use strict";
let app = angular
.module("myApp", ["ui.bootstrap"])
.controller("MainController", MainController);
MainController.$inject = ["$scope", "$timeout", "$uibModal"];
function MainController($scope, $timeout, $uibModal) {
/**
* John Papa Style Guide
* https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md
* */
let vm = this;
// ==== scoped variables ====
vm.title = "AngularJS - Passing Toggled Values to a Modal"
vm.taskInProgress = false;
vm.taskButtonLocked = false;
// ==== functions hoist ====
vm.beginTask = _beginTask;
function _beginTask() {
vm.modalIsOpen = true;
// do work
openModal();
}
// ==== local functions ====
function openModal() {
// open the modal with configurations
let modalInstance = $uibModal.open({
templateUrl: 'myModalContent.html', // Points to my script template
controller: 'ModalController', // Points to my controller
controllerAs: 'mc',
windowClass: 'app-modal-window',
backdrop: 'static',
resolve: {
taskInProgress: function() {
// pass the task state to the Modal
return vm.taskInProgress;
}
}
});
// handle the value(s) passed back from the modal
modalInstance.result.then(returnedTaskState => {
// reset control values after modal is closed
vm.taskButtonLocked = false;
vm.modalIsOpen = false;
// reassign the returned value of the modal
console.log("returnedTaskState: ", returnedTaskState);
if (returnedTaskState !== null) {
vm.taskInProgress = returnedTaskState;
}
});
}
}
})();
(function() {
'use strict';
angular
.module('myApp')
.controller('ModalController', ModalController);
ModalController.$inject = ['$scope', '$timeout', '$uibModalInstance', 'taskInProgress'];
function ModalController($scope, $timeout, $uibModalInstance, taskInProgress) {
// Assign Cats to a Modal Controller variable
let vm = this;
vm.inProgress = taskInProgress;
console.log("taskInProgress", taskInProgress)
$scope.submit = function() {
$uibModalInstance.close(vm.inProgress);
}
$scope.close = function() {
$uibModalInstance.close(null);
}
}
})();
input[type="radio"]:hover {
cursor: pointer;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>AngularJS Plunk</title>
<link rel="stylesheet" href="style.css" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
<!-- JQuery and Bootstrap -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<!-- Angular Stuff -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.8/angular.js"></script>
<!-- UI Bootstrap Stuff -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/2.5.0/ui-bootstrap-tpls.min.js"></script>
<!-- Our Angularjs App -->
<script type="text/javascript" src="app.js"></script>
</head>
<body ng-app="myApp" ng-controller="MainController as tr">
<!-- ==== MAIN APP HTML ==== -->
<div class="container" style="padding:1em;">
<div class="row">
<div class="col-xs-12">
<div class="jumbotron text-center">
<h2>{{ tr.title }}</h2>
<h4><em>SO Question #55362380</em></h4>
<h4><em>AngularJS - v1.7.8</em></h4>
</div>
</div>
<div class="col-xs-12">
<form>
<div class="form-group">
<h3>Task In Progress</h3>
<div>
<label>Yes:</label>
<input type="radio"
ng-checked="tr.taskInProgress"
ng-click="tr.taskInProgress = true"
ng-disabled="tr.modalIsOpen">
</div>
<label>No:</label>
<input type="radio"
ng-checked="!tr.taskInProgress"
ng-click="tr.taskInProgress = false"
ng-disabled="tr.modalIsOpen">
</div>
<div class="form-group">
<label>Open the modal:</label>
<button type="button"
class="btn btn-success"
ng-click="tr.beginTask();"
ng-disabled="tr.taskButtonLocked">
<span>Begin Task</span>
</button>
</div>
</form>
</div>
</div>
</div>
<!-- ==== MODAL HTML TEMPLATE ==== -->
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3 class="modal-title" id="modal-title">I'm a modal!</h3>
</div>
<div class="modal-body" id="modal-body">
<form>
<div class="form-group">
<label>Task State:</label>
<div style="padding:1em;background:rgba(200, 214, 229,0.3);">
<p>
<span ng-show="!mc.inProgress">
<span>Task is not in progress... </span>
<i class="fa fa-check-square" aria-hidden="true"></i>
</span>
<span ng-show="mc.inProgress">
<span>Task is in progress... </span>
<i class="fa fa-spinner fa-spin" aria-hidden="true"></i>
</span>
</p>
</div>
</div>
<div class="form-group" style="padding-top:1em;">
<h3>Task In Progress</h3>
<div>
<label>Yes:</label>
<input type="radio"
ng-checked="mc.inProgress"
ng-click="mc.inProgress = true">
</div>
<label>No:</label>
<input type="radio"
ng-checked="!mc.inProgress"
ng-click="mc.inProgress = false">
</div>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-primary" type="button" ng-click="submit()">OK</button>
<button class="btn btn-warning" type="button" ng-click="close()">Cancel</button>
</div>
</script>
</body>
</html>

how to disable or enable button on angularjs?

I have used 2 button in the form. I want to disable button1 on initialisation though I have given ng-disabled="true" but whenever user clicks on button2, button1 get enabled. Can anyone tell me how to do this in angularjs ?
You don't need to do anything in the controller if you are not working with the scope variable inside the controller.
So just do something like:
angular.module("app",[]).controller("ctrl",function($scope){})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<button ng-disabled="first !== true"> one</button>
<button ng-click="first = true"> two</button>
</div>
You can call one function on click of second button and set the ng-disabled value to false.
DEMO
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl',function($scope) {
$scope.inactive= true;
$scope.enableButton1 = function() {
$scope.inactive= false;
}
});
<div ng-app="myApp" ng-controller="MyCtrl">
<br><input type="button" ng-disabled="inactive" value="button1"/>
<br><input type="button" ng-click="enableButton1()" value="button2"/>
</div>
use scope variables and assign them to ng-disabled
angular.module("app",[])
.controller("ctrl",function($scope){
$scope.firstBtn = true;
$scope.secondBtn = false;
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<button ng-disabled="firstBtn" > one</button>
<button ng-disabled="secondBtn" ng-click="firstBtn = false"> two</button>
</div>
Its very simple as given below:
JS
var app = angular.module('myApp', []);
app.controller('ctrl', function($scope) {
$scope.isDisabled = true;
$scope.toggleButton = function() {
$scope.isDisabled = !$scope.isDisabled;
}
});
HTML
<div ng-app='myApp'>
<div ng-controller='ctrl'>
<button ng-click='toggleButton()'>
Toggle
</button>
<button ng-disabled='isDisabled'>
I am button
</button>
</div>
</div>
Here is the jsfiddle link Jsfiddle demo

Prevent ng-click="" effect on a disabled button

How can I prevent AngularJS to not click on an HTML button tag that has "disabled" attribute?
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<button type="button" disabled ng-click="something()">No Click Please!</button>
In this case, something() should NOT be called.
You pass an expression that has to be evaluated in the ngClick directive. If it is not evaluated true then something() will not be called.
Heres an example:
(function() {
angular.module('MyApp', [])
.controller('MyController', MyController);
MyController.$inject = ["$scope"];
function MyController($scope) {
$scope.disabled = true;
}
})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div data-ng-app="MyApp">
<div data-ng-controller="MyController">
<button type="button" ng-disabled="disabled" ng-click="disabled || something()">No Click Please!</button>
<button type="button" data-ng-click="disabled = !disabled">{{disabled ? 'Enable' : 'Disable'}}</button>
</div>
</div>
Notice you can also use the ngDisabled directive so that if $scope.disabled is true, something() will not be called and the button will also be disabled!
Proper way is to use ng-disabled which is a default directive in angular and using a scope variable to handle it to make it disabled,
HTML:
<button ng-click="disableClick()" ng-disabled="isDisabled" ng-model="isDisabled">No Click Please!</button>
JS:
$scope.isDisabled = false;
$scope.disableClick = function() {
alert("Clicked!");
$scope.isDisabled = true;
return false;
}
EDIT
As papakia's mentioned, check the boolean variable and function so that it will not get executed.
DEMO APP
This solution works in AngularJS for any and all click targets using the built-in disabled attribute for form inputs and/or other elements using Bootstrap's .disabled class and it works without adding to the controller.
HTML
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<button type="button" disabled="disabled" data-ng-click="something($event)">No Click Please!</button>
JavaScript
function something( $event )
{
var is_enabled = !angular.element( $event.currentTarget ).is( '.disabled,:disabled' );
if( is_enabled )
{
}
}
Use ng-disabled.
<md-button ng-disabled="true"> Disabled Button </md-button>
EDIT ...
Fiddled

Getting ng-show to work with Html5 <dialog> elements

Html5 dialogs are simple. Shoulda been there 15 years ago!
How to get ng-show working (it doesn't) with dialogs?
<!DOCTYPE html>
<html ng-app="project">
<head>
<meta charset='UTF-8'>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script>
<script>
angular.module('project', [])
.controller('TheController', function ($scope) {
$scope.dialogShowing = false;
$scope.showDialog = function () {
dialogShowing = true;
document.getElementById('theDialog').show();
};
$scope.hideDialog = function () {
dialogShowing = false;
document.getElementById('theDialog').close();
};
});
</script>
</head>
<body ng-controller="TheController">
<div> Hello
<!-- dialog, where it is placed in the source, doesn't take up space -->
<dialog id="theDialog">
<div>
<h3>Simple Angular Html5Dialog</h3>
<hr/>
<p>I am very well, thank you</p>
<button ng-click="hideDialog()">No, thank you</button>
</div>
</dialog>
how are you?
</div>
<button ng-click="showDialog()">^ Click for the answer</button>
</body>
</html>
The only thing I have been able to get working is .open() and .close() on the dialog widget itself, and have to simulate ng-show/hide, above.
Advice?
I'm not sure what browser you are using, but dialog is very much unsupported by most browsers (http://caniuse.com/#search=dialog). If it's a simple modal you're looking to create why not use a div and style it accordingly?
It's perfectly possible. Here's a demo from my blog:
<div style="width: 600px;" id="example">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<script type="text/javascript">
var App = angular.module("MyApp", []);
// Make ng-show/hide doesn't work with <dialog>
App.controller('DialogDemo', ['$scope', function ($scope) {
$scope.dialogShowing = false;
$scope.showDialog = function () {
$scope.dialogShowing = true;
$scope.whatHappened = "something happened that needs a dialog";
document.getElementById('theDialog').showModal();
};
$scope.hideDialog = function () {
$scope.dialogShowing = false;
document.getElementById('theDialog').close();
$scope.whatHappened = undefined;
};
}]);
</script>
<div style="align-content: center" ng-app="MyApp" ng-controller="DialogDemo">
(text above button)<br/>
<button ng-click="showDialog()">Click me</button><br/>
(text below button, and above dialog in source)<br/>
<dialog id="theDialog">
<div>
<h3>Ooops</h3>
<hr/>
<div>
<!-- see note above about double-curly-brace -->
{{whatHappened}}
</div>
<hr/>
<button ng-click="hideDialog()">OK</button>
</div>
</dialog>
(text below dialog in source)<br/>
<span style="font-weight: bold" ng-show="dialogShowing">Dialog should now be show (modal style) in the center of the page.</span>
</div>
</div>

Angularjs action on click of button

I am trying to do some calculation but it is getting done as soon as I enter the amount. I just want this to happen on click of a button rather than automatically.
What I have done so far:
<!DOCTYPE html>
<html ng-app="myAppModule">
<head>
<title>Angular JS - programming-free.com</title>
<link href="https://dl.dropbox.com/u/96099766/DetailModalExample/bootstrap.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="lib/angularjs.min.js"></script>
</head>
<body>
<div ng-controller="myAppController" style="text-align:center">
<p style="font-size:28px;">
Enter Quantity:
<input type="text" ng-model="quantity"/>
</p>
<h2>Total Cost: Rs.{{calculateval(quantity,10)}}</h2>
</div>
<script type="text/javascript">
var myAppModule = angular.module('myAppModule', []);
myAppModule.controller('myAppController', function($scope,calculateService) {
$scope.quantity=1;
$scope.calculateval = function(xval,yval) {
return calculateService.calculate(xval,yval);
}
});
// Service
myAppModule.factory('calculateService', function(){
return {
calculate: function(xval,yval){
return xval*yval;
}
}
});
</script>
</body>
</html>
The calculation occurs immediately since the calculation call is bound in the template, which displays its result when quantity changes.
Instead you could try the following approach. Change your markup to the following:
<div ng-controller="myAppController" style="text-align:center">
<p style="font-size:28px;">Enter Quantity:
<input type="text" ng-model="quantity"/>
</p>
<button ng-click="calculateQuantity()">Calculate</button>
<h2>Total Cost: Rs.{{quantityResult}}</h2>
</div>
Next, update your controller:
myAppModule.controller('myAppController', function($scope,calculateService) {
$scope.quantity=1;
$scope.quantityResult = 0;
$scope.calculateQuantity = function() {
$scope.quantityResult = calculateService.calculate($scope.quantity, 10);
};
});
Here's a JSBin example that demonstrates the above approach.
The problem with this approach is the calculated result remains visible with the old value till the button is clicked. To address this, you could hide the result whenever the quantity changes.
This would involve updating the template to add an ng-change on the input, and an ng-if on the result:
<input type="text" ng-change="hideQuantityResult()" ng-model="quantity"/>
and
<h2 ng-if="showQuantityResult">Total Cost: Rs.{{quantityResult}}</h2>
In the controller add:
$scope.showQuantityResult = false;
$scope.calculateQuantity = function() {
$scope.quantityResult = calculateService.calculate($scope.quantity, 10);
$scope.showQuantityResult = true;
};
$scope.hideQuantityResult = function() {
$scope.showQuantityResult = false;
};
These updates can be seen in this JSBin demo.

Resources