add http:// to input if not present on blur - angularjs

For all input fields with the type of url (input[type=url]), on blur I wish to check if the value of an input contains http:// or https:// and if it does not to add http:// to the beginning of the user inputted value. Similar to the below jquery:
$('.txtUrl').blur(function(e) {
if ($(this).val().match(/^http/) || $(this).val().match(/^https/)) {
$.noop()
}
else {
// get value from field
var cur_val = $(this).val();
// do with cur_val
$(this).val('http://' + cur_val);
}
});
How do I do this the angular way?

You could do the same functionality using angular directive.
Define ng-model that will take care of ng-model value.
Markup
<input type="url" my-directive ng-model="myUrl"/>
Directive
app.directive('myDirective', function() {
return {
restrict: 'AE',
require: 'ngModel',
link: function(scope, element, attrs, ctrl) {
var model = $parse(attrs.ngModel)
element.on('blur', function(e) {
var value = ctrl.$modelValue; //ngModel Value
if (value.match(/^http/) || value.match(/^https/)) {
angular.noop()
} else {
// assign value to $modelValue
model.assign(scope, 'http://' + value);
}
});
}
}
});
This could help you, Thanks.

Related

AngularJS Custom Validation Directives - How to avoid using isolated scope

I'm attempting to use multiple angular validators on a text field, but have run into the Multiple directives requesting isolated scope error. (Please read on before closing as a duplicate.)
All the solutions I've seen so far, recommend removing the scope: {...} from the offending directives, however for my scenario, I need to evaluate variables from the controller (and $watch them for changes).
I've tried using attrs.$observe, but I can't work out how to get the evaluated variables into the $validator function. (Additionally, I can't $observe the ngModel).
Please let me know if there's a another way to solve this issue.
Here's the smallest example I could put together. N.B. maxLength validator's scope is commented out, essentially disabling it:
angular
.module('app', [])
// validates the min length of a string...
.directive("minLen", function() {
return {
require: 'ngModel',
restrict: 'A',
scope: {
ngModel: '=',
minLen: '='
},
link: function(scope, element, attrs, ngModelCtrl) {
scope.$watch('ngModel', function(){
ngModelCtrl.$validate();
});
scope.$watch('minLen', function(){
ngModelCtrl.$validate();
});
ngModelCtrl.$validators.minLength = function(modelValue, viewValue) {
var value = modelValue || viewValue;
return angular.isUndefined(scope.minLen) ||
angular.isUndefined(value) ||
value.length >= scope.minLen;
};
}
};
})
.directive("maxLen", function() {
return {
require: 'ngModel',
restrict: 'A',
// Commented out for now - causes error.
// scope: {
// ngModel: '=',
// maxLen: "="
// },
link: function(scope, element, attrs, ngModelCtrl) {
scope.$watch('ngModel', function(){
ngModelCtrl.$validate();
});
scope.$watch('maxLen', function(){
ngModelCtrl.$validate();
});
ngModelCtrl.$validators.maxLength = function(modelValue, viewValue) {
var value = modelValue || viewValue;
return angular.isUndefined(scope.maxLen) ||
angular.isUndefined(value) ||
value.length >= scope.maxLen;
};
}
};
})
// this controller just initialises variables...
.controller('CustomController', function() {
var vm = this;
vm.toggleText = function(){
if (vm.text === 'aaa') {
vm.text = 'bbbbb';
} else {
vm.text = 'aaa';
}
}
vm.toggle = function(){
if (vm.minLen === 3) {
vm.minLen = 4;
vm.maxLen = 12;
} else {
vm.minLen = 3;
vm.maxLen = 10;
}
};
vm.toggleText();
vm.toggle();
return vm;
})
;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
<div ng-app="app" ng-controller="CustomController as ctrl">
<ng-form name="ctrl.form">
<label>Enter {{ctrl.minLen}}-{{ctrl.maxLen}} characters: </label>
<input
name="text"
type="text"
ng-model="ctrl.text"
min-len="ctrl.minLen"
max-len="ctrl.maxLen"
/>
</ng-form>
<br/><br/>
<button ng-click="ctrl.toggle()">Modify validation lengths</button>
<button ng-click="ctrl.toggleText()">Modify ngModel (text)</button>
<h3>Validation (just list $error for now)</h3>
<pre>{{ ctrl.form.text.$error | json }}</pre>
</div>
remove isolated scope
You dont need to observe, watch ngModel - when it changes, angular will run validator for you.
Decide how you want to use your directive: my-val-dir="{{valName}}" vs my-val-dir="valName". In first case you use attrs.$observe('myValDir'), in second $watch(attrs.myValDir) & $eval.
When your value gonna be something simple, like number or short string - first way seems good, when value is something big, i.e. array - use second approach.
Remove isolate scope and use scope.$watch to evaluate the attribute:
app.directive("minLen", function() {
return {
require: 'ngModel',
restrict: 'A',
scope: false,
// ngModel: '=',
// minLen: '='
// },
link: function(scope, element, attrs, ngModelCtrl) {
var minLen = 0;
scope.$watch(attrs.minLen, function(value){
minLen = toInt(value) || 0;
ngModelCtrl.$validate();
});
ngModelCtrl.$validators.minLength = function(modelValue, viewValue) {
return ngModelCtrl.$isEmpty(viewValue) || viewValue.length >= minLen;
};
}
};
})
There is no need to watch the ngModel attribute as the ngModelController will automatically invoke the functions in the $validators collection when the model changes.
When the watch expression is a string, the string attribute will be evaluated as an Angular Expression.
For more information, see AngularJS scope API Reference - $watch.

How to access ng-model from attribute directive?

I'm trying to write a custom directive to validate input value: does it belong to the specified range. The problem is that I can't access ng-model without knowing the name of the scope variable which is used for ng-model. Considering that directive has to be reused with different inputs I want to access ng-model directly. I did try to use scope[attrs.ngModel] but got the undefined value. How can read ng-model value inside directive? Thank you.
netupApp.directive('between', function() {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, element, attrs, ngModelCtrl) {
scope.$watch('dataSubmitting', function(dataSubmitting){
if (dataSubmitting) {
var min = Number(attrs.min);
var max = Number(attrs.max);
console.log(attrs.ngModel); // "number"
console.log(scope[attrs.ngModel]); // undefined
var inputText = scope.number; // that is the var used in ng-model
console.log(min); // 10
console.log(inputText); // would be the input value
console.log(max); //20
if (inputText <= min || inputText >= max) {
scope.alerts.push({
msg: 'error',
type: 'danger',
icon: 'warning',
'closable': true
});
}
}
});
}
};
});
You should hook into the Angular validation system and add your validator function to either the $validators or $asyncValidators collections (in your case I think $validators is enough, no need for async).
The validator functions receive the model value as an argument :
link: function(scope, elm, attrs, ctrl) {
var min = Number(attrs.min);
var max = Number(attrs.max);
ctrl.$validators.between = function(modelValue, viewValue) {
if (modelValue <= min || modelValue >= max) {
//do something here or just return false
return false;
}
return true;
}
}
In the view you can get the validation error messages like this :
<div ng-messages="formName.inputName.$error">
<p ng-message="between">The value is not in the required range<p>
</div>
Reference doc : https://docs.angularjs.org/api/ng/type/ngModel.NgModelController
The proper way to get the ngModel.$viewValue is:
app.directive('between', function () {
return {
require: 'ngModel',
link: function (scope, element, attrs, ngModel) {
ngModel.$render = function () {
var newValue = ngModel.$viewValue;
console.log(newValue)
};
}
};
});
Have a look at tutorial underneath when wanting to invoke the ngModel.$setViewVAlue from the directive
https://egghead.io/lessons/angularjs-using-ngmodel-in-custom-directives
According to angluarJs doc:$parse
you need to parse the attrs, please try:
var getter=$parse(attrs.ngModel);
var setter=getter.assign;
setter(scope,getter(scope));

how to display object in json formate in angular js?

I am trying to display value of all my fields in a json object .I am able to add firstname ,email , password in an object.but my confirm password not displaying in object why ? I enter same password with confirm password still not display
here is my code
http://plnkr.co/edit/iHA8iQC1HM5OzZyIg4p3?p=preview
angular.module('app', ['ionic','ngMessages']).directive('compareTo',function(){
return {
require: "ngModel",
scope: {
otherModelValue: "=compareTo"
},
link: function(scope, element, attributes, ngModel) {
ngModel.$validators.compareTo = function(modelValue) {
// alert(modelValue == scope.otherModelValue)
return modelValue == scope.otherModelValue;
};
scope.$watch("otherModelValue", function() {
ngModel.$validate();
});
}
};
why confirm password not display ?
}).controller('first',function($scope){
})
Your compareTo directive fails and it will not bind to a model if the validator is failing. If you remove your compareTo directive from the code you will get the confiredpassword in your scope.
Refer to this: password-check directive in angularjs to fix your comparTo directive.
Also here is a plunker of the fixed directive:
http://plnkr.co/edit/wM3r6eR2jhQS7cjvreLo?p=preview
.directive('compareTo', function() {
return {
scope: {
targetModel: '=compareTo'
},
require: 'ngModel',
link: function postLink(scope, element, attrs, ctrl) {
var compare = function() {
var e1 = element.val();
var e2 = scope.targetModel;
if (e2 !== null) {
return e1 === e2;
}
return false;
};
scope.$watch(compare, function(newValue) {
ctrl.$setValidity('errorCompareTo', newValue);
});
}
};

Directive doesn't update scope variable

I have a directive that formats a phone number to (xxx) xxx-xxxx. The formatting works as expected, however, the model on the input field isn't updating unless you enter one character passed the standard 10. So after the user enters 10 digits the number automatically formats inside of the input field. But the scope variable set on ng-model does not save the formatting unless you enter an additional character.
Here's the directive:
(function (app) {
'use strict';
app.directive('formatPhone', [
function() {
return {
require: 'ngModel',
restrict: 'A',
link: function(scope, elem) {
elem.on('keyup', function() {
var origVal = elem.val().replace(/[^\d]/g, '');
if(origVal.length === 10) {
var str = origVal.replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3');
var phone = str.slice(0, -1) + str.slice(-1);
jQuery('#phonenumber').val(phone);
}
});
}
};
}
]);
}(window.app));
And here is the input field, using the directive as an attribute:
<input type="text" placeholder="Phone" name="phone" id="phonenumber" class="user-search-input create-short form-control" ng-model="userCtrl.userPost.user.phoneNumber" required format-phone>
I've tried adding a $watch to it, also with no luck.
Try like
.directive('formatPhone', [
function() {
return {
require: 'ngModel',
restrict: 'A',
priority:999999, //<-- Give a higher priority
scope: {
model:'=ngModel' //<-- A 2 way binding to read actual bound value not the ngModel view value
},
link: function(scope, elem, attrs, ctrl) {
var unwatch = scope.$watch('model', function(val){
if(!val) return;
var origVal = val.replace(/[^\d]/g, '');
if(origVal.length === 10) {
var str = origVal.replace(/(\d{3})(\d{3})(\d{4})/, '($1) $2-$3');
var phone = str.slice(0, -1) + str.slice(-1);
ctrl.$setViewValue(phone);
ctrl.$render();
unwatch();
}
});
}
};
}
]);

Angular - How to "bind" when "oninput" with "contenteditable span"?

"<span contenteditable>{{ line.col2 }}</span>"
Hello,
This code is good at initialisation but if I edit the span, no bing is send and my array model never updated...
So, I have tried this :
<span contenteditable ng-model="line.col2" ng-blur="line.col2=element.text()"></span>
But "this.innerHTML" does not exist.
What can I do ?
Thank at all ;-)
you can remove the ng-blur and you will have to add this directive:
<span contenteditable ng-model="myModel"></span>
Here is the directive taken from the documentation:
.directive('contenteditable', function() {
return {
restrict: 'A', // only activate on element attribute
require: '?ngModel', // get a hold of NgModelController
link: function(scope, element, attrs, ngModel) {
if(!ngModel) return; // do nothing if no ng-model
// Specify how UI should be updated
ngModel.$render = function() {
element.html(ngModel.$viewValue || '');
};
// Listen for change events to enable binding
element.on('blur keyup change', function() {
scope.$apply(read);
});
read(); // initialize
// Write data to the model
function read() {
var html = element.html();
// When we clear the content editable the browser leaves a <br> behind
// If strip-br attribute is provided then we strip this out
if( attrs.stripBr && html == '<br>' ) {
html = '';
}
ngModel.$setViewValue(html);
}
}
}
});
I only will point you to possible solution, then you need to parse/clean HTML better.
<span contenteditable data-ng-blur="bar = $event.target.innerHTML">
{{bar}}
</span>
// upd.
Angular events such as click, blur, focus, ... - fired with scope context, e.g. this will be current scope.
Use $event, be happy.
Solution with Mirrage and gab help :
<span contenteditable="true" ng-model="ligne.col2">{{ ligne.col2 }}</span>
app.directive('contenteditable', function() {
return {
require: 'ngModel',
link: function(scope, element, attrs, ctrl) {
// view -> model
element.bind('blur', function() {
scope.$apply(function() {
ctrl.$setViewValue(element.html());
});
});
// model -> view
ctrl.$render = function() {
element.html(ctrl.$viewValue);
};
// load init value from DOM
ctrl.$render();
}
};
});
Thank at all ;-)

Resources