Angular Form Undefined In Controller - html

Have an angular form that I'm passing into my controller.
When I open browser to inspect form, it is undefined. I've tried changing the name of the form, and moving the form tag to enclose the entire body. Here is my form:
<form layout-padding id="form-container" ng-controller="RegisterController as RgCtrl" layout="column" ng-cloak name="projectForm">
<div id="content-row-header">What is your email?</div>
<md-input-container class="md-block md-input-focused">
<label>Email</label>
<input required type="email" name="email" ng-model="email"
minlength="10" maxlength="100" ng-pattern="/^.+#.+\..+$/" />
<div ng-messages="projectForm.email.$error" role="alert">
<div ng-message-exp="['required', 'minlength', 'maxlength', 'pattern']">
Your email must be between 10 and 100 characters long and look like an e-mail address.
</div>
</div>
</md-input-container>
<div id="content-row-header">Set a password</div>
<md-input-container class="md-block md-input-focused">
<label>Password</label>
<input required name="password" ng-model="password">
<div ng-messages="projectForm.password.$error">
<div ng-message="required">This is required.</div>
</div>
</md-input-container>
</form>
Here is my function call:
<md-button id="orange-button" ui-sref="app.unauthenticated.purchase.agent" ng-click="doRegistration(projectForm)" flex>Create Account</md-button>
and here is my controller:
(function () {
'use strict';
angular
.module('app.auth.register')
.controller('RegisterController', RegisterController);
/** #ngInject */
function RegisterController($scope, $auth, $log, $location,$rootScope,$state,app_auth,$stateParams) {
// Data
var vm = this;
// Methods
$scope.doRegistration = function (form) {
console.log(form);
app_auth.register(form.email.$viewValue,form.password.$viewValue,form.passwordConfirm.$viewValue);
};
// $scope.goHome = function () {
/
/ $state.go('app.public');
// };
}
})();
right now when that console.log(form) runs, form is undefined

If you have some conditional directive in the form:
<form name="myForm" ng-if="someVariable">
Then $scope.myForm will be undefined in your controller.
Besides, you should use ng-submit.

you are using a directive.
The directive scope is different from the controllers. That's why you are not able to see the form reference.
GO to directive implementation and add:
scope: {
projectForm: '=',
},
reference: https://www.sitepoint.com/form-based-directives-angularjs/

name attribute will bind form controller to $scope, so you have name="projectForm" in your controller you should be able
to use $scope.projectForm
check jsfiddle here
https://jsfiddle.net/hurricanew/6tqywue6/

Register Controller had to encompass the form definition and function that took in a form as argument

Related

How to dynamically add ng-model name to template added dinamically with ng-repeat and button click?

I have a template app/views/templates/destForm.tpl.html
<div class="row">
<div class="col-sm-8">
<div class="form-group">
<label>Departure</label>
<input class="form-control form-control-rounded input-lg" type="text" ng-model="???????" />
</div>
</div>
</div>
I include it in my html page like this:
<form action="" name="formPackages">
<div ng-repeat="form in destForms track by $index">
<dest-form></dest-form>
</div>
...
In my controller I've got this code:
$scope.destForms = [];
$scope.addForm = function(){
var formIndex = $scope.destForms.length + 1;
$scope.destForms.push('app/views/templates/destForm.tpl.html');
}
$scope.addForm();
EDIT 1: (suggested in comments)
This is my directive.
function destForm () {
return {
restrict: 'E',
transclude: true,
scope: {
ngModel: '<'
},
bindToController: true,
controllerAs: '$quoteAskCtrl',
templateUrl: 'app/views/templates/destForm.tpl.html',
controller: 'quoteAskCtrl'
};
}
EDIT 2
How can I set ng-model within the template html to be available within the $scope of my controller? User may have the option to make just one departure or several, that's what I add dynamically with
EDIT 3
This is what I'm trying to reach, so when form submitted, I need to loop within this departure-destinations to post them to my DB.
I'm trying to add a template for each "departure" the user has to make.
How to add ng-model dynamically so I can collect data in my controler to make an $http.post?
Thanks in advance.
In your directive:
<input class="form-control form-control-rounded input-lg" type="text" ng-model="$quoteAskCtrl.ngModel" />
and your html:
<form action="" name="formPackages">
<div ng-repeat="form in destForms track by $index">
<dest-form ng-model="form"></dest-form>
</div>
explanation:
Your directive expects to receive propety as 'ngModel' from the parent object.
Because you have set:controllerAs: '$quoteAskCtrl',
You need to access it this way:ng-model="$quoteAskCtrl.ngModel"

Getting hardcoded value from input tag into angular controller

I am using angularjs in my application.I am trying to pass hardcoded value from input tag into angularjs controller.Here i am not taking any dynamic values.User just clicks the input area.Based on clicked area i am passing value into angular controller.
Here is my html
<div class="first-hour">
<input type="text" value="12:00am - 12:30am" readonly>
</div>
<div class="second-hour">
<input type="text" value="12:30am - 01:00am" readonly>
</div>
If the user select first input text box value is 12:00am - 12:30am and if second means value is 12:30am - 01:00am.I need to get these values inside angular controller.Can anyone tell how to get the input hardcoded values directly into angularjs controller?
Here is an example of how you can select a specific filed. Both ranges have to be initialised in the Controller:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.range1 = "12:00am - 12:30am";
$scope.range2 = "12:30am - 01:00am";
$scope.select = function(val) {
$scope.display = angular.copy(val);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<div class="first-hour">
<input type="text" ng-model="range1" ng-click="select(range1)" readonly>
</div>
<div class="second-hour">
<input type="text" ng-model="range2" ng-click="select(range2)" readonly>
</div>
Selected: {{display}}
</div>
(value was replaced with ng-model)
You can try like this,
create one object and initialize value in controller itself. then bind the object in html,
$scope.client = {};
$scope.client.start = "12:00am - 12:30am";
in html page,
<div class="first-hour">
<input type="text" ng-model="client.start" readonly>
</div>
please let me know if u have any quires.

how to access element in directive?

I have a html page in which there is a directive(child html) inside as below. I want to do input validation of input1 and input2 in directive(child html) for the button in parent html, but I don't know how I can access the input1 and input2 in child (directive). I would like to know what is the right way to access input1 and input2? Thanks in advance!!
Parent html:
<div>
<child></child>
<button name="myButton" ng-disabled="????.myForm.input1.$invalid"><button>
</div>
Directive: child
<form name="myForm">
<input name="input1" required/>
<input name="input2" required/>
</form>
Try this:
Parent controller:
vm.myForm = {};
Parent Html:
<child my-form="vm.myForm"></child>
<button name="myButton" ng-disabled="vm.myForm.input1.$invalid"><button>
Child directive:
scope: {
myForm: "="
}
Child HTML:
<form name="myForm">
<input name="input1" required/>
<input name="input2" required/>
</form>
You can $emit event to your parent controller and pass needed data.
Directive:
$scope.$emit('yourCustomEvent', 'Data to send');
And catch the event in you parent controller.
Parent controller:
$scope.$on('yourCustomEvent', function (event, data) {
console.log(data); // will print "Data to send"
});
And in your case I advice you to include the button in your directive, it will be much easier to work with it.

ng-model vs ngModel - breaks form

New to angular, new to life:
I have a small email form.
This works:
<form method="post" name="form" role="form" ng-controller="contactForm" ng-submit="form.$valid && sendMessage(input)" novalidate class="form-horizontal">
<p ng-show="success"><b>We received your message</b></p>
<p ng-show="error">Something wrong happened!, please try again.</p>
<label for="name">Name:</label><br>
<input type="text" id="name" name="name" ng-model="input.name" required><br>
<label for="email">Email:</label><br>
<input type="email" id="email" name="email" ng-model="input.email" required><br>
<label for="messsage">Message:</label><br>
<textarea id="messsage" name="message" ng-model="input.message" ngMaxlength='2000' required></textarea><br>
<button type="submit" name="submit" ng-disabled="error" value="submit">Submit</button>
</form>
This does not work:
<form method="post" name="form" role="form" ng-controller="contactForm" ng-submit="form.$valid && sendMessage(input)" novalidate class="form-horizontal">
<p ng-show="success"><b>We received your message</b></p>
<p ng-show="error">Something wrong happened!, please try again.</p>
<label for="name">Name:</label><br>
<input type="text" id="name" name="name" ngModel="input.name" required><br>
<label for="email">Email:</label><br>
<input type="email" id="email" name="email" ngModel="input.email" required><br>
<label for="messsage">Message:</label><br>
<textarea id="messsage" name="message" ngModel="input.message" ngMaxlength='2000' required></textarea><br>
<button type="submit" name="submit" ng-disabled="error" value="submit">Submit</button>
</form>
for the 2 inputs and the textarea if I use 'ng-model' the email sends, but when the page loads, the form loads invalid.
If i use 'ngModel' the form loads clean, but the email wont submit.
controller here:
app.controller("contactForm", ['$scope', '$http', function($scope, $http) {
$scope.success = false;
$scope.error = false;
$scope.sendMessage = function( input ) {
$http({
method: 'POST',
url: 'processForm.php',
data: input,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
})
.success( function(data) {
if ( data.success ) {
$scope.success = true;
$scope.input.name="";
$scope.input.email="";
$scope.input.message="";
} else {
$scope.error = true;
}
} );
}
You can see it live here:
http://smartestdiner.com/Bethel/indexx.html#/contact
Warning:
There is some annoying red background
.ng-invalid{
background-color:red;
}
}]);
That's how we know it is loading invalidly.
The annoying red background is the form, since you have a very generic rule set by .ng-invalid, the class will be set on the form as well. You would need to make it more specific for the inputs and controls within the form.
Example:
input.ng-invalid,
textarea.ng-invalid {
background-color:red;
}
Or just reset rule for form.ng-invalid
To add on there is nothing called ngModel it is ng-model. using the former one doesn't do anything but adds a dummy attribute on the element, it has no effect. It is angular way of directive naming, since html is case insensitive the one way angular can identify the directive from attribute or element name (based on the restriction). It converts it to camelCasing to evaluate and process respective directive (or directives attribute bindings). When you do not have ng-model specified and if the form or control does not have novalidate attribute, then the browser's HTML5 validation kicks in that is what you see as inconsistency. Using HTML5 novalidate attribute makes sure no native validation happens on the form.
ng-model is when u write the view (html part).
ngModel is used when one write a custom directive. It is placed in the "require:" param so that u can access,
variables like ngModel.$modelValue
ngModel.$modelValue will have the latest content which has been typed by the user at realtime. So, it can be used for validations, etc.
View code:-
<!doctype html>
<html ng-app="plankton">
<head>
<script src="/bower_components/angular/angular.min.js"></script>
<script src="/scripts/emailing/emailing.directive.js"></script>
</head>
<body ng-controller="EmailingCtrl">
<div>
<label>Enter Email: </label>
<emailing id="person_email" ng-model="email_entered"></emailing>
</div>
</body>
</html>
Custom directive:-
(function() {
'use strict';
angular.module('plankton', [])
.directive('emailing', function emailing(){
return {
restrict: 'AE',
replace: 'true',
template: '<input type="text"></input>',
controllerAs: 'vm',
scope: {},
require: "ngModel",
link: function(scope, elem, attrs, ngModel){
console.log(ngModel);
scope.$watch(function(){ return ngModel.$modelValue;
}, function(modelValue){
console.log(modelValue);//awesome! gets live data entered into the input text box
});
},
};
})
.controller('EmailingCtrl', function($scope){
var vm = this;
});
})();
This has been plunked here:- here

How can I isolate nested form?

I'm very new to AngularJS, and new to client side programming.
Context:
I'm implementing a contact form with support for multiple phone numbers and addresses.
It look like this:
<form name="contactInsertForm" ng-controller="contactInsertController as contactCtrlr" ng-submit="contactInsertForm.$valid && contactCtrlr.save()">
<input type="text" name="name" />
<phones-editor></phones-editor>
<addresses-editor></addresses-editor>
<input type="submit" />
</form>
phonesEditor and addressesEditor are custom Angular directives which implement support for adding, removing and editing phones and addresses. The controllers and modules look like this:
Addresses:
(function () {
var app = angular.module("AddressesEditorModule", []);
app.directive("addressesEditor", function () {
return {
restrict: "E",
templateUrl: "/addressesEditorTemplate.html",
controller: function ($scope) {
this.addresses = [
// this will hold addresses.
];
// ...
}
}
})();
Phones:
(function () {
var app = angular.module("PhonesEditorModule", []);
app.directive("phonesEditor", function () {
return {
restrict: "E",
templateUrl: "/phonesEditorTemplate.html",
controller: function ($scope) {
this.phones = [
// this will hold phones.
];
// ...
}
}
})();
And the templates:
Addresses:
<!-- list already added addresses -->
<div ng-repeat="address in addressesEditorCtrlr.addresses">
<p>{{address.address}}</p>
<p>{{address.city}}</p>
</div>
<form name="addressInsertForm" ng-submit="addressInsertForm.$valid && addressesEditorCtrlr.add()">
<!-- inputs for each of the address fields -->
<input type="submit" value="Add" />
</form>
Phones:
<!-- list already added phones -->
<div ng-repeat="phone in phonesEditorCtrlr.addresses">
<p>{{phone.number}}</p>
<p>{{phone.areaCode}}</p>
</div>
<form name="phoneInsertForm" ng-submit="phoneInsertForm.$valid && phonesEditorCtrlr.add()">
<!-- inputs for each of the phone fields -->
<input type="submit" value="Add" />
</form>
As you may have noticed, the generated at the browser HTML looks like this:
<form>
<input type="text" name="name" />
<phones-editor>
<!-- list already added phones -->
<div ng-repeat="phone in phonesEditorCtrlr.addresses">
<p>{{phone.number}}</p>
<p>{{phone.areaCode}}</p>
</div>
<form name="phoneInsertForm" ng-submit="phoneInsertForm.$valid && phonesEditorCtrlr.add()">
<!-- inputs for each of the phone fields -->
<input type="submit" value="Add" />
</form>
</phones-editor>
<addresses-editor>
<!-- list already added addresses -->
<div ng-repeat="address in addressesEditorCtrlr.addresses">
<p>{{address.address}}</p>
<p>{{address.city}}</p>
</div>
<form name="addressInsertForm" ng-submit="addressInsertForm.$valid && addressesEditorCtrlr.add()">
<!-- inputs for each of the address fields -->
<input type="submit" value="Add" />
</form>
</addresses-editor>
</form>
The problem:
I have two form's inside a form. The nested forms work correctly, adding and validating values it should be doing, and refusing to add invalid phones/addresses.
But when I click the submit button at the outer form, it will interpret the inner forms input fields and will raise errors if these fields have invalid values.
How can I use AngularJS form handling and avoid this situation? Is this possible at all?
you would need a directive if you want child form as isolate form. Have a look at answers from this SO question. please have a look at fiddle attached in this answer. I am putting the fiddle link here for you to js-fiddle to see it in action.
putting below code just because SO doesnt accept only fiddle links...
<form name="parent">
<input type="text" ng-model="outside"/>
<ng-form name="subform" isolate-form>
<input type="text" ng-model="inside"/>
</ng-form>
</form>
Working on Angular 1.6
const isolatedFormDirective = () => {
return {
restrict: 'A',
require: '?form',
link: ($scope, $element, $attrs, ctrl) => {
ctrl && ctrl.$$parentForm && ctrl.$$parentForm.$removeControl(ctrl);
}
}
}
app.directive('isolatedForm', isolatedFormDirective);
This article has exactly what you are looking for.
The basic gist is that you want to use the ngForm directive inside your form tag.
<div ng-form="outerForm">
<input type="text" ng-model="main.outerFormText"/>
<div ng-form="innerForm">
<input type="text" ng-model="main.innerFormText" required/>
<button type="button" ng-click="main.submit('innerForm')"
ng-disabled="innerForm.$invalid">Inner Submit</button>
</div>
<button type="button" ng-click="main.submit('outerForm')"
ng-disabled="outerForm.$invalid">Outer Submit</button>
</div>
Example plnkr