I am using date picker in angular ..which is working fine .But I need when user type "t" or "T" it show current or today date ..And if user type "t-1" ..it show yesterday date ...Same when user type "t+1" it show tomorrow date .
here is my code
http://plnkr.co/edit/UnxLAHmKZU15cqukKqp5?p=preview
angular.module('app',['ui.bootstrap']).controller('cntrl',function($scope){
$scope.open2 = function() {
$scope.popup2.opened = true;
};
$scope.popup2 = {
opened: false
};
}).directive('toDateCheck', function() {
return {
require: 'ngModel',
link: function link(scope, element, attr, ngModel) {
scope.$watch(attr.ngModel, function(val) {
console.log(val)
})
}
}
})
What you're going to want to do is use a parser on your directive. The reason your $watch is not firing is because its not passing validation. Try something like this.
.directive('toDateCheck', function($browser) {
return {
require: 'ngModel',
link: function link(scope, element, attr, ngModelCtrl) {
scope.$watch(attr.ngModel, function(val,l) {
console.log(val,l);
});
ngModelCtrl.$parsers.unshift(function(viewValue){
if(viewValue === 't-1'){
var yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
// Update the textbox to show the new value
element.val(yesterday.toLocaleDateString());
return yesterday;
}
return viewValue;
});
}
}
})
Related
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);
});
}
};
Was wondering how I should handle async functions in $parsers.
The below code doesn't update the scope.
I'm using AngularJS 1.2 so can't make use of the new and fancy 1.3 features.
http://plnkr.co/edit/uk9VMipYNphzk8l7p9iZ?p=preview
Markup:
<input type="text" name="test" ng-model="test" parse>
Directive:
app.directive('parse', function($timeout) {
return {
require: 'ngModel',
link: function(scope, element, attrs, ctrl) {
ctrl.$parsers.unshift(function(viewValue) {
$timeout(function() {
return viewValue;
});
});
}
};
});
If you are looking for async validation function, I did something like that some time ago and release it as a library. Check the custom-remote-validator directive here.
The basic idea was use ngModelController $setValidity after receiving validation result from server. This is the directive source code
.directive('customRemoteValidator', [function () {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, elm, attr, ngModelCtrl) {
var validateFunctionNames = attr["remoteValidateFunctions"].split(",");
var validatorNames = attr["customRemoteValidator"].split(",");
ngModelCtrl.$parsers.push(function (value) {
angular.forEach(validateFunctionNames, function (functionName, index) {
if (!scope[functionName]) {
console.log('There is no function with ' + functionName + ' available on the scope. Please make sure the function exists on current scope or its parent.');
} else {
var result = scope[functionName](value);
if (result.then) {
result.then(function (data) { //For promise type result object
ngModelCtrl.$setValidity(validatorNames[index], data);
}, function (error) {
ngModelCtrl.$setValidity(validatorNames[index], false);
});
}
}
});
return value;
});
}
};
}])
I'm trying to create a timepicker directive in AngularJS that uses the jquery timepicker plugin. (I am unable to get any of the existing angular TimePickers to work in IE8).
So far, I was able to get the directive to work as far as updating the scope when a time is selected. However, what I need to accomplish now is getting the input to display the time, rather than the text of the model's value when the page first loads. See below:
this is what shows:
this is what I want:
Here is my directive:
'use strict';
playgroundApp.directive('timePicker', function () {
return {
restrict: 'A',
require: "?ngModel",
link: function(scope, element, attrs, controller) {
element.timepicker();
//controller.$setViewValue(element.timepicker('setTime', ngModel.$modelValue));
//ngModel.$render = function() {
// var date = ngModel.$modelValue ? new Date(ngModel.$modelValue) : null;
//};
//if (date) {
// controller.$setViewValue(element.timepicker('setTime', date));
//}
element.on('change', function() {
scope.$apply(function() {
controller.$setViewValue(element.timepicker('getTime', new Date()));
});
});
},
};
})
The commented code is what I've attempted, but it doesn't work. I get an error that reads, ngModel is undefined. So, to clarify, when the page first loads, if there is a model for that input field, I want the input to show only the time, as it does after a value is selected.
Thanks.
EDIT:
Ok, after making some trial and error changes, my link function looks like this:
link: function (scope, element, attrs, controller) {
if (!controller) {
return;
}
element.timepicker();
var val = controller.$modelValue;
var date = controller.$modelValue ? new Date(controller.$modelValue) : null;
controller.$setViewValue(element.timepicker('setTime', controller.$modelValue));
//ngModel.$render = function () {
// var date = ngModel.$modelValue ? new Date(ngModel.$modelValue) : null;
//};
if (date) {
controller.$setViewValue(element.timepicker('setTime', date));
}
element.on('change', function() {
scope.$apply(function() {
controller.$setViewValue(element.timepicker('getTime', new Date()));
});
});
},
This doesn't give me any errors, but the $modelValue is always NaN. Here is my controller code:
$scope.startTime = new Date();
$scope.endTime = new Date();
and the relevant html:
<input id="startTime" ng-model="startTime" time-picker/>
<input id="endTime" ng-model="endTime" time-picker />
Is there something else I need to do?
I spent several days trying with the same plugin without getting results and eventually I found another:
http://trentrichardson.com/examples/timepicker/
It works perfectly using the following directive:
app.directive('timepicker', function() {
return {
restrict: 'A',
require : 'ngModel',
link : function (scope, element, attrs, ngModelCtrl) {
$(function(){
element.timepicker({
onSelect:function (time) {
ngModelCtrl.$setViewValue(time);
scope.$apply();
}
});
});
}
}
});
I hope you find useful.
I have created a custom validator for requiring a date to be in the past. The validation seems to work great when entering the date manually into the field. However, if I enter change the date programmatically (change the model directly as opposed to typing in the field), the validation does not fire.
I believe I am doing the custom validation directive as directed in the documentation. Here is a jsFiddle illustrating the problem. In the fiddle, if you click the "Change date programatically" button, you can see the validation error doesn't get displayed (but it does if you change it manually). Here is the directive code (also in the fiddle):
myApp.directive('pastDate', function() {
return {
restrict: 'A',
require: '?ngModel',
link: function (scope, element, attrs, ctrl) {
ctrl.$parsers.unshift(function (viewValue) {
var today = new Date();
today = new Date(today.getFullYear(), today.getMonth(), today.getDate());
if (new Date(viewValue) < today) {
ctrl.$setValidity('pastDate', true);
return viewValue;
}
ctrl.$setValidity('pastDate', false);
return undefined;
});
}
};
});
There are two ways of the model binding, $parsers controls the pipeline of view-to-model direction, and $formatters controls the pipeline of the model-to-view direction. When you update the model in the controller, the change goes through the $formatters pipeline.
I have updated your code to: this, so it handles both ways.
myApp.directive('pastDate', function() {
return {
restrict: 'A',
require: '?ngModel',
link: function (scope, element, attrs, ctrl) {
function validate (value) {
var today = new Date();
today = new Date(today.getFullYear(), today.getMonth(), today.getDate());
if (new Date(value) < today) {
ctrl.$setValidity('pastDate', true);
return value;
}
ctrl.$setValidity('pastDate', false);
return value;
}
ctrl.$parsers.unshift(validate);
ctrl.$formatters.unshift(validate)
}
};
});
New answer since angular 1.3 provides $validators property.
Since 1.3, $parsers and $formatters are not supposed to set validity anymore, even if it still possible.
Then your code becomes simpler :
myApp.directive('pastDate', function() {
return {
restrict: 'A',
require: '?ngModel',
link: function (scope, element, attrs, ctrl) {
ctrl.$validators.pastDate = function(modelValue) { // 'pastDate' is the name of your custom validator ...
var today = new Date();
today = new Date(today.getFullYear(), today.getMonth(), today.getDate());
return (new Date(modelValue) < today);
}
}
};
});
Updated jsFiddle : http://jsfiddle.net/jD929/53/
I've defined a directive like so:
angular.module('MyModule', [])
.directive('datePicker', function($filter) {
return {
require: 'ngModel',
link: function(scope, elem, attrs, ctrl) {
ctrl.$formatters.unshift(function(modelValue) {
console.log('formatting',modelValue,scope,elem,attrs,ctrl);
return $filter('date')(modelValue, 'MM/dd/yyyy');
});
ctrl.$parsers.unshift(function(viewValue) {
console.log('parsing',viewValue);
var date = new Date(viewValue);
return isNaN(date) ? '' : date;
});
}
}
});
The parser seems to fire every time I type a key in my textbox though -- what exactly is the default event, is it keyup, or input? And how do I change it to only fire onchange? It really isn't necessary to fire anymore often than that.
Furthermore, I'm actually manipulating the content of this input using jQuery UI's datepicker. When clicking on the calendar it doesn't seem to trigger the appropriate event that causes the model to be updated/parser to be triggered. I think I can force an event to be fired but I need to know which one.
Trying to use scope.$apply() but that doesn't seem to help any:
.directive('datepicker', function($filter) {
return {
require: 'ngModel',
link: function(scope, elem, attrs, ctrl) {
$(elem).datepicker({
onSelect: function(dateText, inst) {
console.log(dateText, inst);
scope.$apply();
}
});
ctrl.$formatters.unshift(function(modelValue) {
console.log('formatting',modelValue);
return $filter('date')(modelValue, attrs.datePicker || 'MM/dd/yyyy');
});
ctrl.$parsers.unshift(function(viewValue) {
console.log('parsing',viewValue);
return new Date(viewValue);
});
}
}
})
I don't think the solution given here works for me because (a) I want to use the datepicker attribute value for choosing a date format or other options, but more importantly, (b) it seems to be passing back a string to the model when I want an actual date object... so some form of parsing has to be done and applied to the ng-model.
Here I created a mo-change-proxy directive, It works with ng-model and it updates proxy variable only on change.
In this demo I have even included improved directive for date-input. Have a look.
Demo: http://plnkr.co/edit/DBs4jX9alyCZXt3LaLnF?p=preview
angModule.directive('moChangeProxy', function ($parse) {
return {
require:'^ngModel',
restrict:'A',
link:function (scope, elm, attrs, ctrl) {
var proxyExp = attrs.moChangeProxy;
var modelExp = attrs.ngModel;
scope.$watch(proxyExp, function (nVal) {
if (nVal != ctrl.$modelValue)
$parse(modelExp).assign(scope, nVal);
});
elm.bind('blur', function () {
var proxyVal = scope.$eval(proxyExp);
if(ctrl.$modelValue != proxyVal) {
scope.$apply(function(){
$parse(proxyExp).assign(scope, ctrl.$modelValue);
});
}
});
}
};
});