I am using Ionic Angularjs and want, after typing 3 characters into a input type text, to set the focus on the next input .
Can I use limitTo filter combining with another angularjs feature?
For this you can use AngularJS directives, combined with HTML5's input maxlength attribute:
The directive
angular.module('myApp', [])
.directive('focusAfter', function() {
return {
restrict: 'A',
scope: {
elemToFocus: '#'
},
link: function(scope, elem, attrs) {
var elementToFocus = document.getElementById(scope.elemToFocus);
elem.on('keyup', function() {
if(elem.val().length === 3) {
window.setTimeout(function() {
elementToFocus.focus();
});
}
});
}
};
});
View
<input type="text" maxlength="3" id="input1" focus-after elem-to-focus="input2">
<input type="text" maxlength="3" id="input2" focus-after elem-to-focus="input3">
<input type="text" maxlength="3" id="input3" focus-after elem-to-focus="input1">
Here's a plunkr: http://plnkr.co/edit/QvS0dwUNW3oAhHID1VRX?p=info
Related
I have a custom directive obtained from https://github.com/neoziro/angular-match that matches two form fields. However, how can I customize it to match more than one field? Here is better explanation of what I mean:
-Form Field 1
-Form Field 2
-Form Field 3
-Form Field 4
-Confirmation (I want this one to match either Field 1,2,3 OR 4.)
Currently, I can only match it up to one field.
HTML Form:
<input type="text"
name="correctAnswer"
ng-model="quiz.quizData.correctAnswer"
match="answer1">
<div ng-show="theQuiz.correctAnswer.$error.match && !theQuiz.correctAnswer.$pristine">Answers do not match!</div>
Directive:
angular.module('match', []).directive('match', ['$parse', matchDirective]);
function matchDirective($parse) {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, ctrl) {
scope.$watch(function () {
return [scope.$eval(attrs.match), ctrl.$viewValue];
}, function (values) {
ctrl.$setValidity('match', values[0] === values[1]);
}, true);
}
};
}
It might be easier to write your own directive for this, especially since angular-match plugin is no longer maintained.
To watch multiple form inputs, just pass the ng-model of each desired input to the directive. Here I called it match.
<input type="text" name="firstNameOne" ng-model="firstNameOne"/>
<input type="text" name="firstNameTwo" ng-model="firstNameTwo"/>
<input type="text" name="firstNameThree" ng-model="firstNameThree"/>
<input type="text" name="confirmFirstName" ng-model="confirm" match="{{[firstNameOne, firstNameTwo, firstNameThree]}}"/>
Now for the directive
app.directive('match', function() {
return {
restrict: 'A',
controller: function($scope) {
$scope.doValidation = function(matches) {
//Validation logic.
}
},
link: function(scope, element, attrs) {
scope.$watch('confirm', function() {
scope.matches = JSON.parse(attrs.match); //Parse the array.
scope.doValidation(scope.matches); //Do your validation here.
});
}
}
});
Here is a fiddle showing validation of form inputs: https://jsfiddle.net/cpgoette/und9t5ee/
How to disable special characters in angular js input tag. Only allow alphanumeric
just like we use
<input type="text" ng-trim="false" style="text-transform: uppercase" ng-pattern="/^[a-zA-Z0-9]*$/" class="form-text" id="pan_card_number" name="pan_card_number" ng-minlength="10" maxlength="10" required ng-model="registration.newTSP.panCardNumber">
you can use Regex with Ng-pattern and Display the message through ng-message
$scope.useOnlySpecialCharacters = /^[a-zA-Z0-9]*$/;
<input type="text" ng-model="specialcharacters"
ng-pattern="useOnlySpecialCharacters" />
show message through ng-message
<div ng-message="pattern"> Please Enter AlphaNumeric </div>
OR
Best Option is to use Directives
app.directive('noSpecialChar', function () {
return {
require: 'ngModel',
restrict: 'A',
link: function (scope, element, attrs, modelCtrl) {
modelCtrl.$parsers.push(function (inputValue) {
if (inputValue == null) {
return '';
}
var cleanInputValue = inputValue.replace(/[^\w\s]/gi, '');
if (cleanInputValue != inputValue) {
modelCtrl.$setViewValue(cleanInputValue);
modelCtrl.$render();
}
return cleanInputValue;
});
}
}
});
LINK
use ng-pattern="/[A-Z]{5}\d{4}[A-Z]{1}/i" in your HTML input tag
use the following
Controller
$scope.panCardRegex = '/[A-Z]{5}\d{4}[A-Z]{1}/i';
HTML
<input type="text" ng-model="abc" ng-pattern="panCardRegex" />
Use Directives to restrict Special characters:
angular.module('scPatternExample', [])
.controller('scController', ['$scope', function($scope) {
}])
.directive('restrictSpecialCharactersDirective', function() {
function link(scope, elem, attrs, ngModel) {
ngModel.$parsers.push(function(viewValue) {
var reg = /^[a-zA-Z0-9]*$/;
if (viewValue.match(reg)) {
return viewValue;
}
var transformedValue = ngModel.$modelValue;
ngModel.$setViewValue(transformedValue);
ngModel.$render();
return transformedValue;
});
}
return {
restrict: 'A',
require: 'ngModel',
link: link
};
});
<input type="text" ng-model="coupon.code" restrict-Special-Characters-Directive>
set pattern to allow only alphanumeric
/^[a-z0-9]+$/i
I am new to Angular JS and I am doing form validation for login page using Angular Js. If I enter username and password, it is working fine But if I choose remember credentials in browser and choose autocomplete options next time, my Submit button is not enabled. I am facing this issue only in IE9. for rest of the browsers its working fine. Any suggestions for this. My login.html looks like this:
<input ng-model="username"
class="login"
value=""
name="userId"
type="text"
required/>
<input ng-model="password"
class="login"
value=""
name="password"
type="password"
required/>
<button class="primaryButton"
type="submit"
ng-click="loginUser()"
ng-disabled="loginForm.$invalid"/>
Also, as per one blog, I tried adding directive for this. By adding directive, If I choose autocomplete options and just mouse click somewhere, submit button is enabled. But I don't want to click after choosing autocomplete option.
My directive looks like this:
angular.module('sampleModule').directive('autofill', function autofill(){
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, ngModel) {
scope.$watch(function () {
return element.val();
}, function(nv, ov) {
if(nv !== ov) {
ngModel.$setViewValue(nv);
}
});
}
};
})
You may need to apply a timeout to your directive's logic to force it to alert IE that it needs to re-render.
angular.module('sampleModule').directive('autofill', ['$timeout',
function autofill($timeout){
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, ngModel) {
scope.$watch(function () {
$timeout(function () {
return element.val();
}, 0);
}, function(nv, ov) {
$timeout(function () {
if(nv !== ov) {
ngModel.$setViewValue(nv);
}
}, 0);
});
}
};
}]);
Try to copy at interval times, because IE9 (and chrome) doesn't emit events for user and password autocomplete.
Set respective ids for inputs, and then:
app.controller('yourController', function($scope, $interval) {
$interval(function() {
$scope.username = $('#username').val();
$scope.password = $('#password').val();
}, 1000); // each 1 second
});
of course, you can adapt this soluction to your directive.
try a directive to call change from element:
directive('monitorAutoFill', function($timeout) {
return {
restrict: 'A',
link: function(scope, el, attrs, ctrl) {
$timeout(function() {
el.trigger('change');
}, 500);
}
};
});
and, on your inputs:
<input ng-model="username"
class="login"
value=""
name="userId"
type="text"
required
monitor-auto-fill />
<input ng-model="password"
class="login"
value=""
name="password"
type="password"
required
monitor-auto-fill />
I have this directive:
(function () {
'use strict';
var app = angular.module('myAppName');
app.directive('smFocus', [ '$timeout', function ($timeout) {
return {
restrict: 'A',
link: function (scope, element) {
scope.$on('sm:focus', function () {
$timeout(function() {
element[0].focus();
}, 10);
});
}
};
}]);
})();
I also have these two controls:
<input type="text"
name="nickname"
id="nickname"
ng-model="currentDynamicRule.nickname"
class="form-control"
ng-disabled="!isNew"
placeholder="Nickname"
required
ng-maxlength="10"
sm-focus />
and another one
<input type="text" name="descrip" id="descrip" ng-model="currentDynamicRule.descrip" class="form-control"
placeholder="Description" required ng-maxlength="30"
sm-focus />
So, two controls where the first one is only enabled when it's a new row (disabled in Edit mode). I want to have the first control focused when it's a new record and the second control focused when it's in edit mode.
I am using ASP.NET MVC. Right now in both edit and new modes I have the second control focused. I am not sure how to make this focus conditional.
hmm I had written a directive before wherein it accepts an event and an element id to focus when that event has been triggered.
It's something like this(Plunker DEMO):
JAVASCRIPT
.directive('eventFocus', function($timeout) {
return function(scope, elem, attr) {
elem.on(attr.eventFocus, function() {
// timeout makes sure that is invoked after any other event has been triggered.
// e.g. click events that need to run before the focus or
// inputs elements that are in a disabled state but are enabled when those events
// are triggered.
$timeout(function() {
var element = document.getElementById(attr.eventFocusId);
if(element)
element.focus();
});
});
scope.$on('$destroy', function() {
element.off(attr.eventFocus);
});
};
})
HTML (Possible implementation)
<input type="text" id="pet-desc" ng-model="pet.desc">
<button type="button" event-focus="click" event-focus-id="pet-desc">Edit</button
When Edit Button is clicked, input with id="pet-desc" is focused.
UPDATE:
To identify between which sm-focus element is the target for the sm:focus event, you can add an argument(the id of the element to focus to) within your $rootScope.$broadcast(). See this PLUNKER.
e.g.
Controller
$rotoScope.$broadcast('sm:focus', 'pet-id');
Directive
directive('smFocus', function($timeout) {
return function(scope, elem, attr) {
scope.$on('sm:focus', function(event, id) {
$timeout(function() {
if(attr.id == id)
elem[0].focus();
});
});
};
})
Here is my current implementation that seems to be working! Need to test more:
app.directive('smFocus', [ '$timeout', function ($timeout) {
return {
restrict: 'A',
scope: {
noFocus: "=?"
},
link: function (scope, element) {
var noFocus = angular.isDefined(scope.noFocus) ? scope.noFocus : false;
// console.log('noFocus=' + noFocus)
if (!noFocus) {
scope.$on('sm:focus', function () {
$timeout(function () {
element[0].focus();
}, 10);
});
}
}
};
And my form controls are:
<input type="text"
name="nickname"
id="nickname"
ng-model="currentDynamicRule.nickname"
class="form-control"
ng-disabled="!isNew"
placeholder="Nickname"
required
ng-maxlength="10"
no-focus="!isNew"
sm-focus />
And similar for description:
<input type="text" name="descrip" id="descrip" ng-model="currentDynamicRule.descrip" class="form-control"
placeholder="Description" required ng-maxlength="30"
no-focus="isNew"
sm-focus />
The form works as I want it. I am going to test few more forms to make sure this change didn't break anything.
Is there a cleaner way of delegating focus to an element when a checkbox is clicked. Here's the dirty version I hacked:
HTML
<div ng-controller="MyCtrl">
<input type="checkbox" ng-change="toggled()">
<input id="name">
</div>
JavaScript
var myApp = angular.module('myApp',[]);
function MyCtrl($scope, $timeout) {
$scope.value = "Something";
$scope.toggled = function() {
console.debug('toggled');
$timeout(function() {
$('#name').focus();
}, 100);
}
}
JSFiddle: http://jsfiddle.net/U4jvE/8/
how about this one ? plunker
$scope.$watch('isChecked', function(newV){
newV && $('#name').focus();
},true);
#asgoth and #Mark Rajcok are correct. We should use directive. I was just lazy.
Here is the directive version. plunker I think one good reason to make it as directive is you can reuse this thing.
so in your html you can just assign different modals to different sets
<input type="checkbox" ng-model="isCheckedN">
<input xng-focus='isCheckedN'>
directive('xngFocus', function() {
return function(scope, element, attrs) {
scope.$watch(attrs.xngFocus,
function (newValue) {
newValue && element.focus();
},true);
};
});
Another directive implementation (that does not require jQuery), and borrowing some of #maxisam's code:
myApp.directive('focus', function() {
return function(scope, element) {
scope.$watch('focusCheckbox',
function (newValue) {
newValue && element[0].focus()
})
}
});
HTML:
<input type="checkbox" ng-model="focusCheckbox">
<input ng-model="name" focus>
Fiddle.
Since this directive doesn't create an isolate scope (or a child scope), the directive assumes the scope has a focusCheckbox property defined.
If you want to make it more interesting, and support for any expression to be evaluated (not only variables), you can do this:
app.directive('autofocusWhen', function ($timeout) {
return {
link: function(scope, element, attrs) {
scope.$watch(attrs.autofocusWhen, function(newValue){
if ( newValue ) {
$timeout(function(){
element.focus();
});
}
});
}
};
});
And your html can be a little more decoupled, like that:
<input type="checkbox" ng-model="product.selected" />
{{product.description}}
<input type="text" autofocus-when="product.selected" />
A cleaner way is to use a directive to perform the toggle:
app.directive('toggle', function() {
return {
restrict: 'A',
scope: {
selector: '='
},
link: function(scope, element, attrs) {
element.on('change', function() {
$(scope.selector).focus();
scope.$apply();
});
}
}:
});
Your html would be sth like:
<input type='checkbox' toggle selector='#name'>