Angular JS Directive loaded in expression - angularjs

I'm new to Angular, and have found a ton of resources about directives and nesting, but can't seem to get this simple example to work. So basically I am working on a tabset, I have an HTML template:
tabset.html
<div>
<ul>
<li ng-repeat="tab in tabset.tabs" ng-class="{active:tabset.current()==$index}">
<a href ng-click="tabset.current($index)">{{tab}}</a>
</li>
</ul>
<div>
<div ng-repeat="pane in tabset.panes">
<div ng-show="tabset.current()==$index">
{{pane.contents}}
</div>
</div>
</div>
</div>
And a search form template:
search-form.html
<div>
<form name="ytSearch" ng-submit="YTCtrl.submit()" novalidate>
<label for="search_box">Search For: </label>
<input id="search_box" ng-model="YTCtrl.searchString"/>
<br>
<label for="location">Location: </label>
<input id="location" ng-model="YTCtrl.location"/>
within
<input type="numeric" value="100" ng-model="YTCtrl.locationRadius" />
<select ng-model="YTCtrl.locationUnit">
<option value="ft">Feet</option>
<option value="m">Meters</option>
<option value="mi">Miles</option>
<option value="km">Kilometers</option>
</select>
<br>
<label for="search_order">Sort By: </label>
<select id="search_order" ng-model="YTCtrl.order">
<option value="relevance">Relevance</option>
<option value="date">Date</option>
<option value="rating">Rating</option>
</select>
<br>
<button id="search">
Search
</button>
</form>
</div>
And a simple app file with 2 directives to handle each of the templates:
app.js
(function() {
angular.module("JHYT", [])
.directive("sidebarTabset", function($compile) {
return {
restrict : 'E',
templateUrl : 'tabset.html',
controller : function($scope, $compile, $http) {
this._current = 0;
this.current = function(i) {
if (i != null)
this._current = i;
return this._current;
};
this.tabs = ['Search', 'Favorite'];
this.panes = [{
contents : "<search-form></search-form>"
}, {
contents : "Favorite Pane"
}];
},
controllerAs : 'tabset',
};
}).
directive("searchForm", function() {
return {
restrict : 'E',
templateUrl : 'search-form.html',
controller : function($scope, $compile, $http) {
this.searchString = '';
this.location = '';
this.locationRadius = '';
this.locationUnit = 'mi';
this.order = 'relevance';
this.submit = function() {
console.log("Submit");
};
},
controllerAs : 'YTCtrl',
}
});
})();
So as you can probably tell, the idea is to be able to send a JSON object into the tabset (through a service probably) and have it build out a dynamic tabset, that actually works exactly as I expected it to. What isn't working is that in the first tab, the content, which is <search-form></search-form> is not processed, and the tag is rendered as plain text in the content area.
Since this is a tabset, the "child" doesn't need anything from the "parent", the search form and the tab itself have no scope dependencies. I tried playing with the link and compile functions after seeing some examples of nested structures, but can't seem tog et them to work.
How can I process the content of that variable so that element directives are rendered using their templates?
EDIT:
#sielakos Gave me exactly what I was hoping for, a reusable method for doing this.
I added a directive to my module called compile, which adds a wrapper to allow me to use plain text:
.directive("compile", function($compile){
return {
restrict: 'A',
link: function(scope, element, attr){
attr.$observe("compile", function(str){
var compiled = $compile("<div>"+str+"</div>")(scope);
jQuery(element).replaceWith(compiled);
})
}
}
})
And I changed my tabset to use this directive:
<div>
<ul>
<li ng-repeat="tab in tabset.tabs" ng-class="{active:tabset.current()==$index}">
<a href ng-click="tabset.current($index)">{{tab}}</a>
</li>
</ul>
<div>
<div ng-repeat="pane in tabset.panes">
<div ng-show="tabset.current()==$index">
<div compile="{{pane.contents}}"></div>
</div>
</div>
</div>
</div>

You will need to compile your string using $compile service if you wish to use it as you would use template. Otherwise it will be treated as normal string and displayed as it is.
Here is example how to use it inside directive:
var compiled = $compile(str)(scope);
element.empty();
element.append(compiled);
If you wish you can look at this fiddle for more complex example:
https://jsfiddle.net/x78uuwp2/
Here I created simple compile directive that takes string compiles it and puts as element body with current scope.

Related

losing scope of ng-model when using ng-include (AngularJS)

I am creating android app using ionic and angularjs. In app i used ng-include for include html content in my page.
checkbox.html:
<ul>
<li ng-repeat="opt in $parent.checkboxOptions">
<h4>
<label><input type="checkbox" name="checkbox" ng-model="$parent.checkboxAnswer" value="{{opt.option_value}}">{{opt.option_value}}</label>
</h4>
</li>
</ul>
surveyCtrl.js
$scope.checkboxOptions = params.QuestAnswers;
$scope.next = function(){
console.log($scope.checkboxAnswer);
}
its showing undefined and another thing when i am click on one checkbox its selecting all checkbox's also.
surveyCtrls.js
.directive('question', function ($compile) {
return {
restrict: 'A',
replace: true,
link: function (scope, ele, attrs) {
scope.$watch(attrs.question, function(QuesHtml) {
ele.html(QuesHtml);
$compile(ele.contents())(scope);
});
}
};
})
.directive('description', function ($compile) {
return {
restrict: 'A',
replace: true,
link: function (scope, ele, attrs) {
scope.$watch(attrs.description, function(DescHtml) {
ele.html(DescHtml);
$compile(ele.contents())(scope);
});
}
};
})
.directive('answers', function ($compile) {
return {
restrict: 'A',
replace: true,
link: function (scope, ele, attrs) {
scope.$watch(attrs.answers, function(AnswerHtml) {
ele.html(AnswerHtml);
$compile(ele.contents())(scope);
});
}
};
})
.controller('surveyLoad', function($scope){
var QuestType = SurveyData[QuestionIndex].question_type;
var DrawHTML = {
'QuestionText': 'Some Text',
'QuestionDesc': 'Some Desc',
'QuestAnswers': [{
option_value: 'Red',
}, {
option_value: 'Blue',
}];,
'scope' : $scope
};
checkbox(DrawHTML);
}
})
.controller('nextQuest', function($scope){
$scope.QuestNext = function(){
console.log($scope);
}
});
function checkbox(params){
var $scope = params.scope;
$scope.QuesHtml = "<p>"+params.QuestionText+"</p>";
$scope.DescHtml = "<p>"+params.QuestionDesc+"</p>";
$scope.checkboxOptions = params.QuestAnswers;
$scope.AnswerHtml = "<div ng-include src=\"'surveyTemplate/checkbox.html'\"></div>";
}
survey.html
<div class="row">
<div class="col question_div">
<div class="qus_head">
<p>Question: 1/10</p>
</div>
<h4 class="para"><span question="QuesHtml"></span> </h4>
<div class="qus_footer">
<p>Maxime quis.</p>
</div>
</div>
</div>
<div answers="AnswerHtml">
</div>
<div class="row">
<div class="col button_div">
<ul>
<li><img src="../img/next.png" style="width:70px;float:right" alt="next" ng-controller="nextQuest" ng-click="QuestNext()"></li>
<!-- <center><li><button style="align:center">Stop</button></li></center> -->
<li><img src="../img/pre.png" style="width:70px;float:left" alt="previous" ></li>
</ul>
</div>
</div>
is there any way to get the value of checked checkboxes and prevent to check all other checkboxe's ?
Using ng-includes create it's own scope.
By using the controller as syntax you can overcome this issue.
https://docs.angularjs.org/api/ng/directive/ngController
<div id="ctrl-as-exmpl" ng-controller="Controller as ctrl">
...
<li ng-repeat="opt in ctrl.checkboxOptions">
<h4>
<label><input type="checkbox" name="checkbox" ng-model="ctrl.checkboxAnswer" value="{{opt.option_value}}">{{opt.option_value}}</label>
</h4>
</li>
...
</div>
and in your controller :
$scope.checkboxOptions = params.QuestAnswers;
becomes
this.checkboxOptions = params.QuestAnswers;
and so on.
AngularJS plunker about this syntax :
https://plnkr.co/edit/DB1CpoWLUxQ9U8y558m1?p=preview
Regards,
Eric
You need some correction in the html.
<label><input type="checkbox" name="checkbox" ng-model="opt.option_value">{{opt.option_value}}</label>
With ng-model="$parent.checkboxAnswer" ,all checkbox will share common model.
So,it will get updated at the same time.
So,when you check/uncheck,it will check/uncheck everyone.
And ,you don;t need to use value,angular is used ng-model property for its value evaluation and not value
Yupii...i found the solution..
here is solution:
<ul>
<label ng-repeat="opt in $parent.checkboxOptions">
<li>
<h4>
<label><input type="checkbox" name="checkbox" ng-model="$parent.$parent.selected[opt.option_value]" >{{opt.option_value}}</label>
</h4>
</li>
</label>
</ul>
(function(angular) {
'use strict';
angular.module('MyApp', [])
.controller('AppCtrl', SettingsController1);
function SettingsController1($scope) {
$scope.options = {
'checkboxAnswer': ''
};
$scope.checkboxOptions= [{
type: 'phone',
value: '917xxxxxxxx'
}, {
type: 'email',
value: 'sajankumarv#example.org'
}];
}
})(window.angular);
radio box template file #radiobox.html
<ul>
<li ng-repeat="opt in checkboxOptions">
<h4>
<label><input type="checkbox" ng-model="options.checkboxAnswer" ng-true-value="'{{opt.value}}'" ng-false-value="''">{{opt.type}}</label>
</h4>
</li>
<h1>{{options.checkboxAnswer}}</h1>
</ul>
//in main index.html you simply include this radiobox.html using ng-include directive
<body ng-app="MyApp">
<div ng-controller="AppCtrl">
<div ng-include='"radiobox.html"'></div>
</div>
</body>
I think you are not in isolate scope so you don't have to use $parent for your case.I made a simple working demo for you to understand kindly refer the below link.
https://plnkr.co/edit/aQMZBln5t0Fipwn1qloN?p=preview

Isolate scope in reusable angular direcives

I have a custom directive : myContent
'use strict';
angular.module('myModule').directive('myContent', function() {
return {
restrict: 'E',
templateUrl: 'myContent.html',
controller: function($scope){
$scope.selectedContents = {
priceOrTransactionOption : null,
yearlyOrMonthly : 'Yearly',
contentIndicator : null
};
$scope.comboContent = {
priceOrTransactionOption : ['By Price Range', 'By Transactions'],
yearlyOrMonthly : ['Yearly', 'Monthly'],
contentIndicator : ['Active configuration', 'Next Configuration']
};
},
controllerAs: 'myContentCtrl'
};
});
And I'm using this same directive in multiple places :
<div class="tab-content col-lg-10">
<my-content></my-content>
</div>
<div class="tab-content col-lg-10">
<my-content></my-content>
</div>
<div class="tab-content col-lg-10">
<my-content></my-content>
</div>
And my html page for the directive (myContent.html) is having some data with :
<div class="row no-left-padding">
<div class="col-lg-3 no-left-padding">
<select class="form-control" ng-model="selectedContent.priceOrTransactionOption"
ng-options="keyOption as keyOption for keyOption in comboContent.priceOrTransactionOption">
</select>
</div>
<div class="col-lg-3 no-left-padding">
<select class="form-control" ng-model="selectedContent.yearlyOrMonthly" ng-disabled = "true"
ng-options="interval as interval for interval in comboContent.yearlyOrMonthly">
</select>
</div>
<div class="col-lg-3 no-left-padding">
<select class="form-control" ng-model="selectedContent.contentIndicator"
ng-options="indicator as indicator for indicator in comboContent.contentIndicator">
</select>
</div>
</div>
But my problem is, when ever I'm changing the model in one directive, it reflects in each directives.
How can I use the same directive, and map each with different models?
I had tried with wadding one attribute to my custom directive:
<div class="tab-content col-lg-10">
<my-content category="type1"></my-content>
</div>
<div class="tab-content col-lg-10">
<my-content category="type2"></my-content>
</div>
<div class="tab-content col-lg-10">
<my-content category="type3"></my-content>
</div>
But still I'm confused with where should I map the category for getting isolated object.
You need to add Isolated scope to your directive. This effectively allows it to have its own set of properties:
angular.module('myModule').directive('myContent', function() {
return {
restrict: 'E',
templateUrl: 'myContent.html',
scope: {
category:'='
},
controller: function($scope){
$scope.selectedContents = {
priceOrTransactionOption : null,
yearlyOrMonthly : 'Yearly',
contentIndicator : null
};
$scope.comboContent = {
priceOrTransactionOption : ['By Price Range', 'By Transactions'],
yearlyOrMonthly : ['Yearly', 'Monthly'],
contentIndicator : ['Active configuration', 'Next Configuration']
};
},
controllerAs: 'myContentCtrl'
};
});
You can then use your example above:
<div class="tab-content col-lg-10">
<my-content category="type1"></my-content>
</div>
And each one will work individually.
Take note though, when you add your properties of the isolated scope binding '='. There are a number of different types, '#', '=' and '&' as well as optional arguments. The naming of your scope property uses snake case. Rather than me giving you a full explanation, read the Angular developers guide on isolated scope
Try adding this in your directive definition:
restrict: 'E',
scope: {},
It appears what you want is to return selectedContents for each instance of the directive. To do this, you would use angular two way binding to create a link between your directive and the page content.
angular.module('myModule').directive('myContent', function() {
return {
restrict: 'E',
templateUrl: 'myContent.html',
scope: {
selectedContents: '='
},
controller: function($scope){
$scope.selectedContents = {
priceOrTransactionOption : null,
yearlyOrMonthly : 'Yearly',
contentIndicator : null
};
....
now, you can refer to the selectedContents as a parameter on the directive.
<div class="tab-content col-lg-10">
<my-content selectedContents="someObject.selectedContents"></my-content>
</div>
<div class="tab-content col-lg-10">
<my-content selectedContents="someOtherObject.selectedContents"></my-content>
</div>

How should i propertly use angular templates (ng-include)?

I made html template and want to use it with angular via ng-include.
<input class="k-textbox" ng-model="entity.Name">
i want to use it twice, so i added it into page like this
<div ng-include="'/template.html'" ng-init="entity=firstEntity"></div>
<div ng-include="'/template.html'" ng-init="entity=secondEntity"></div>
But as a result i getting 2 templates with 'secondEntity' as data, what is proper usage?
This could be a possible usage:
JS:
app.controller("myCtrl1", function($scope) {
$scope.entity = firstEntity;
}
app.controller("myCtrl2", function($scope) {
$scope.entity = secondEndity;
}
HTML:
<div ng-controller="myCtrl1">
<div ng-include="'/template.html'"></div>
</div>
<div ng-controller="myCtrl2">
<div ng-include="'/template.html'"></div>
</div>
Although, reusable templates that require passing different models or configuration are achieved using directives.
EDIT: Directive approach:
JS:
app.controller("myCtrl1", function($scope) {
$scope.entities = {entity1: {}, entity2: {}};
}
app.directive('myDirective', function() {
return {
scope: {
entity: '='
},
template: '<input class="k-textbox" ng-model="entity.Name">'
}
});
HTML:
<div ng-controller="myCtrl1">
<myDirective entity="entities.entity1"></myDirective>
<myDirective entity="entities.entity2"></myDirective>
</div>

How to create a directive for disable all elements into div element

how to create a directive for disable all elements into div element ?
something like this :
<div div-disabled div-disabled-condition="state=='Stack'||state=='Over'||state=='Flow'">
<input type="text"/>
<input type="url"/>
<div>
<input type="text"/>
<input type="url"/>
</div>
<div>
Is it possible? I have no idea .
angular
.module('uiRouterApp.ctrl.add', ['uiRouterApp.ctrl.customDirective'])
.controller('addCtrl', [
'$scope',
'$location',
'$stateParams',
'$state',
function ($scope, $location, $stateParams, $state) {
$scope.state = {};
}
]).directive('divDisabled', function () {
return {
scope: {
divDisabledCondition: '#'
},
link: function (scope, element, attrs) {
}
};
});
Update :
please see this :
<div class="col-sm-12 ng-isolate-scope" selected-object="SelectedAutoComplete" local-data="requirements.Item1" search-fields="NameFa,NameEn" title-field="NameFa" minlength="2" field-required="true" image-field="ImageUrl" disable-auto-compelete="response.State=='Success'||response.State=='Error'||response.State=='Warning'">
<div class="angucomplete-holder">
<input id="_value" ng-model="searchStr" type="text" placeholder="select" class="form-control ng-dirty" ng-focus="resetHideResults()" ng-blur="hideResults()" autocapitalize="off" autocorrect="off" autocomplete="off" ng-change="inputChangeHandler(searchStr)" ng-disabled="response.State=='Success'||response.State=='Error'||response.State=='Warning'" style="">
<!-- ngIf: showDropdown -->
</div>
</div>
directive :
.directive('contentsDisabled', function() {
return {
compile: function(tElem, tAttrs) {
var inputs = tElem.find('input');
for (var i = 0; i < inputs.length; i++) {
inputs.attr('ng-disabled', tAttrs['disableAutoCompelete']);
}
}
}
})
why When the state is 'Success' or 'Error' or 'Warning' Input not disabled ?
You can create a directive that alters its content during compile time by adding the condition. Something along these lines (untested):
module.directive('contentsDisabled', function() {
return {
compile: function(tElem, tAttrs) {
var inputs = tElem.find('input');
inputs.attr('ng-disabled', tAttrs['contentsDisabled']);
}
};
});
See a JSFiddle here: http://jsfiddle.net/HB7LU/6380/
This has the drawback that you just copy the expression from contents-disabled into ng-disabled attributes of any inputs - if somebody uses a directive that in turn creates <input> elements, you won't pick them up.
It'd be less fragile to get hold of the FormController instance and iterate through all its controls, but sadly AngularJS doesn't expose the controls in a form. Maybe file a feature request?
You also can use a tag fieldset :
<form>
<fieldset ng-disable="foo">
<input name="the_one"/>
<input name="the_second"/>
</fieldset>
<input name="the_thrid"/>
</form>
With this way, when the variable foo is TRUE, inputs "the_one" and "the_second" will be disabled.
Why don't you use ng-disabled on your required expression on each input?
https://docs.angularjs.org/api/ng/directive/ngDisabled
If you truly do want a grouping directive, use the compile function of the directive to insert the ng-disabled attribute on each child. Or use a paren't child directive to signify which children to apply the ng-disabled to.
There is a new option to control enable/disable input field for angucomplete-alt.
http://ghiden.github.io/angucomplete-alt/#example13

Dynamic validation and name in a form with AngularJS

I have this form : http://jsfiddle.net/dfJeN/
As you can see the name value for the input is statically set :
name="username"
, the form validation works fine (add something and remove all text from the input, a text must appears).
Then I try to dynamically set the name value : http://jsfiddle.net/jNWB8/
name="{input.name}"
Then I apply this to my validation
login.{{input.name}}.$error.required
(this pattern will be used in an ng-repeat) but my form validation is broken. It is correctly interpreted in my browser (if I inspect the element I saw login.username.$error.required).
Any Idea ?
EDIT: After logging the scope in the console it appears that the
{{input.name}}
expression is not interpolate. My form as an {{input.name}} attribute but no username.
UPDATE: Since 1.3.0-rc.3 name="{{input.name}}" works as expected. Please see #1404
You can't do what you're trying to do that way.
Assuming what you're trying to do is you need to dynamically add elements to a form, with something like an ng-repeat, you need to use nested ng-form to allow validation of those individual items:
<form name="outerForm">
<div ng-repeat="item in items">
<ng-form name="innerForm">
<input type="text" name="foo" ng-model="item.foo" />
<span ng-show="innerForm.foo.$error.required">required</span>
</ng-form>
</div>
<input type="submit" ng-disabled="outerForm.$invalid" />
</form>
Sadly, it's just not a well-documented feature of Angular.
Using nested ngForm allows you to access the specific InputController from within the HTML template. However, if you wish to access it from another controller it does not help.
e.g.
<script>
function OuterController($scope) {
$scope.inputName = 'dynamicName';
$scope.doStuff = function() {
console.log($scope.formName.dynamicName); // undefined
console.log($scope.formName.staticName); // InputController
}
}
</script>
<div controller='OuterController'>
<form name='myForm'>
<input name='{{ inputName }}' />
<input name='staticName' />
</form>
<a ng-click='doStuff()'>Click</a>
</div>
I use this directive to help solve the problem:
angular.module('test').directive('dynamicName', function($compile, $parse) {
return {
restrict: 'A',
terminal: true,
priority: 100000,
link: function(scope, elem) {
var name = $parse(elem.attr('dynamic-name'))(scope);
// $interpolate() will support things like 'skill'+skill.id where parse will not
elem.removeAttr('dynamic-name');
elem.attr('name', name);
$compile(elem)(scope);
}
};
});
Now you use dynamic names wherever is needed just the 'dynamic-name' attribute instead of the 'name' attribute.
e.g.
<script>
function OuterController($scope) {
$scope.inputName = 'dynamicName';
$scope.doStuff = function() {
console.log($scope.formName.dynamicName); // InputController
console.log($scope.formName.staticName); // InputController
}
}
</script>
<div controller='OuterController'>
<form name='myForm'>
<input dynamic-name='inputName' />
<input name='staticName' />
</form>
<a ng-click='doStuff()'>Click</a>
</div>
The problem should be fixed in AngularJS 1.3, according to this discussion on Github.
Meanwhile, here's a temporary solution created by #caitp and #Thinkscape:
// Workaround for bug #1404
// https://github.com/angular/angular.js/issues/1404
// Source: http://plnkr.co/edit/hSMzWC?p=preview
app.config(['$provide', function($provide) {
$provide.decorator('ngModelDirective', function($delegate) {
var ngModel = $delegate[0], controller = ngModel.controller;
ngModel.controller = ['$scope', '$element', '$attrs', '$injector', function(scope, element, attrs, $injector) {
var $interpolate = $injector.get('$interpolate');
attrs.$set('name', $interpolate(attrs.name || '')(scope));
$injector.invoke(controller, this, {
'$scope': scope,
'$element': element,
'$attrs': attrs
});
}];
return $delegate;
});
$provide.decorator('formDirective', function($delegate) {
var form = $delegate[0], controller = form.controller;
form.controller = ['$scope', '$element', '$attrs', '$injector', function(scope, element, attrs, $injector) {
var $interpolate = $injector.get('$interpolate');
attrs.$set('name', $interpolate(attrs.name || attrs.ngForm || '')(scope));
$injector.invoke(controller, this, {
'$scope': scope,
'$element': element,
'$attrs': attrs
});
}];
return $delegate;
});
}]);
Demo on JSFiddle.
Nice one by #EnISeeK.... but i got it to be more elegant and less obtrusive to other directives:
.directive("dynamicName",[function(){
return {
restrict:"A",
require: ['ngModel', '^form'],
link:function(scope,element,attrs,ctrls){
ctrls[0].$name = scope.$eval(attrs.dynamicName) || attrs.dynamicName;
ctrls[1].$addControl(ctrls[0]);
}
};
}])
Just a little improvement over EnlSeek solution
angular.module('test').directive('dynamicName', ["$parse", function($parse) {
return {
restrict: 'A',
priority: 10000,
controller : ["$scope", "$element", "$attrs",
function($scope, $element, $attrs){
var name = $parse($attrs.dynamicName)($scope);
delete($attrs['dynamicName']);
$element.removeAttr('data-dynamic-name');
$element.removeAttr('dynamic-name');
$attrs.$set("name", name);
}]
};
}]);
Here is a plunker trial. Here is detailed explantion
I expand the #caitp and #Thinkscape solution a bit, to allow dynamically created nested ng-forms, like this:
<div ng-controller="ctrl">
<ng-form name="form">
<input type="text" ng-model="static" name="static"/>
<div ng-repeat="df in dynamicForms">
<ng-form name="form{{df.id}}">
<input type="text" ng-model="df.sub" name="sub"/>
<div>Dirty: <span ng-bind="form{{df.id}}.$dirty"></span></div>
</ng-form>
</div>
<div><button ng-click="consoleLog()">Console Log</button></div>
<div>Dirty: <span ng-bind="form.$dirty"></span></div>
</ng-form>
</div>
Here is my demo on JSFiddle.
I used Ben Lesh's solution and it works well for me. But one problem I faced was that when I added an inner form using ng-form, all of the form states e.g. form.$valid, form.$error etc became undefined if I was using the ng-submit directive.
So if I had this for example:
<form novalidate ng-submit="saveRecord()" name="outerForm">
<!--parts of the outer form-->
<ng-form name="inner-form">
<input name="someInput">
</ng-form>
<button type="submit">Submit</button>
</form>
And in the my controller:
$scope.saveRecord = function() {
outerForm.$valid // this is undefined
}
So I had to go back to using a regular click event for submitting the form in which case it's necessary to pass the form object:
<form novalidate name="outerForm"> <!--remove the ng-submit directive-->
<!--parts of the outer form-->
<ng-form name="inner-form">
<input name="someInput">
</ng-form>
<button type="submit" ng-click="saveRecord(outerForm)">Submit</button>
</form>
And the revised controller method:
$scope.saveRecord = function(outerForm) {
outerForm.$valid // this works
}
I'm not quite sure why this is but hopefully it helps someone.
This issue has been fixed in Angular 1.3+
This is the correct syntax for what you are trying to do:
login[input.name].$invalid
if we set dynamic name for a input like the below
<input name="{{dynamicInputName}}" />
then we have use set validation for dynamic name like the below code.
<div ng-messages="login.dynamicInputName.$error">
<div ng-message="required">
</div>
</div>

Resources