How do you find first visible element with jqlite under AngularJS? - javascript

So, I have the following Angular directive to autofocus first input field on the current page of my Ionic application. It works great when the first field isn't hidden. But, if it's hidden by ng-hide, logic fails. So need to modify the element selector to find just for visible elements in my directive.
angular.module('myApp').directive('focusMe', function($timeout) {
return {
link: function(scope, element, attrs) {
$timeout(function() {
element.find('label')[0].focus();
}, 150);
}
};
});
Using above directive on a form element as follows,
<form name="signinForm" ng-submit="signinForm.$valid && doSignin(credentials)" novalidate focus-me>
So how should I change my jQLite find query to just look for the visible element? The find lookup is limited by tag name as per docs.

You can write something like this:
element[0].querySelector('input:not(.ng-hide)').focus();
jQLite only allows selecting by tag name. So we can use the pure Javascript version i.e. querySelector along with using :not selector.
See a working example below:
angular.module('myApp', [])
.directive('focusMe', function($timeout) {
return {
link: function(scope, element, attrs) {
$timeout(function() {
element[0].querySelector('input:not(.ng-hide)').focus();
}, 150);
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<form focus-me ng-app="myApp">
<input type="text" name="firstName" ng-show="false" />
<input type="text" name="lastName" ng-show="true" />
<input type="text" name="email" />
</form>

Related

Retrieving the value of ng-model from Directives template to Another Html file

I can't retrieve the ng-model value of my template-url from my name directive.
team-two.html
<form name="userForm" novalidate>
<div name-directive></div>
</form>
<pre>{{userForm.firstname}}</pre>
here i have name-directive inside the form and a pre tag to view as I type a value in input text of name-directive
name-directive.js
(function () {
'use strict';
var app = angular.module('app.input-form');
app.directive('nameDirective', function () {
return {
restrict: 'AE',
scope: true,
controller: function() {
var vm = this;
vm.namePattern = /^[a-zA-Z ]{1,25}$/;
},
controllerAs: 'vm',
templateUrl: '/src/client/app/input-form/name.html'
}
});
})();
in here, I have a templateUrl dont mind the other codes coz I think it not related to my concern.
name.html
<input type="text" name="firstname" class="form-control" placeholder="Enter
your first name"
ng-model="firstname"
ng-minlength="2"
ng-maxlength="20"
required
ng-pattern="vm.namePattern"/>
in here, I have a ng-model that I want to access which is the firstname..
Edit Note: I discovered that if I add $viewValue in <pre>{{userForm.firstname.$viewValue}}</pre> it works.. I get what I want.. But I think that it is not the exact solution for my problem..
Edit 2 Added link to Plunker: https://plnkr.co/edit/6glStzEq5ckZZzph2qLw?p=preview
Since you use the controllerAs in the directive need to reference that when you are accessing variables from the html.
ng-model="vm.firstname"
<input type="text" name="firstname" class="form-control" placeholder="Enter
your first name"
ng-model="vm.firstname"
ng-minlength="2"
ng-maxlength="20"
required
ng-pattern="vm.namePattern"/>

AngularJS - exclude field from form validation / dirty

I have a checkbox inside ng-form rapped by HTML5 form that I want to exclude so it won't change my form $state($pristine or $dirty).
I have tried using ignoreDirty directive - Angular 1.2: Is it possible to exclude an input on form dirty checking?
and some other solutions and none work for ng-form inside HTML5 form, some example code:
<form name="mainForm" class="col-xs-10 form-validation" novalidate>
<ng-form name="innerForm">
<div>
<span>check my
<span ng-if="vm.utils.mode!=='readonly'">
<input type="checkbox"
ng-model="vm.utils.amalotSecond"
class="secondYearCheckBox">
</span>
</span>
</div>
</ng-form>
<form>
The ignoreDirty directive you provided works fine like in this demo fiddle. The following code example was taken from angular-1-2-is-it-possible-to-exclude-an-input-on-form-dirty-checking. Also try to avoid using nested forms which are not HTML conform. An form element can't have an element form. It will cause problems and errors e.g. the one you are currently facing.
View
<div ng-controller="MyCtrl">
<form name="test">
Watching dirty: <input ng-model="name" /><br />
Ignoring dirty: <select ng-model="gender" ignore-dirty>
<option>male</option>
<option>female</option>
</select><br />
dirty: {{test.$dirty}}
</form>
</div>
AngularJS application
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl', function ($scope) {
$scope.name = 'Superhero';
});
myApp.directive('ignoreDirty', [function() {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
ctrl.$setPristine = function() {};
ctrl.$pristine = false;
}
}
}]);

validate input element nested in ng-repeat also on page load, not only on change

I have an angularjs page. I made a custom directive in order to validate an input element that is nested in an ng-repeat. Now, the validation works, but I also need it to work on page load and on changes that happen on the page (like drop down selected and button clicked), not only when the user changes the value. I also need to add the the directive (or to the validation) to see if there is a value for a filter from a controller on this module.
Any suggestions? Here is my current code:
.directive('myDirective', function() {
return {
require: 'ngModel',
link: function(scope, element, attr, mCtrl) {
function myValidation(value) {
mCtrl.$setValidity('charE', false);
if (value>1){
mCtrl.$setValidity('charE', true);
} else {
mCtrl.$setValidity('charE', false);
}
return value;
}
mCtrl.$parsers.push(myValidation);
}
};
})
here is my call to it:
<td align="center">
<form name="myForm">
<!--<input name="myInput" ng-model="myInput" required my-directive>-->
<input type="number" name="myInput" ng-model="item.qtyToOrder" ng-model-options="{ updateOn: 'blur' }" ng-change="SavePO(item.qtyToReOrder, item.qtyToOrder, {{$index}})" required my-directive/>
<!--<span>test - {{myForm.myInput.$valid}}</span>-->
</form>
</td>
Maybe ngOnInit() {} helps with your problem!
see https://angular.io/docs/ts/latest/api/core/OnInit-interface.html
was able to do it straight on the DOM.
<input ng-class="{ 'has-error': item.qtyToOrder<=0 && filter.vendor !='' }" type="number" name="myInput" ng-model="item.qtyToOrder" ng-model-options="{ updateOn: 'blur' }" ng-change="SavePO(item.qtyToReOrder, item.qtyToOrder, {{$index}})" />

Re-focus input field right after blur event in AngularJS

i have a html input field and would like to stay focussed on it no matter what happens. I know how to achieve it with JQuery but i only want to embed it if i really need to. My code example doesn't work.
My thoughts for code so far:
HTML
<input type="text" ng-blur="refocus()" autofocus>
AngularJS (inside my controller)
$scope.refocus = function($scope, $element) {
$element.focus();
};
I hope you guys have the right inspiration or better solution to solve this :)
You can keep an element focused with the following directive:
angular.module('test', []).directive('stayFocused', function(){
return {
link: function($scope, $element){
$element.on('blur', function(){
$element[0].focus();
});
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="test">
First
<input type="text" stay-focused="" autofocus>
<br />
Second
<input type="text" stay-focused="" autofocus>
</div>

Angular get the current form in the html

I'm wondering if it is possible to retrieve the current form in a html template.
To be clear, I actually would like to reuse some form fields this way:
<form name="myForm">
<div ng-include src="'templates/form-field/email.html'">
<div ng-include src="'templates/form-field/password.html'">
</form>
Here is templates/form-field/email.html:
<div>
<label>Email:</label>
<input type="email" name="email" ng-model="data.email" ng-required="true">
</div>
<div ng-show="myForm.email.$error.required && myForm.email.$touched" class="error">Email is required</div>
<div ng-show="myForm.email.$error.email && myForm.email.$touched" class="error">Email is not valid</div>
So this works well and allows me to re-use HTML components including error messages.
However, I have to to give a static name to my form (here "MyForm")
Is there any way to retrieve the current form inside the tags?
I'm quite new with angular so there may even be better ways to achieve the same behavior (i.e. re-use html components / error messages) that I'm not aware of.
I'm interesting in any solution as long as it does not include any 3rd parties.
Maybe using $scope to define the name of the form?
With ng-include it creates a child scope from the parent so the data is only shared one-way, from parent to child. You will need to create a directive instead and set scope to false, or not declare it at all since that is the default, so that the controller and the directive will share the same scope.
Email Directive:
directive('emailTemplate', [function(){
return {
templateUrl: 'templates/form-field/email.html',
link: function(scope, elem, attrs) {
}
};
}]);
Password Directive:
directive('passwordTemplate', [function(){
return {
templateUrl: 'templates/form-field/password.html',
link: function(scope, elem, attrs) {
}
};
}]);
HTML
<form name="myForm">
<email-template></email-template>
<password-template></password-template>
</form>
EDIT
Email Directive:
directive('emailTemplate', [function(){
return {
templateUrl: 'templates/form-field/email.html',
link: function(scope, elem, attrs) {
scope.form = scope[attrs.formName];
}
};
}]);
HTML
<form name="myForm">
<email-template form-name="myForm"></email-template>
<password-template form-name="myForm"></password-template>
</form>
Template
<div>
<label>Email:</label>
<input type="email" name="email" ng-model="data.email" ng-required="true">
</div>
<div ng-show="form.email.$error.required && form.email.$touched" class="error">Email is required</div>
<div ng-show="form.email.$error.email && form.email.$touched" class="error">Email is not valid</div>

Categories

Resources