<div ng-controller="TestingCtrl">
<input ng-class="{'fancy' :status}">
<input ng-class="{'fancy' :status2}">
<input type="button" value="change" ng-change="action()">
</div>
.fancy{
background:Yellow;
}
function TestingCtrl($scope) {
$scope.status = true
$scope.status2 = true
$scope.action = function() {
$scope.status = false
$scope.status2 = false
}
The model never changes so ng-change is never called. From the docs:
"ngChange expression is only evaluated when a change in the input value causes a new value to be committed to the model"
The action function is never evaluated because there's no ng-model to change for that specific input.
If you do ng-click it will work, then you can toggle the background color.
$scope.action = function(){
$scope.status = !$scope.status
$scope.status2 = !$scope.status2
}
http://jsfiddle.net/KYk2c/
Use ng-click instead of ng-change on button and it's done.. Also Created an angular app first before your controller..
var app = angular.module('myApp', []);
function testController($scope) {
$scope.status = true;
$scope.status2 = true;
$scope.action = function() {
$scope.status = false
$scope.status2 = false
}
}
and the html goes like this
<div ng-controller="testController">
<input ng-class="{'fancy' :status}">
<input ng-class="{'fancy' :status2}">
<input type="button" value="change" ng-click="action()">
</div>
Related
I have a form in my page with AngularJS and Stripe JS.
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"> <script type="text/javascript">
var app= angular.module("app",[]);
app.config(function($interpolateProvider){
$interpolateProvider.startSymbol("[[[");
$interpolateProvider.endSymbol("]]]");
});
app.controller("Ctrl",function(stripeService, $scope, $rootScope){
$scope.name= "World";
$scope.stripeCompleted= false;
stripeService.start();
$rootScope.on("stripedone", function(e,stripeEvent){
$scope.stripeCompleted= stripeEvent.complete;
$scope.$apply();
});
});
app.service("stripeService", function($window,$rootScope){
function start(){
var btn= document.querySelectorAll("#test")[0];
var displayError= document.getElementById('card-errors');
var stripe= Stripe("{{ stripe_key }}");
var elements= stripe.elements();
var style= {
base: {
fontSize: "1.1875rem",
fontSmoothing: "always",
fontWeight: "600"
}
};
var card= elements.create("card", {style:style});
card.mount("#card-element");
card.addEventListener('change', function(event) {
if (event.error) {
displayError.textContent = event.error.message;
} else {
displayError.textContent = '';
}
if (event.complete) {
$rootScope.$broadcast("stripedone",event);
} else {
$rootScope.$broadcast("stripedone",event);
}
});
var formID= "register-form";
var form= document.getElementById(formID);
form.addEventListener("submit",function(event){
event.preventDefault();
stripe.createToken(card).then(function(result){
if(result.error) {
displayError.textContent= result.error.message;
} else {
stripeTokenHandler(result.token, formID);
}
});
});
return {"start":start};
}
});
// tut https://stripe.com/docs/stripe-js/elements/quickstart#create-form
function stripeTokenHandler(token, formID) {
// Insert the token ID into the form so it gets submitted to the server
var form = document.getElementById(formID);
var hiddenInput = document.createElement('input');
hiddenInput.setAttribute('type', 'hidden');
hiddenInput.setAttribute('name', 'stripeToken');
hiddenInput.setAttribute('value', token.id);
form.appendChild(hiddenInput);
// Submit the form
form.submit();
}
</script> <form id="register-form" name="regForm" method="post>
<input ng-model="reg.email" type="email" name="username">
<div id="stripe-wrapper">
<div id="card-element"></div>
</div>
<small id="card-errors" class="text-danger" role="alert">{{ ccErrMsg }}</small>
<br>
<button type="submit" ng-model="reg.btn" ng-disabled="!regForm.username.$valid>Register</button>
</form>
I want for my button to be un-clickable unless the user fills out the Stipe credit card section correctly. How do I make it so my button is disabled unless the the Stripe credit card fields are filled out correctly?
Update: Following karthick's answer gives me a new error:
angular.js:13642 TypeError: stripeService.start is not a function
at Object.<anonymous> ((index):135)
at Object.invoke (angular.js:4708)
at P.instance (angular.js:10177)
at n (angular.js:9096)
at g (angular.js:8459)
at angular.js:8339
at angular.js:1782
at m.$eval (angular.js:17378)
at m.$apply (angular.js:17478)
at angular.js:1780
You should use a AngularJS directive in this case. This is nothing to put in a controller, service, factory or component. Once you use a directive your code will be much smarter and become fully supported by AngularJS diggest cycles and DOM bindings. This is how the documentation introduces directives:
What are Directives? At a high level, directives are markers on a DOM element (such as an attribute, element name, comment or CSS class) that tell AngularJS's HTML compiler ($compile) to attach a specified behavior to that DOM element (e.g. via event listeners), or even to transform the DOM element and its children.
> Demo fiddle
Your solution could be smart like this one by using a nice directive:
View
<body ng-app="angularjs-starter">
<script src="https://js.stripe.com/v3/"></script>
<div ng-controller="MainCtrl">
<form name="regForm" id="register-form">
<label>Mail</label>
<input ng-model="reg.email" type="email" name="username">
<div stripe-validator
stripe-complete="stripeCompleted"
stripe-form-id="register-form"></div>
<br>
<button ng-model="reg.btn" ng-disabled="stripeCompleted === false || !regForm.username.$valid">Register</button>
</form>
</div>
</body>
AngularJS Application / Stripe.js card validation directive
var app = angular.module('angularjs-starter', []);
app.controller('MainCtrl', function($scope, $rootScope) {
//Init stripe state via controller
$scope.stripeCompleted = false;
});
app.directive('stripeValidator', function() {
return {
restrict: 'A',
template: `
<div id="stripe-wrapper">
<div id="card-element"></div>
</div>
<small id="card-errors" class="text-danger" role="alert">{{ ccErrMsg }}</small>
<input type="hidden" name="stripeToken" ng-value="stripeToken" />`,
scope: {
"stripeComplete": '=',
"stripeFormId": '#',
"stripeError": '=',
"stripeToken": '=',
},
link: function(scope, element, attrs) {
//Init
var stripe = Stripe("pk_test_6pRNASCoBOKtIshFeQd4XMUh");
var elements = stripe.elements();
var card = elements.create("card");
var form = document.getElementById(scope.stripeFormId);
//mount card element https://stripe.com/docs/stripe-js/reference#element-mount
card.mount("#card-element");
//add event listener
card.addEventListener('change', function(event) {
//check for errors
if (event.error) {
scope.ccErrMsg = event.error.message;
} else {
scope.ccErrMsg = '';
}
//check for complete
scope.stripeComplete = event.complete ? true : false;
//apply scope
scope.$apply();
});
//inject form submit event
form.addEventListener("submit", function(event) {
//prevent form submit
event.preventDefault();
//handle token, handle error and form submit forward
stripe.createToken(card).then(function(result) {
if (result.error) {
scope.ccErrMsg = event.error.message;
scope.stripeToken = '';
} else {
scope.ccErrMsg = '';
scope.stripeToken = result.token;
}
//apply scope
scope.$apply();
//forward submit
form.submit();
})
});
}
}
});
// I have written java code to fetch data from mongo-db. What i need to do is on tick of checkbox button i have to display those data in drop-down menu using angular-js and bootstrap. Nothing is happening after doing these code.
.html page
<div ng-controller="release">
<div class="col-md-2 col-centered col-fixed">
<label for="cloneRelease" translate="release.form.cloneRelease">CloneRelease</label>
</div>
<div>
<input type="checkbox" ng-model="ticked">
<div class="dropdown-menu" ng-repeat="release in releaseName" ng-show="ticked">{{release.name}}</div>
</div>
</div>
controller.js
releaseApp.controller('release', function($scope, $location, $http, ReleaseNameService){
$scope.releaseName = [];
init();
function init(){
ReleaseNameService.getReleaseName().then(function(data){
$scope.releaseName = data;});
console.log('inside controller: '+$scope.releaseName);
}
});
service.js
releaseApp.factory('ReleaseNameService', function($http){
var releaseName = [];
var factory = {};
factory.getReleaseName = function(){
return $http.get('release/fetchAllReleaseDetails').then(function(response){
releaseName = response.data;
console.log('inside service method'+ releaseName);
return releaseName;
});
};factory;
});
It is simple, u need to bind checkbox with ng-model:
<input type="checkbox" ng-model="ticked">
If its ticked $scope.ticked return true, else return false. If true show data, if false hide it (with ng-show)
Here is an example in jsFiddle without css ofc.
http://jsfiddle.net/RLQhh/2282/
UPDATE:
recreateing case with service.
service.js
app.factory('dataService', function ($http) {
var dataObject= {
async: function () {
var promise = $http.get('data/').then(function (response) {
return response;
});
return promise;
}
};
return dataObject;
})
controller.js
$scope.dataTest = [];
$scope.ticketed = false;
var getData = function(){
dataService.async().then(function (d) {
$scope.dataTest = d.data;
});
}
getData();
html
<input type="checkbox" ng-model="ticketed">
<div ng-show="ticketed" ng-repeat="dat in dataTest">
{{dat.name}}
</div>
...this is tested case so it should work with yours
You can make a REST call to fetch the data from your java function and store it in scope.Then you can use ng-repeat to display data in dropdown.
Here is a very good article on how to do it.
http://www.infragistics.com/community/blogs/dhananjay_kumar/archive/2015/06/29/how-to-work-with-the-bootstrap-dropdown-in-angularjs.aspx
http://plnkr.co/edit/pJRzKn2v1s865w5WZBkR?p=preview
I have a large select dropdown form which is repeated in 2 places. The only thing that changes is the first select tag, which has a different function.
<!--
On simple, change ng-change function to functionOne
On advanced, change ng-change function to functionTwo
-->
<select name="name1" ng-change="functionOne('function1')" id="the-id-1">
<select name="name2" ng-change="functionTwo('function2)" id="the-id-2">
<option value="aaa">aaa</option>
<option value="bbb">bbb</option>
<option value="ccc">ccc</option>
</select>
I tried using ng-hide ng-show however there must be a different way to accomplish this.
var app = angular.module('myApp', [])
.directive('termsForm', function() {
return {
templateUrl : "termsForm.html",
restrict : "E",
scope : false,
controller : 'TermsFormController'
}
})
.directive('selectOptions', function() {
return {
templateUrl : "form.html",
restrict : "E",
scope : false
}
})
.controller('TermsFormController',
['$scope',
function($scope) {
var vs = $scope;
vs.hello = "This is the form.";
vs.showingSimple = true;
vs.showingAdvanced = false;
vs.showForm = function(type) {
if (type === 'simple') {
vs.showingSimple = true;
vs.showingAdvanced = false;
} else if (type === 'advanced') {
vs.showingSimple = false;
vs.showingAdvanced = true;
}
}
vs.functionOne = function(msg) {
alert(msg);
}
vs.functionTwo = function(msg) {
alert(msg);
}
}]);
termsForm.html
<ul class="nav nav-tabs">
<button class="btn btn-info" ng-click="showForm('simple')">Simple</button>
<button class="btn btn-info" ng-click="showForm('advanced')">Advanced</button>
</ul>
<p>The select:</p>
<div ng-show="showingSimple" class="simple-form">
<p>Simple</p>
<select-options></select-options>
</div>
<div ng-show="showingAdvanced" class="advanced-form">
<p>Advanced</p>
<select-options></select-options>
</div>
You already have a directive created for your select, that gets you half way there. Now you just need to pass the function in through whats known as the isolated scope.
.directive('selectOptions', function() {
return {
templateUrl : "form.html",
restrict : "E",
scope : {
changeFunc: '&'
}
}
})
This allows you to pass in the function you want to call on the ng-change event:
<select-options changeFunc="function1"></select-options>
<select-options changeFunc="function2"></select-options>
And then in your form.html you simply put
<select name="name2" ng-change="changeFunc()" id="the-id-2">
This way you are basically passing the funciton in as a parameter. Read this blog for a great guide on isolated scopes.
I would just refactor your markup and controller to adapt based on the simple/advanced context.
In your controller, you'd expose a 'generic' on change function for the dropdown, first...
(function () {
'use strict';
angular.module('app').controller('someCtrl', [someCtrl]);
function someCtrl() {
var vm = this;
vm.isSimple = true;
vm.nameChange = function () {
if(vm.isSimple)
functionOne('function1');
else
functionTwo('function2');
}
// Other things go here.
}
})();
...Then, on your view, your select would change to this*:
<select id="someId" name="someName" ng-change="vm.nameChange()" />
*: Assuming you're using controllerAs syntax, that is. If you're not, don't prepend the vm. on the select.
I have a page design in which i have attached the main controller to body:
<body ng-controller="firstController">
first
second
<input ng-model="hello" ng-disabled="xyz()">
<button id="test" ng-disabled="xyz()">test button</button>
{{hello}}
<div ng-view></div>
</body>
I load a template for default as
var mainApp = angular.module('mainApp',['ngRoute'])
.config(['$routeProvider',function($routeProvider){
$routeProvider.when('/',{
templateUrl: 'partials/first.html',
controller: 'firstTemplate'
})
I my template i a check box as:
<div>
<input type="checkbox" ng-model="check">
</div>
Now i want the button #id to be disable the check box is unchecked, now i thought of using factory as these two are in different controllers:
mainApp.factory('clientId',function(){
var flag = true;
return flag;
});
mainApp.controller('firstController',['$scope','clientId',function($scope,clientId){
//$scope.check = true;
clientId.flag = false;
$scope.xyz = function(){
if(clientId){
return true;
}else{
return false;
}
}
}])
I am able to get the value from factory, now i want to update the value of the flag from different controller(template controller) and the value should reflect in first controller too so that the state of button can be updated.
mainApp.controller('firstTemplate',['$scope','clientId',function($scope,clientId){
}])
How can i update the value from second controller and make it reflect in first controller. If it is not possible is there and alternative to achieve this?
You can solve this using two ways.
1. using $rootScope.
2. using services.
using $rootScope:
<input ng-model="hello" ng-disabled="flagtoDisable">
<button id="test" ng-disabled="flagtoDisable">test button</button>
{{hello}}
<div ng-view></div>
mainApp.controller('firstController', ['$scope','$rootScope','clientId',function($scope,$rootScope,clientId){
//$scope.check = true;
clientId.flag = false;
$scope.xyz = function(){
if(clientId){
return true;
}else{
return false;
}
}
}])
mainApp.controller('firstTemplate','$scope','$rootScope','clientId',
function($scope,$rootScope,clientId){
$rootScope.flagtoDisable = false;
if($scope.check == true){
$rootScope.flagtoDisable = true;
}
}])
using Service:
mainApp.factory('clientId',function(){
var flag = {
status:false; };
return{
setFlag : funcion() {
flag.status = true;
}
getFlag : funcion() {
return flag;
}
});
mainApp.controller('firstController',['$scope','clientId',function($scope,clientId){
//$scope.check = true;
$scope.xyz = function(){
var flag = clientId.getFlag();
return flag.status;
}
}])
<input ng-model="hello" ng-disabled="xyz()">
<button id="test" ng-disabled="xyz()">test button</button>
{{hello}}
<div ng-view></div>
mainApp.controller('firstTemplate',['$scope','clientId',function($scope,clientId){
if($scope.check== true){
clientId.setFlag();
}
}])
This code is not tested.you can follow this approaches.
Yes, You can do it by using $rootScope
The ways are.
Initialize the $rootScope in your controller
Call the first controller scope variable from second controller
if 1st controller varaiable is $scope.name
now you just call $rootScope instead of $scope in second controller
like
$rootScope.name
I am having a lot of trouble trying to save values from the modal component available in Angular UI.
Here is the page controller that calls the modal dialog
$scope.sourceSchema = [];
$scope.targetSchema = [];
$scope.apiDefinition = [];
$scope.availableSchemas = availableSchemas.get();
$scope.addComponent = function (type) {
$scope.$broadcast('addComponent', [type]);
var templateUrl = "";
var controller = null;
var resolve = null;
var componentSchema = [];
switch (type) {
case "sourceSchema":
templateUrl = 'source-schema.tpl.html';
controller = 'SourceCtrl';
componentSchema = $scope.sourceSchema;
break;
case "targetSchema":
templateUrl = 'target-schema.tpl.html';
controller = 'TargetCtrl';
componentSchema = $scope.targetSchema;
break;
case "api":
templateUrl = 'api.tpl.html';
controller = 'SourceCtrl';
componentSchema = $scope.apiDefinition;
break;
}
var modalInstance = $modal.open({
templateUrl: templateUrl,
controller: controller,
resolve: {
existingSchemas: function () {
return $scope.availableSchemas;
}
}
});
modalInstance.result.then(function (selectedItem) {
componentSchema.push(selectedItem);
}, function () {
// $log.info('Modal dismissed at: ' + new Date());
});
};
Here is the SourceCtrl that controls one of the modal dialogs I am using:
.controller("SourceCtrl", function ($scope, $modalInstance, existingSchemas) {
$scope.existingSchemas = existingSchemas;
$scope.sourceSchema = "";
$scope.ok = function () {
$modalInstance.close($scope.sourceSchema);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
$scope.$watch('sourceSchema', function(newValue, oldValue) {
console.log(newValue, oldValue);
})
})
And finally here is the template for this controller (SourceCtrl).
<div class="modal-header">
<h3>New Source Schema</h3>
</div>
<div class="modal-body">
<div class="row">
<div class="col-xs-3">
<label for="schema-source">Source</label>
</div>
<div class="col-xs-9">
<select name="sourceSchema" ng-model="sourceSchema" ng-options="s as s.name for s in existingSchemas">
<option value="">-- choose source --</option>
</select>
</div>
<h5>Name: {{sourceSchema.name}}</h5>
</div>
</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>
The funny thing is that when I change the value in the select, the {{sourceSchema.name}} line does show the correct name of the schema, however the changes do not get reflected in the controller and the actual value is not being passed on. I have used a watch to detect when something gets changed and apparently it doesn't. But the value does get changed otherwise why would it get displayed when I select it in the dropdown list.
Make sure that you've got a dot in your ngModel expression - that is - that you are binding to an object property and not directly to the scope. Something like:
.controller("SourceCtrl", function ($scope, $modalInstance, existingSchemas) {
$scope.existingSchemas = existingSchemas;
$scope.source = {
schema: ''
};
$scope.ok = function () {
$modalInstance.close($scope.source.schema);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
$scope.$watch('source.schema', function(newValue, oldValue) {
console.log(newValue, oldValue);
})
})
And then, in your markup:
<select name="sourceSchema" ng-model="source.schema" ng-options="s as s.name for s in existingSchemas">
<option value="">-- choose source --</option>
</select>
If you can provide a plunker I can help you fixing the code.