Is there any way to inject error manually to form, I know the way via directive but not sure how can inject error from the controller.
<div ng-controller="myController">
<form name="createForm">
<div ng-repeat="item in someItems">
<input type="text" ng-change="customValidation()" />
</div>
<input type="button" ng-disabled="createForm.$invalid" value="Submit" />
</form>
</div>
controller
function myController($scope) {
$scope.customValidation = function() {
//do some validation and made createForm valid/invalid based on it
};
}
Yes, You can do it in two ways.
instead of Creaeform.$invalid. You can use some value inside your scope.
You should set the value true or false depending on the validation result of the input. If this doesn't make sense to you, give a comment. I'll give some code.
another way is passing the form object itself to the controller and set the createForm.$valid = false; in the controller.
Related
I am trying to submit a form, but the values are always empty.
my HTML:
<form novalidate name="creditCardForm" id="creditCardForm" method="POST">
<input type="hidden" name="EPS_MERCHANT" value="{{credit.data.merchantId}}">
<input type="hidden" name="EPS_TIMESTAMP" value="{{credit.data.currentGMTTimestamp}}">
<input type="hidden" name="EPS_TYPE" value="{{credit.data.epsType}}">
<div class="text-center">
<button class="btn btn-primary" ng-click="credit.save()">Save</button>
</div>
</form>
and my js part:
function save(){
document.getElementById("creditCardForm").setAttribute("action", this.data.crnUrl)
document.forms["creditCardForm"].submit()
}
and from inspection, these fields all have values
but from the request, these fields are all empty:
update my question:
because this is a special form post that it will call NAB bank api to verify something, so I cannot put each fields into an object and do a ajax/$resource/$http call.
thanks
That's a not angular way to submit the form via action attribute. Use ng-submit form attribute and make a $http.post request async.
<form novalidate name="creditCardForm" id="creditCardForm"
ng-submit="saveCredit(creditCardForm)">
<!-- no input hidden -->
<div class="text-center">
<button class="btn btn-primary">Save</button>
</div>
</form>
And you dont need hidden inputs in this way.
If I get your question and your requirement correct. You should be using following way:
<form novalidate name="creditCardForm" id="creditCardForm" method="POST">
<input type="hidden" name="EPS_MERCHANT" ng-model="credit.data.merchantId">
<input type="hidden" name="EPS_TIMESTAMP" ng-model="credit.data.currentGMTTimestamp">
<input type="hidden" name="EPS_TYPE" ng-model="credit.data.epsType">
<div class="text-center">
<button class="btn btn-primary" ng-click="credit.save(credit.data)">Save</button>
</div>
</form>
This is assuming that credit is the alias for your controller.
I have tried to keep your ways of ng-click to call a method on controller. However with forms in angular, you can do the same via ng-submit directive also.
In your controller you will have something like:
$scope.save = function(data){
//use data here as you like
//data.merchantId and other fields
}
If you are using alias form, then use:
//vm or any other name you have for your `this` instance
vm.save = function(){
// use data here as you like
}
I want to try to fix your problem. The first thing that you have to do is add ng-model and ng-value in your form. For example:
view:
<form novalidate name="creditCardForm" id="creditCardForm" ng-submit="save()">
<input type="hidden" ng-model="credit_card.eps_merchant" name="eps_timestamp" ng-value="{{credit.data.merchantId}}">
<input type="hidden" ng-model="credit_card.eps_timestamp" name="eps_timestamp" ng-value="{{credit.data.currentGMTTimestamp}}">
<input type="hidden" ng-model="credit_card.eps_type" name="eps_type" ng-value="{{credit.data.epsType}}">
<div class="text-center">
<button type="submit" class="btn btn-primary">Save</button>
</div>
</form>
For the next you can create controller. For example:
angular controller:
angular.module('cartApp')
.controller('AddCreditCartCtrl', [
'$scope',
'$location',
'$http',
function($scope, $location, $http) {
$scope.credit_card = {};
$scope.credit.data = {
merchantId: 'your-merchant-id',
currentGMTTimestamp: 'your-currentGMTTimestamp',
epsType: 'your-epsType'
}
$scope.save = function () {
$http.post('/yourUrl', {credit_card: $scope.credit_card}).then(function(res){
// Successfully create data
},
function(response) {
// Failed to create data
});
}
}]);
I hope this can help you. :)
thanks every body above. just want to share the root cause
I have a directive called <credit-card></credit-card>, and inside this directive, I have the form, with both name and id to be creditCardForm, so when this directive is used in several places, and in the controller I use document.forms["creditCardForm"], js did not know which is the target form, and this results in empty values in the request
hope it can help someone with same problem
I need to be able to see in the Angular controller if the datepicker is pristine or not. Tried all sorts of things including sending the pristine value in a method but cannot get this value. Below is the view code:
<form name="myForm">
<!-- Datepicker From -->
<div class="small-6 medium-5 large-2 columns" ng-if="vm.subViewActive">
<div class="input-group">
<input name="valuationDatePickerFrom" ng-model="name" type="text" class="datepicker" id="valuationDatePickerFrom" placeholder="DD/MM/YYYY" pikaday="vm.datePickerFrom" on-select="vm.selectStartDate(pikaday)" year-range="{{ vm.yearRange }}" >
<div class="input-group-addon">
<label for="valuationDatePickerFrom" class="postfix">
<i class="fa fa-calendar"></i> From
</label>
</div>
</div>
</div>
</form>
and then I also tried :
var isPristine = $scope.myForm.valuationDatePickerFrom.$pristine;
console.log(isPristine);
in my controller but cannot get the pristine value. Read lots of posts here but mainly to do with CSS classes and front-end control or setting the pristine state from the backend not getting or checking the pristine state.
Thanks anybody that can help.
You are using:
var isPristine = $scope.myForm.valuationDatePickerFrom.$pristine;
but your form's name is not myForm.
Change <input name="name"... <input name="valuationDatePickerFrom"...
Then you can use:
var isPristine = $scope.userForm.valuationDatePickerFrom.$pristine;
Also, the controller is getting called before the view is created, so no myForm exists at the time the controller runs. Try adding a $timeout like so:
$timeout(function() {
var isPristine = $scope.userForm.valuationDatePickerFrom.$pristine;
console.log(isPristine);
}, 100);
plunkr
The above solution only works on page load, but you need to know this value when the page is being used. Instead pass the value to the controller when an action happens:
<form name="myForm">
<input type="text" name="valuationDatePickerFrom" ng-model="valuationDatePicker" ng-blur="alerty(myForm.$pristine)">
</form>
.controller('MainController', function($scope) {
$scope.alerty = function(isPristine){
alert('isPristine: ' + isPristine);
};
https://plnkr.co/edit/f0EWvYmoXCn8UOH3QCfE?p=preview
How to get form by name in $scope?
Test example:
<div ng-controller="solod">
<form name="good_f">
<input type="text" name="super">
</form>
</div>
<script>
function solod($scope){
console.log($scope.good_f) //undefined
}
</script>
Is it possible?
Thank you
You usually don't want the controller to access the form like this, that's coupling the controller to the structure of the view too tightly. Instead, pass the form to the controller like this...
<div ng-controller="solod">
<form name="good_f" ng-submit="submit(good_f)">
<input type="text" name="super">
</form>
</div>
<script>
function solod($scope){
$scope.submit = function(theForm){
console.log(theForm)// not undefined
console.log($scope.good_f) // will exist now also
};
// do stuff in a watch
$scope.$watch("good_f", function(formVal){ console.log(formVal);});
}
</script>
Otherwise, if you just want to track the value of the text input, give it an ng-model
Edit:
On further research, $scope will have good_f as a property, just not when you're logging it in the constructor. You could set up a watch on good_f if you wanted, but I still think you should pass it in.
name (optional) string Name of the form. If specified, the form
controller will be published into related scope, under this name.
https://docs.angularjs.org/api/ng/directive/form
Another possible way is to use ng-form, this will help you to access the form via scope easily.
<div ng-controller="solod">
<ng-form name="good_f">
<input type="text" name="super">
</ng-form>
</div>
Script code in your controller:
EDIT:
As JeremyWeir mentioned, to solve your problem you can use $timeout service of angularjs
function solod($scope){
$timeout(function(){
console.log($scope.good_f);
});
}
Caution: Don't use this - seriously
Angular is not jQuery.
As par as your question is concerned you can use $element in your controller(if you are not concrete with the $scope usage for this use case) -
myApp.controller("myCtrl", function($scope, $element){
alert($element.find('form').attr('name'));
$scope.myFormName = $element.find('form').attr('name');
});
PLNKR DEMO
The original question asked about how to determine which element called the controllers blurr function, but I didn't clarify that I was not specifically asking about ng-blur, but ng-* (ng-change, ng-focus, ng-mouseover, ng-*) in general. So, with that in mind:
How do I determine which element input is calling the blurr() and/or check() functions?
html
<body ng-app="test">
<div ng-controller="Cntrlr as cntrlr">
<form name="meta_test">
<input type="text" name='inpt' ng-model="cntrlr.inpt" ng-blur="cntrlr.blurr()" ng-change="cntrlr.check()" />
<input type="text" name='second' ng-model="cntrlr.second" ng-blur="cntrlr.blurr()" ng-change="cntrlr.check()" />
</form>
</div>
</body>
js
var app = angular.module("test", []);
app.controller("Cntrlr", ["$scope", function($scope){
this.blurr = function(){
alert("which input am I?");
alert("this is so meta.");
// ?
};
this.check = function(){
alert("this is how meta I am:");
alert(this);
}
$scope.Cntrlr = this; // see: (reference)
return $scope.Cntrlr;
}]);
You may be asking yourself "why would he want to do this?"
There are 2 reasons:
because I want to call:
$scope.user_form[meta_test.[(whatever this element is.name)]].$setValidity('spike', false);
because I'm curious. There has to be a simple way to do this.
(reference):
controller as syntax
Use this -
<input type="text" name='inpt' ng-model="cntrlr.inpt" ng-blur="cntrlr.blurr($event)" ng-change="cntrlr.check()" />
This returns the jQuery lite version of the event that causes the blurr function. Once you receive this element in your controller, you can pretty much do whatever you want with it.
The .target attribute of the event will give you the required element.
Should work
Try this:
<form name="meta_test">
<input type="text" name='inpt' ng-model="cntrlr.inpt" ng-blur="cntrlr.blurr()"
ng-change="cntrlr.check('One')" />
<input type="text" name='second' ng-model="cntrlr.second"
ng-blur="cntrlr.blurr()" ng-change="cntrlr.check('Two')" />
</form>
In JS,
this.check = function(Type){
if(Type == "One"){
//Then it is the first text box.
}else if(Type == "Two"){
//Then it is the second text box.
}
}
I'm using Angular and attempting to show a button to a form only when the object changes that the form manipulates.
html:
<input ng-model="form.field1" />
<input ng-model="form.field2" />
<div ng-show="formChanged">Show button</div>
controller:
$scope.form = {
field1: 'hello'
}
$scope.$watch('form', function(){
$scope.formChanged = true;
});
I was under the impression that $watch would fire whenever any part of the object changed. It seems, however, that the $watch is called at the very beginning and only once after the object changes.
I have a plunker here: http://plnkr.co/edit/Hv8oLLviOzSLMUg2iBXt
Parenthetical information:
I have found that if I set $watch to explicitly look at each property that the $watch functions as I expect it to, though it still is run at the beginning.
To stop it from being called at the beginning I've tried to use the newValue and oldValue variables as follows:
$scope.$watch('form', function(newVal, oldVal){});
but that doesn't work either.
Use $dirty property from the FormController, or set the third parameter on $watch callback to true for object equality comparison.
Solution A:
<form ng-submit="submit()" name="myForm">
<div>
<input type="email" name="email" ng-model="formData.email" required />
<span ng-show="myForm.email.$dirty && myForm.email.$error.required">required</span>
</div>
<div>
<button ng-show="myForm.$dirty" type="submit">Submit</button>
</div>
</form>
Solution B:
$scope.$watch('form', function(){
$scope.formChanged = true;
}, true);