AngularJS form is undefined in $scope in controller - javascript

I am trying to access a html defined form in the $scope in the controller. The thing is that the form is under ng-switch directive so I was suspecting this is the issue. Still, I couldn't find any solution to this.
My code is :
<div ng-switch="bla">
<div ng-switch-when="blabla">
<form name="myForm">
</form>
</div>
</div>
And the js : $scope.myForm is returning undefined.
Can you please help me with this?
Thanks in advance.

Yes, you are right:
This directive creates new scope.
Like ng-if.
See: https://docs.angularjs.org/api/ng/directive/ngSwitch
Here could be an answer:
https://github.com/angular/angular.js/issues/10944
https://github.com/angular/angular.js/wiki/Understanding-Scopes#ng-include
If you need the form in a method in the controller, that you call from the html code, you can use the form as a parameter.
For instance:
<form name="dataForm" ng-submit="$parent.processForm(dataForm)">
processForm is a method in the controller.
You need $parent here because of the child scope under ng-switch.

check that condition for div "ng-switch-when " is true i.e "blabla" is true or not . because form will be there only if the condition is true
If it is not working then try to declare form object in your controller (at the time when controller loads ). like this
$scope.myForm ={};
Hope it will work ........

Related

How to apply the AngularJS controller to the included page using ng-include

I have two html pages, main.html and nested.html, so the nested.html is actually included in main.html, this way:
main.html starts
<div ng-include src="'nested.html'"></div>
main.html ends
FULL CODE
nested.html
<html>
<h1> I am included, but controller not sending the values to me. </h1>
<input type="text" id="myDatePicker"/>
</html>
main.html
<html ng-controller="MainCtrl">
<h1> I am main.html and controller working properly on me, please take care of my child **given below** </h1>
<div ng-include src="'nested.html'"></div>
</html>
Controller Code:
(function() {
'use strict';
angular.module('bootstrapApp').controller('MainCtrl', MainCtrl);
function MainCtrl($scope, $location, $http, $compile) {
$("#myDatePicker").datepicker({
orientation: 'left'
});
}
});
The Controller code makes the text field a datepicker using jquery. The input field is in nested.html page. If the controller works on the included page, the textfield becomes a datepicker. That's it
Please guide me through how do I apply the same controller MainCtrl to included nested.html page
Thanks.
There are 2 important things to mention here:
The controller scope of the MainCtrl is already applied to the included nested.html. You can review that in the following Plunker: https://embed.plnkr.co/cvILaL3VvnJ5c1YDHDT1/.
You shouldn't use a jQuery datepicker from out of a AngularJS controller. Instead use a datepicker, which is intended for AngularJS (e.g. angular-datepicker)
from what I can guess,you must be using $scope.someVar and you are trying to render it in ng-include. Try creating an obj inside the controller like below:
$scope.obj= {
someVar : 'Value'
};
and use it in ng-include i.e. nested.html as {{obj.someVar}}.
Update 1
As per your new update, try AngularJS datepicker and let me know.
Try to add controller into nested.html file like:
<div ng-controller="MainController">
<h1> I am included, but controller not sending the values to me. </h1>
<input type="text" id="myDatePicker"/>
</div>
And from your comment:

How to reference child controllers of a certain type from an angular directive or component?

When I define an angular component or directive, I can use 'require' to bind to a parent controller like require: {'parentForm' : '^^ngForm'}.
I'd like to do the same thing, but in reverse: require: {'childrenForms' : '[children]ngForm'} would bind childrenForms to an array of all controllers contained within my component which are ngForms.
I want to do this in order to build components that add aggregate behavior to directives I don't have control over. For example my-special-form container could have an isValid() method that returns true if all the ng-forms within it are valid at the moment.
Is there any way to do this? Am I making a mistake by even wanting to?
There is no option to require inner child directive in Angular. Personally I don't think so the approach you thought about would be good approach to go for, like here parent directive want to know directly about child directive. Rather I'd say choose the approach where child directive will pass required data to parent controller by calling one of its method.
If you only wanted to validate inner forms then you can wrap all the inner forms inside wrapper form ng-form with some name(you can have nested form in angular using ng-form directive). You can see example below, where you can see I wrapped all the inner form with one wrapper form element ng-form. So what happen is, when any one of the forms get invalid the parent form will invalid. If all forms are valid then parentForm will become valid as well.
Markup
{{parentForm.$valid}}
<div ng-form name="parentForm" my-directive>
<form name="form1" some-directive>
.....
</form>
<form name="form2" some-directive>
.....
</form>
<form name="form3" some-directive>
.....
</form>
</div>

How to access form nested ng-include scope/fields?

I looked around and can't find the same problem that I have.
Like a lot of people ng-include creates a new child scope that can't propagate to parent.
I have a generic template that I want to use with different form actions but can't since it doesn't receive the data from ng-include.
Here is the code:
<form ng-controller='FormCtrl' name="form1" ng-submit="treatForm1(data)"><div ng-include src="'template'"></div></form>
<form ng-controller='FormCtrl' name="form2" ng-submit="treatForm2(data)"><div ng-include src="'template'"></div></form>
I can't use notations like vm. or form., unfortunately.
Is there a way to get the ng-include scope on submit? I tried this, $parent, nada.
Have you tried using $emit to send it up to the parent?

ng-click doesn't take parameters from the DOM

I have the following code:
<input id="id">
<button data-action="bea" ng-click="Create($('#id1')[0].value);" class="btn">Insert ID</button>
<button data-action="bea" ng-click="Create($('#id2')[0].value);" class="btn">Insert ID</button>
In the JS I have:
$scope.Create = function (id){
if (id === undefined) {
$scope.data = "You must specify an id";
} else {
$scope.data = data;
console.log(data);
});
}
};
When the call gets into the Create function the value of the id is undefined.
If I add the following line at the beginging of the Create function everything works ok:
id = $('#id')[0].value;
If I send a constant value it works:
<button data-action="bea" ng-click="Create('SomeID');" class="btn">Insert ID</button>
Why is this happening and how can I do that without putting the line of value into the method?
Thanks
This is just an extension of comments and other answers, You could achieve this in many ways using angular, one simple example could be:-
<!-- Add a controller -->
<div ng-controller="MainCtrl">
<!-- Give a model binding to your text input -->
<input ng-model="userEntry" type="text"/>
<!-- ng-click pass which ever argument you need to pass, provided it is an expression that can be evaluated against the scope or any constants -->
<button data-action="bea" ng-click="Create(userEntry);" class="btn">Insert ID</button>
<!-- Some simple data binding using interpolation -->
{{data}}
<!-- Just for demo on repeater on a list of items on the scope -->
<div ng-repeat="item in items track by $index">{{item}}</div>
</div>
Example Demo
My 2 cents on the lines of what were originally trying to do:-
Use angular bindings instead of accessing DOM directly for getting the data, it really helps you deal with just the data without worrying about how to access or render it in DOM. If you think you need to access DOM for implementing business logic re-think on the design, if you really need to do it, do it in a directive. Angular is very opinionated on the design and when where you do DOM access.
ng-model
ng-binding
controller
all about ngmodel controller
This is not the way you should do in AngularJS. You should really think in Angular if you want to use AngularJS. Refer this post ("Thinking in AngularJS" if I have a jQuery background?)
All DOM manipulation should be done in Directive. Refer this page that I found really clear.
(http://ng-learn.org/2014/01/Dom-Manipulations/)
My guess is that $ is not bound to the jQuery function when the ng-click value is evaluated, because it is not exposed in the Angular scope.
Solutions to adress this:
expose the jQuery function in scope somewhere, e.g $scope.$ = $; in a controller.
make the Create function parameterless as you suggested, with a var id = $('#id')[0].value; at the beginning
my favorite : avoid using jQuery. If you put some data in the #id element, there's probably a more natural and AngularJS-idiomatic way of retrieving it than querying the DOM (e.g an Angular service).
In particular, if the element you're targeting is an <input> element, then use the ngModel directive to link the value to a $scopeproperty that will be accessible in the controller :
<input ng-model="inputData"/>
The JavaScript you are trying to pass as a parameter of the create function is not available in the scope of the Create function.
Try to target the element a different way.
Does that help?

Data Binding between pages in Angularjs

I am trying to understand data binding in Angularjs.
What I want to do is establish binding between pages that is if I change the input on first.html, the data should automatically change in second.html.
For example,
This is first.html:
<div ng-controller="MyCtrl">
<input type="text" ng-model="value"/><br>
{{value}}
<input type="submit" value="Second page"/>
</div>
and say second.html has only this piece of code {{value}}.
and in the .js file we have $routeProvider which takes the template url as 'second.html' & the controller is 'MyCtrl'.
So the controller is:
MyApp.controller(function($scope){
$scope.value="somevalue";
})
By doing the above way the {{value}} on the second.html is getting the value "somevalue". Which is comming from the controller.
But if I change the input value dynamically that is on the first.html, the value on the second.html is not getting that value.
My question is how do I bind the value on second.html with first.html automatically.
To understand the question clearly, Suppose there is an input field for entering text and a submit button on first.html, then I want to get the Input value of the text field of the first.html on the second.html page on Submit.
Use a service and store your model there. Gloopy already has a good example of this here: https://stackoverflow.com/a/12009408/215945
Be sure to use an object property instead of a primitive type.
If you'd rather use $rootScope, then as above, define an object, rather than a primitive:
$rootScope.obj = { prop1: "somevalue" }`
then bind to that object property in your views:
<input type="text" ng-model="obj.prop1">
{{obj.prop1}}
If you attach your data to $rootScope if will survive transitions across controllers and be part of all $scopes (prototype inheritance magic)
//**attach in controller1:**
function MyCtrl1($rootScope) {
$rootScope.recs= { rec1 : "think philosophically" };
}
//**do nothing in controller for view2:**
function MyCtrl2($scope) {
//nothing
}
//**Markup for view2: automaticall makes use of data in $routeScope**
<p>Try doing this: {{recs.rec1 }}</p>
//**markup for view1 to respond to OPs question in comments**:
<input ng-model="recs.rec1" />
Update: Creating a custom service is a more scalable and structurally sound way to handle this, but the $rootScope method is the quick and dirty way.
Update2: added view1 markup to respond to OP question, edited example to take advantage of correct advice to use object rather than primitive.
Found the Solution to what I was looking for, The solution is in the Angular docs, here is the link http://docs.angularjs.org/cookbook/deeplinking.
Some part of the example on that link answers my question.
You should user $broadcast, $emit or scope communication. Try to avoid overloading the rootScope. It is as a bad practice as saving data into the application sessions.

Categories

Resources