angularjs access another form from directive - angularjs

<ng-form name="innerForm">
<select ng-model="obj1" ng-options="i as i for i in selectTrueFalse" my-drective">...</select>
</ng-form>
<ng-form name="innerForm">
<select ng-model="obj2" ng-options="i as i for i in selectTrueFalse" my-drective">...</select>
</ng-form>
Two select elements above are wrapped around separate form element. In angularjs directive we can access the current form as mentioned below but as far as I know it only gives access to the current form. I need to access other form in order to access the element inside other form e.g. if the directive is being evaluated for obj1 how to access obj2 at that time. Is there a way?
app.directive('myDirective'), function() {
return {
require: '^form'

Related

How use multiply ng-models in AngularJS

I have textarea with ng-model 'wordset' and ng-change="onChange()"
<div>
<textarea ng-model="wordset" ng-change="onChange()"
class="form-control app-word-set"
placeholder="Enter Word Set" rows="4">
</textarea>
</div>
I have button which added new textarea in this div. I needed that already added textarea includes the same on change method that my first textarea i have. But it should use ng-model...
I want to use on method in my angularJS controller that gets values from every textarea by foreach like this:
$scope.wordSetTextarea = angular.element(document.getElementsByClassName('app-word-set'));
$scope.onChange = function() {
angular.forEach($scope.wordSetTextarea, function(value, key) {
console.log(value);
});
}
Is this possible?
With the AngularJS framework, multiple elements are added with the ng-repeat directive:
<div ng-repeat="item in itemArr">
<textarea ng-model="item.wordset"
ng-change="onChange(item,$index)"
name="'item' + $index"
class="form-control app-word-set"
placeholder="Enter Word Set" rows="4">
</textarea>
</div>
<button ng-click="addNewTextarea()">Add input</button>
$scope.itemArr = [{}];
$scope.addNewTextarea = function() {
$scope.itemArr.push({});
};
New AngularJS developers often do not realize that ng-repeat, ng-switch, ng-view, ng-include and ng-if all create new child scopes, so [data hiding problems] often shows up when these directives are involved ... [they] can be easily avoided by following the "best practice" of always have a '.' in your ng-models.
For more information, see
AngularJS ng-repeat Directive API Reference -
What are the nuances of scope prototypal / prototypical inheritance in AngularJS?

AngularJS: Programmatically adding nested form (ngForm)

I have a specific problem where I need to add nested form in a form built with angular.
Statically (non-programmatically), I can the do the following:
<form>
...
<ng-form>
<input ng-model="myModel" required>
</ng-form>
...
</form>
And validation error in the nested form invalidates the outer form. Which is exactly what I need.
But I can't seem to do this programmically via a directive. In the template I have the following
<div dynamic-nested-form="">
</div>
And I have the following:
(function () {
angular
.module('controls')
.directive('dynamicNestedForm', dynamicNestedForm);
function dynamicNestedForm($compile) {
return {
restrict: 'A',
link: linkedFunction
};
function linkedFunction($scope, element) {
var nestedForm = angular.element('<ng-form><input ng-model="myModel" required></ng-form>');
element.append($compile(nestedForm)($scope));
}
})();
The form does get injected in the DOM and it is in invalid state, in Chrome element view, I see
<div dynamic-nested-form="" class="ng-scope">
<ng-form
class="ng-pristine ng-scope ng-invalid ng-invalid-required">
<input ng-model="myModel" required=""
class="ng-pristine ng-untouched ng-invalid ng-invalid-required">
</ng-form>
</div>
But outer form does not get invalidated. When the outer form loaded does it not see the inner form?
What am I doing wrong?
Right,
So,
Basically did a little debugging through Angular and it just happens that the nested form could not find the outer form controller. (The outer form controller is needed in ngModelDirective in its preLink)
The reason it cannot find it is because this preLink happens during compile (obviously, it's a preLink) and my compile was done before the nested form was attached.
So as a solution, instead of compiling before attaching, I do it after, like
var nestedForm = angular.element('<ng-form><input ng-model="myModel" required></ng-form>');
$compile(element.append(nestedForm ).contents())($scope);
Well, I think I am recompiling it.
Anyhoo, this then makes the inner control find the outer form and my problem is solved.

ionic select with angularjs

I am new to ionic + angularJS... I have created a select item drop down like this
<div class="list">
<div class="item item-input item-select">
<div class="input-label" >
Unit
</div>
<select id="unit">
<option selected>Kilometer</option>
<option>Mile</option>
</select>
</div>
</div>
I am wanting to get the value with angularJS... I have tried this..
The scope.convert is coming when I click a button.
$scope.convert = function() {
alert($scope.unit);
};
It outputs "undefined".. Why is this?
$scope.unit is actually not defined in the scope, hence you get undefined. You have to define unit on the scope. Since this is an angular application, you can do it the angular way.
In your controller, you want to define a model to hold the value selected. Lets call this model unit like you are actually trying to do. Hence you can initialize this model to Kilometer in your controller.
$scope.unit = 'Kilometer'
Now you need an array of options. This can be set up in your controller as well.
$scope.unitOptions = ['Kilometer', 'Mile']
We use scope to expose our models to the view, hence in your view, you can access this models as follow:
<select id='unit' ng-options="unit for unit in unitOptions">
You will get a dropdown with 'Kilometer' and 'Mile'. You can select any one of them and your model unit will be updated.
//This should now work
$scope.convert = function() {
alert($scope.unit);
};
Note: I left the id attribute on the select element to show it has nothing to do with the model in your controller.

How do I add a class to a div if the item in ng-repeat is not valid?

I am trying to use $invalid to add a class to a div when the input within the div is not filled out. However I just cannot work out the syntax.
<div ng-app ng-controller="miniC">
<form name="persondetails" novalidate>
<div ng-repeat="account in myAccounts" ng-class="{'has-error': account.amount.$invalid}" >
<input name="{{account.name}}" ng-model="account.amount" required="required"/>
</div>
</form>
</div>
function Account(nameArg, amountArg){
this.name = nameArg;
this.amount = amountArg;
}
The surrounding div needs to have class="has-error" when the inner item is not filled in. I have done similar on single bound elements just cant seem to get this working....
$invalid flag is not attached to the ngModel, but to the form controller (ngFormController).
In your example you're not demonstrating that you're even using ngForm, and you should, if you want angular to validate your form.
Next, you're trying to dynamically set the input's name attribute. ngForm won't like it because ngFormControll will be initialized before your expression is evaluated.
Workaround is to wrap each ng-repeat iteration inside new ngForm (ngForm can be nested and it will just work) and name your inputs with some static string value (e.g. name="amount").
So, you'll want your view written as:
<div
ng-repeat="account in myAccounts"
ng-class="{'has-error': form.amount.$invalid}"
ng-form="form"
>
<input name="amount" ng-model="account.amount" required="required"/>
</div>

Model not updated when view changes

I have a form for creating new records in a partial which I load in my main view like this
<div ng-controller="NewProductController">
<ng-include src=" 'views/partials/product-form.html' "></ng-include>
</div>
In the form, I have some input fields
..
<input ng-model="cip" type="text" id="cip" class="form-control" placeholder="Enter the CIP" autofocus="autofocus"/>
<input ng-model="name" type="text" id="name" class="form-control" placeholder="Enter the name" />
And in my controller, I'm sending a POST request with the values of the input fields:
...
.controller('NewProductController', function(Product, $scope) {
$scope.create = function () {
Product.create( {'cip': $scope.cip,
'name': $scope.name,
'dosage': $scope.dosage,
...
});
};
The problem is that when the values of the input fields change, it is not reflected in the controller ($scope.cip and $scope.name are undefined unless I initialized them with some value) but when $scope.cip and $scope.name are changed in the controller, the changes are correctly reflected in the view.
I thought that kind of updates are automatic or am I missing something ?
The reason why this is happening because ng-include creates a child scope. Since you are managing the model fields in the child scope i.e inside the template html, the fields are not available on the parent scope, where your controller is defined.
To fix this issue first and foremost thing that you need to do would be to create a obj such as product and define it on the controller NewProductController scope.
$scope.product={};
The template then should bind to sub properties of this product object.
<input ng-model="product.cip" type="text" id="cip" class="form-control" placeholder="Enter the CIP" autofocus="autofocus"/>
Now your changes would be available in the parent product object.
You can improve it a bit by passing the product object using ng-init like this
<ng-include src=" 'views/partials/product-form.html' " ng-init='model=product'></ng-include>
Now your template input fields change to
<input ng-model="cip" type="text" id="model.cip" class="form-control" placeholder="Enter the CIP" autofocus="autofocus"/>
Advantage
You template is not dependent on the structure of parent model class. Dependency is explicit. The template becomes more reusable as it clearly defines the model it works with, like in your case the template works with Product model.
For the sake of completeness of the answer i must link to this must read article, Understanding Scopes

Resources