AngularJS check if form is valid in controller - angularjs

I need to check if a form is valid in a controller.
View:
<form novalidate=""
name="createBusinessForm"
ng-submit="setBusinessInformation()"
class="css-form">
<!-- fields -->
</form>
In my controller:
.controller(
'BusinessCtrl',
function ($scope, $http, $location, Business, BusinessService,
UserService, Photo)
{
if ($scope.createBusinessForm.$valid) {
$scope.informationStatus = true;
}
...
I'm getting this error:
TypeError: Cannot read property '$valid' of undefined

Try this
in view:
<form name="formName" ng-submit="submitForm(formName)">
<!-- fields -->
</form>
in controller:
$scope.submitForm = function(form){
if(form.$valid) {
// Code here if valid
}
};
or
in view:
<form name="formName" ng-submit="submitForm(formName.$valid)">
<!-- fields -->
</form>
in controller:
$scope.submitForm = function(formValid){
if(formValid) {
// Code here if valid
}
};

I have updated the controller to:
.controller('BusinessCtrl',
function ($scope, $http, $location, Business, BusinessService, UserService, Photo) {
$scope.$watch('createBusinessForm.$valid', function(newVal) {
//$scope.valid = newVal;
$scope.informationStatus = true;
});
...

Here is another solution
Set a hidden scope variable in your html then you can use it from your controller:
<span style="display:none" >{{ formValid = myForm.$valid}}</span>
Here is the full working example:
angular.module('App', [])
.controller('myController', function($scope) {
$scope.userType = 'guest';
$scope.formValid = false;
console.info('Ctrl init, no form.');
$scope.$watch('myForm', function() {
console.info('myForm watch');
console.log($scope.formValid);
});
$scope.isFormValid = function() {
//test the new scope variable
console.log('form valid?: ', $scope.formValid);
};
});
<!doctype html>
<html ng-app="App">
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.min.js"></script>
</head>
<body>
<form name="myForm" ng-controller="myController">
userType: <input name="input" ng-model="userType" required>
<span class="error" ng-show="myForm.input.$error.required">Required!</span><br>
<tt>userType = {{userType}}</tt><br>
<tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>
<tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>
<tt>myForm.$valid = {{myForm.$valid}}</tt><br>
<tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>
/*-- Hidden Variable formValid to use in your controller --*/
<span style="display:none" >{{ formValid = myForm.$valid}}</span>
<br/>
<button ng-click="isFormValid()">Check Valid</button>
</form>
</body>
</html>

The BusinessCtrl is initialised before the createBusinessForm's FormController.
Even if you have the ngController on the form won't work the way you wanted.
You can't help this (you can create your ngControllerDirective, and try to trick the priority.) this is how angularjs works.
See this plnkr for example:
http://plnkr.co/edit/WYyu3raWQHkJ7XQzpDtY?p=preview

I like to disable the save/submit button if the form is invalid:
<form name="ruleForm">
<md-input-container>
<label>Priority</span>
<input name="description" ng-model="vm.record.description" required>
</md-input-container>
<md-button ng-click="vm.save()" ng-disabled="ruleForm.$invalid" class="md-primary md-raised">Save</md-button>
</form>

Related

Adding ng-model directive to dynamically created input tag using AngularJs

I am trying that on a button click, a div and and input tag are created and the input tag contain ng-model and the div has binding with that input.
Kindly suggest some solution.
You can create the div and input beforehand and and do not show it by using ng-if="myVar". On click make the ng-if="true".
<button ng-click="myVar = true">
In controller : $scope.myVar = false;
$scope.addInputBox = function(){
//#myForm id of your form or container boxenter code here
$('#myForm').append('<div><input type="text" name="myfieldname" value="myvalue" ng-model="model-name" /></div>');
}
Here is another solution, in which there's no need to create a div and an input explicitly. Loop through an array of elements with ng-repeat. The advantage is that you will have all the values of the inputs in that array.
angular.module('app', [])
.controller('AppController', AppController);
AppController.$inject = ['$scope'];
function AppController($scope) {
$scope.values = [];
$scope.add = function() {
$scope.values.push('');
};
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="AppController">
<button ng-click="add()">Click</button>
<div ng-repeat="value in values track by $index">
<input type="text" ng-model="values[$index]"/>
<div>{{values[$index]}}</div>
</div>
<pre>{{values}}</pre>
</div>
UPDATE. And if you want only one input, it's even simpler, using ng-show.
angular.module('app', []);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<button ng-click="show = true">Click</button>
<div ng-show="show">
<input type="text" ng-model="value"/>
<div>{{value}}</div>
</div>
</div>
You should use $compile service to link scope and your template together:
angular.module('myApp', [])
.controller('MyCtrl', ['$scope', '$compile', '$document' , function MyCtrl($scope, $compile, $document) {
var ctrl = this;
var inputTemplate = '<div><span ng-bind="$ctrl.testModel"></span>--<span>{{$ctrl.testModel}}</span><input type="text" name="testModel"/></div>';
ctrl.addControllDynamically = addControllDynamically;
var id = 0;
function addControllDynamically() {
var name = "testModel_" + id;
var cloned = angular.element(inputTemplate.replace(/testModel/g, name)).clone();
cloned.find('input').attr("ng-model", "$ctrl." + name); //add ng-model attribute
$document.find('[ng-app]').append($compile(cloned)($scope)); //compile and append
id++;
}
return ctrl;
}]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//code.angularjs.org/1.6.2/angular.js"></script>
<div ng-app="myApp">
<div ng-controller="MyCtrl as $ctrl">
<input type="button" value="Add control dynamically" ng-click="$ctrl.addControllDynamically()"/>
</div>
</div>
UPDATE: to add a new compiled template each time the button is clicked, we need to make a clone of the element.
UPDATE 2: The example above represents a dirty-way of manipulating the DOM from controller, which should be avoided. A better (angular-)way to solve the problem - is to create a directive with custom template and use it together with ng-repeat like this:
angular.module('myApp', [])
.controller('MyCtrl', ['$scope', function MyCtrl($scope) {
var ctrl = this;
ctrl.controls = [];
ctrl.addControllDynamically = addControllDynamically;
ctrl.removeControl = removeControl;
function addControllDynamically() {
//adding control to controls array
ctrl.controls.push({ type: 'text' });
}
function removeControl(i) {
//removing controls from array
ctrl.controls.splice(i, 1);
}
return ctrl;
}])
.directive('controlTemplate', [function () {
var controlTemplate = {
restrict: 'E',
scope: {
type: '<',
ngModel: '='
},
template: "<div>" +
"<div><span ng-bind='ngModel'></span><input type='type' ng-model='ngModel'/></div>" +
"</div>"
}
return controlTemplate;
}]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//code.angularjs.org/1.6.2/angular.js"></script>
<div ng-app="myApp">
<div ng-controller="MyCtrl as $ctrl">
<input type="button" value="Add control dynamically" ng-click="$ctrl.addControllDynamically()"/>
<div ng-repeat="control in $ctrl.controls">
<control-template type="control.type" ng-model="control.value"></control-template>
</div>
</div>
</div>

Component binding not working : Angularjs

Hi I'm trying to create a component, it works fine in controller, however not binding values to view.
My Component is as below
app.component("bdObjects", {
templateUrl: "app/templates/components/BusinessObjects.html",
controller: ["$scope", "$http", "$log", "API_ROOT", "VisDataSet",
function ($scope, $http, $log, API_ROOT, VisDataSet) {
$scope.fnAdd = function() {
$scope.objectId = "";
$scope.objectName = "Test Object";
console.log($scope.objectName);
}
$scope.cancelAdd = function() {
if($scope.items.length > 0) {
$log.info($scope.items[0]);
$scope.fnPopulateForm($scope.items[0]);
}
}
}],
bindings: {
data: "=",
objectId: "=",
objectName: "="
}
});
My Template
<div class="general-form">
<input type="hidden" name="id" ng-model="objectId">
<label>Name:</label>
<br>
<input class="form-control" name="name" placeholder="Name" ng-model="objectName">
<br>
</div>
So on add button I tried to assign value to input box. but it's not taking. and I want to make that two way binding. so later I'll have save button, so changing the value in TextBox will replace in Controller.
Thanks.
In controller, change $scope by this or some alias, e.g.
controller: ["$scope", "$http", "$log", "API_ROOT", "VisDataSet",
function ($scope, $http, $log, API_ROOT, VisDataSet) {
var ctrl = this;
ctrl.fnAdd = function() {
ctrl.objectId = "";
ctrl.objectName = "Test Object";
console.log(ctrl.objectName);
}
// Not sure about items: you haven't defined it,
// neither fnPopulateForm...
ctrl.cancelAdd = function() {
if(ctrl.items.length > 0) {
$log.info($scope.items[0]);
ctrl.fnPopulateForm(ctrl.items[0]);
}
}
}],
And in view, use the default controller binding i.e $ctrl
<div class="general-form">
<input type="hidden" name="id" ng-model="$ctrl.objectId">
<label>Name:</label>
<br>
<input class="form-control" name="name" placeholder="Name" ng-model="$ctrl.objectName">
<br>
</div>
You can also change $ctrl into whatever you want in a controllerAs declaration of the component, i.e.
app.component("bdObjects", {
templateUrl: "app/templates/components/BusinessObjects.html",
controller: ["$scope", "$http", "$log", "API_ROOT", "VisDataSet",
function ($scope, $http, $log, API_ROOT, VisDataSet) {
//...
}],
controllerAs: 'bd',
bindings: {
//...
}
});
and in the view:
I tried with $timeout() and it got working.
Hey check this JS fiddle
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="namesCtrl">
<input type="hidden" name="id" ng-model="objectId">
<label>Name:</label>
<br>
<input class="form-control" name="name" placeholder="Name" ng-model="objectName">
<br>
<button ng-click="fnAdd()">
button
</button>
</div>
<script>
angular.module('myApp', []).controller('namesCtrl', function($scope) {
$scope.fnAdd = function() {
$scope.objectId = "";
$scope.objectName = "Test Object";
console.log($scope.objectName);
}
$scope.cancelAdd = function() {
if ($scope.items.length > 0) {
$log.info($scope.items[0]);
$scope.fnPopulateForm($scope.items[0]);
}
}
});
</script>

$valid method not working in Angular

I am not able to get the $valid method working on the form. I need to get this working for the form validation, not sure where I am going wrong. Here is the angular code below where I am trying to write the output to the console.
<body ng-app="submitExample">
<script>
angular.module('submitExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.list = [];
$scope.text = 'hello';
$scope.submit = function() {
console.log('is email valid? ' + myform.$valid)
if ($scope.text) {
$scope.list.push(this.text);
$scope.text = '';
}
};
}]);
</script>
<form name="myForm" novalidate ng-submit="submit()" ng-controller="ExampleController">
Enter text and hit enter:
<input type="text" ng-model="text" name="text" />
<label>Email:</label>
<input type="email" ng-model="email"/>
<input type="submit" id="submit" value="Submit" />
<pre>list={{list}}</pre>
</form>
</body>
Try like this
HTML
ng-submit="submit(myForm)"
JS
$scope.submit = function(form) {
console.log(form.$valid)
}

How to access form validation properties in the controller

As seen here:
https://docs.angularjs.org/api/ng/input/input%5Bemail%5D
for example, how to access the template var:
{{myForm.input.$valid}}
in the controller?
$scope.myForm.input.$valid
doesnt do it
You can add $watch to $scope.myForm.input.$valid.
Here is working example.
<script>
angular.module('test', [])
.controller('formController', ['$scope', function($scope) {
$scope.myForm = {};
$scope.$watch('myForm.input.$valid', function(newVal) {
$scope.valid = newVal;
});
}]);
</script>
<form name="myForm" ng-controller="formController">
Email: <input type="email" name="input" ng-model="text" required>
{{ myForm.input.$valid }}
{{ valid }}
</form>

Access form element in ng-Submit

I am new to angular js and I am struck with accessing the form element in ng-submit function.
My intention is to set the action attribute dynamically and submit the form rather using jquery selector and setting the action attribute.
<div ng-app="MyApp">
<form name="myForm" ng-controller="myController"
ng-submit="SubmitFunction(myForm)">
<input type="submit" value="Submit" />
</form>
</div>
JS:
var myApp = angular.module("MyApp",[]);
myApp.controller("myController", ["$scope", function ($scope) {
$scope.SubmitFunction = function (formElement) {
//Set action attribute ???
//Submit the form ????
};
}]);
Thanks for ur help. Finally found a solution.
<div ng-app="MyApp">
<form name="myForm" ng-controller="myController"
ng-submit="SubmitFunction($event)">
<input type="submit" value="Submit" />
</form>
</div>
JS:
var myApp = angular.module("MyApp",[]);
myApp.controller("myController", ["$scope", function ($scope) {
$scope.SubmitFunction = function (e) {
var formElement = angular.element(e.target);
formElement.attr("action", actionLink);
formElement.submit();
};
}]);

Resources