How get form by name in $scope? - angularjs

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

Related

Scope variable is changing unexpected manner Angular JS

I am a beginner in AngularJS. Recently tried out below code.
HTML Tag:
<div ng-app="myApp">
<input type="text" ng-model="message" />
<h1>{{ message }}</h1>
<div ng-controller="ctrlOne">
<input type="text" ng-model="message" />
<h1>{{ message }}</h1>
</div>
<div ng-controller="ctrlTwo">
<input type="text" ng-model="message" />
<h1>{{ message }}</h1>
</div>
</div>
JS Script:
var app = angular.module("myApp", []);
app.controller("ctrlOne", function($scope) {
console.dir($scope);
});
app.controller("ctrlTwo", function($scope) {
console.dir($scope);
});
If you type in the text area. Each output print is unique. Even though I have used common variable to the $scope element.
Can any one please explain,
1. what is happening internally?
2. How angular is handling this scope?
If you can help with step wise advice explaining, so that it is easy for beginner like us to understand.
Your time spent on this highly appreciated. Thanks in advance.
Please find JSFIDDLE Link Below:
Code Snippet example on $scope
Please check the console. Its is showing undefined.
Even though you have used a common variable, but both of them are under the scope of different controller.
One is under the scope of controller ctrlone and other is under the scope of controller ctrltwo.
When you create a controller, angular creates a separate scope pertaining to that controller alone. So even if the names of variables are same but if they are defined on two different scope, they will have unique values.
However, if you want to have a variable with same value in both controller, then you will have to define that variable on $rootScope because $rootScope is created once per app.
Inside your controller, you can retrieve the value like this:
console.log($scope.message);
This will give you the value of message as you typed in the input box.

Angular bind service property to a controller scope

I have 2 controllers using the same service, the first controller change the value of a property on the service, I need the second controller to know the property has changed to set the new value in his current $scope. I dont want to use broadcast, is there an elegant way to do this ?
Thank you.
You could create an object in angular service,that will have various shareable properties in it. You could directly assign that variable with your controller scope variable. So that the reference of variable use by both controller are the same, like we gave to myCtrl1 and myCtrl2 will have only one copy in there scope variable. So changes in one variable updates the other one.
Markup
<body>
<div ng-controller="myCtrl1">
1st Controller
<input type="text" ng-model="model1.prop1" />
<input type="text" ng-model="model1.prop2" />
</div>
<div ng-controller="myCtrl2">
2nd Controller
<input type="text" ng-model="model2.prop1" />
<input type="text" ng-model="model2.prop2" />
</div>
</body>
app.service('dataService', function(){
var dataService = this;
dataService.model = {
'prop1': '',
'prop2': '',
}
})
Controller1
app.controller('myCtrl1', function($scope, dataService){
$scope.model1 = dataService.model;
});
Controller2
app.controller('myCtrl2', function($scope, dataService){
$scope.model2 = dataService.model;
});
Demo Plunkr
This will be fired once your value change and you can propagate it to new controller
$scope.$watch('passValueHere', function(event, passValueHere){
$scope.controller2Value = passValueHere;
});

injecting error manually to form

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.

How we set to ng-model variable to parent controller in nested controllers scope

I have one ng-controller nested in another controllers scope.
I want to set scope variable in nested controller scope, to parent controller.
I have view:
<div ng-controller="MyCtrl">
<input type="text" ng-model="name"/>
<div ng-controller="CountryDataController">
<angucomplete
(...)
selectedObject="country"/>
</div>
</div>
which is part of the form.
Then on form submit i want to send ng-models from MyCtrl ( name,country) doing:
fields: {name: $scope.name,
country: $scope.country,
},
How can i tell angular, that selectedObject model belongs to MyCtrl, and not CountryDataController.
I tried
selectedObject="MyCtrl.country"
selectedObject="country[MyCtrl]"
but without effects.
selectedObject in angucomplete works like ng-model.
Also I don't want to rewrite logic from CountryDataController to MyCtrl, because in first i have fields for autocomplete and in second file uploading.
Is there any convention for this?
The answer is:
selectedobject="$parent.country"
You can use $parent, but if you move your HTML or eventually add another controller it between it will break.
The correct way to do that is to use the controller as syntax, as shown below:
<!-- use topCtrl to access this controller scope -->
<div ng-controller="MyCtrl as topCtrl">
<input type="text" ng-model="name"/>
<!-- use countryCtrl to access this controller scope -->
<div ng-controller="CountryDataController as countryCtrl">
<angucomplete
(...)
selectedObject="topCtrl.country"/>
</div>
</div>

How to pass custom directive name dynamically in class attribute of div tag?

I am very new to AngularJS. I have made a custom directive user and I want to call it dynamically in class attribute by using a variable.
e.g. $scope.dirName = "user";
When i use this variable in below code:
<div class = {{dirName}}></div>
Its result must show two input fields with specified values. But it is not doing so. When I replace {{dirName}} with user. It is working fine, means two input fields are shown with values as specified. Can anybody tell, what mistake I am doing?
This is index.html
<div ng-controller = "Ctrl">
<form name = "myForm">
<div class = {{dirName}}></div>
<hr>
<tt>userName : {{user}}</tt>
</form>
This is script.js
<pre>var app = angular.module('App',[]);
app.controller('Ctrl', function($scope){
$scope.user = {name:'adya',last:'Rajput'};
$scope.dirName = "user";
});
app.directive('user',function(){
return{
restrict:'C',
templateUrl:'template.html'
};
});</pre>
template.html contains:
UserName : <input type='text' name='userName' ng-model='user.name' required>
LastName : <input type='text' name='lastName' ng-model='user.last'>
Unfortunately, you cannot save names of directives in string variables and access them in the HTML. You can, however, save a string in a variable in $scope and use ng-switch to select the correct directive:
<div ng-switch="dirName">
<div ng-switch-when="ng-user">
<div ng-user></div>
</div>
<div ng-switch-when="...">
...
</div>
</div>
However, now it might be better to use something more descriptive than ng-user to switch over.
Sidenote: Do not use ng- prefix in your own directives. Angular uses that prefix so that it does not collide with other namespaces. You should use your own prefix for your directives.
Update: For the updated question as to why <div class="{{dirName}}"></div> does not work, it happens because angular $compiles the directive only once. If you first $interpolate the content of the template (which will replace {{dirName}} with ng-user) and then explicitly $compile it before entering it in the HTML, it should work.

Resources