Form is undefined in scope in Angular 1.3 - angularjs

I don't if this is something I did, but once I upgraded to Angular 1.3, the form is no longer defined in my scope. My HTML is
<div some-dir>
<form name="myForm">
<!-- Form stuff here -->
<button ng-click="submit();">
</form>
</div>
The submit function is
scope.submit = function() {
console.log(scope.myForm);
}
And this returns undefined. I have no ng-if or ng-repeat anywhere. There is only one directive and one scope in this specific directive. Again, this was all working until I upgraded to Angular 1.3

The problem can be solved by scoping form data into some scope object:
<form name="myForms.firstForm">
<!-- Form stuff here -->
<button ng-click="submit();">
</form>
And than:
scope.myForms = {};
scope.submit = function() {
console.log(scope.myForms.firstForm);
}
Some more info in this comment.

In my case it happened that my form was nested within another form.
So once I switched the <form name="myForm"> to <ng-form name="myForm" ...> the form was defined.
See ng-form docs.

Got the same problem and fixed by declaring the controller in the html template that contains the form. So you form declaration would become:
<form name="myForm" ng-controller="SomeController">
New "feature" of 1.3, probably..

Related

Form object undefined when using Angularjs blockUI

I'm using Angularjs, version 1.5, and i have specified a form in my html as follows:
<div class="row" ng-show="showForm">
<form class="form-horizontal" name="myForm" novalidate role="form">
</form>
</div>
In the corresponding controller i have a function that resets the form and calls pristine:
$scope.myForm.$setPristine();
Until now everything works fine.
I then try to use blockUI (https://github.com/McNull/angular-block-ui)
by changing the above div to:
<div class="row" ng-show="showForm" block-ui="myBlock">
so the only addition is: block-ui="myBlock"
however, when the controller code runs i get:
TypeError: Cannot read property '$setPristine' of undefined
When debugging i see that the form object does not exist! When removing block-ui="myBlock", everything works fine again.
Any ideas?
Thanks in advance
Try something like these:
function MyCtrl($scope, $timeout, blockUI) {
$scope.form = {};
$scope.submit = function() {
var myBlockUI = blockUI.instances.get('myForm');
$scope.form.myForm.$setPristine();
myBlockUI.start();
$timeout(function() {
// Stop the block after some async operation.
myBlockUI.stop();
}, 3000);
};
}
and view:
<form name="form.myForm" novalidate ng-submit="submit()" block-ui="myForm">
<input type="text">
<button>
Submit
</button>
</form>
I have same trouble like you with undefined form on $scope, but found these trick with using additional object form on SO. Plunk here.

Isolate and shared scope same time in directive AngularJS

New to Angular so not sure if I ask my question the right way.
So I have form.
<form ng-controller="myController" action="" method="get">
<div myDirective>
<input ng-model="question.sex" value="male" type="radio">
<input ng-model="question.sex" value="female" type="radio">
<button ng-click="log(LogThisQuestionAnsware())"></button>
</div>
<div myDirective>
<input ng-model="question.agree" value="no" type="radio">
<input ng-model="question.agree" value="yes" type="radio">\
<button ng-click="log(LogThisQuestionAnsware())"></button>
</div>
</form>
So my goal is to log current "question" answer. on button click.
How can I access local question in myDirective separate from my second directive and have in controller scope too.
--[ Edit: ]--
Ok this is pretty much my scenario. http://jsfiddle.net/y5esnm09/5
Each button have to log its own directive value not both radio values if they are selected.
If I correctly understood your question, you want both directive instances to bind to the same question object, but have their scopes separate from eachother:
Set up a two way data binding between your directive and your controller, e.g.:
<div my-directive question="question">
<!-- the rest -->
angular.module('your.module').directive('myDirective', function() {
return {
scope: question: '=',
//other props
}
This will ensure that both directives bind to the same question object but have their own separate scopes.
An alternative would be to set the scope property to true, that way they will both create a child scope of your controller.
EDIT: Fiddle demonstrating two way binding:
http://jsfiddle.net/L0eqf4qe/
PS: I converted myDirective to my-directive, angular will translate the snake-case to camelCase for you.

AngularJS validate included form(Ionic framework)

I'm trying to validate a form that was included using ng-include.
HTML:
function submit() {
if($scope.form.$invalid) {
return;
}
}
$scope.submit = submit;
<form name='form' ng-submit="submit()" novalidate>
<div ng-include="'my_form_inputs.html'"></div>
</form>
when i try to submit i get an error that form.$invalid is null.
i know ng-include creates another scope within the controller's scope, but is there no way to validate this form?
it seems like i would have to duplicate the entire form elements if i want to create an edit page for this form.
any idea?

How get form by name in $scope?

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

How to prevent transcluding directive to create new child scope for the form directive?

I have a problem with directive transclude and the form directive. As you may know, the form will end up in the "scope" if you add the "name"-property to the form tag, then you can check for form validation and so on.
My problem start when i put the form tag in a directive that uses transclude. I'm aware of how to deal with this problem with two-way data binding, as mention here https://stackoverflow.com/a/14484903/1029874 -- "use an object instead of a primitive"
But my form ends up in the transcluding directives scope. Here is an example of what i want to do.
<div ng-controller="appCtrl">
<widget>
<widget-header>{{model.property}}</widget-header>
<widget-body>
<!-- The form will end up in "widget-body":s scope instead of appCtrl:s scope -->
<form name="appForm" ng-submit="submit()">
<input type="text" required ng-model="model.property" />
<input type="submit" value="submit" />
</form>
</widget-body>
</widget>
</div>
And here is the fiddle, http://jsfiddle.net/WLksJ/1/
Is there a way that I can get around this behavior?
Thanks!
An interesting question, but a problem that's easily avoided by using
<form name="appForm" ng-submit="submit(appForm.$valid)">
and checking the parameter in the submit function.
http://jsfiddle.net/udMJ7/
Another (perhaps better) option is to use this which is set to the scope of the last controller (in this case the form controller, which we want)
$scope.submit = function(){
if(this.appForm.$valid){
//post the form!!
}
};
http://jsfiddle.net/udMJ7/1/

Resources