I got a wired error
I have directive date picker
I have watch listener while the date change
$scope.$watch('model', function (newDate) {
if (newDate) {
if ($scope.hideDay) {
$scope.dateFields.day = 1;
} else {
$scope.dateFields.day = new Date(newDate).getUTCDate();
}
$scope.dateFields.month = new Date(newDate).getUTCMonth() +1;
$scope.dateFields.year = new Date(newDate).getUTCFullYear();
} else {
if ($scope.hideDay) {
$scope.dateFields.day = 1;
} else {
$scope.dateFields.day = null;
}
$scope.dateFields.month = null;
$scope.dateFields.year = null;
}
});
My weird problem is that I have a search box
<input class="free-txt" ng-model="search.name" placeholder="Free search" />
When I typed in the search box The watch model changed with no reason.
What can be the reason for this bug and how can I fixed it?
Here is the full demo
https://embed.plnkr.co/yGqE33kZNwGz7NaNDOD5/
Select day
Select Month
Open the Year modal than Write in the free text "78"
Select The year
The bug when Typing in the free text the day and month change to null
by default angular $watch watch object by reference
https://docs.angularjs.org/api/ng/type/$rootScope.Scope
objectEquality:
Compare for object equality using angular.equals instead of comparing for reference equality.
(default: false)
try to add a parametre to true for watching object or use watchcollection and give it the variables you need
$scope.$watch('model', function (newDate) {
...
},true );
the directive update the model only when the date is valid :
$scope.checkDate = function () {
$timeout(function () {
var date = rsmDateUtils.checkDate($scope.dateFields);
if (date) {
// the watch is called what date is valid with a year
if ($scope.hideDay) {
$scope.model = $filter('date')(date, 'yyyy-MM');
} else {
$scope.model = $filter('date')(date, 'yyyy-MM-dd');
}
}
});
};
I simply want to convert a string of numbers to a number which will be displayed using thousand separated commas.
var value = "123456";
I want to display "123,465" in a grid.
I have looked some documentation on this but everything is about displaying it in HTML.
I want to display this in a dynamic grid.
function numberRenderer (params) {
return new Number (params.value);
}
I want to format the number so that I can convert that into a string for display.
Use a filter ...
HTML usage
{{ number_expression | number : fractionSize}}
Js usage
$filter('number')(number, fractionSize)
I appreciated the answer from #jbrown, but I was also hoping to find some type of solution to add commas to an input field as the user enters numbers. I ended up finding this directive which proved to be exactly what I needed.
HTML
<input type="text" ng-model="someNumber" number-input />
JAVASCRIPT
myApp.directive('numberInput', function($filter) {
return {
require: 'ngModel',
link: function(scope, elem, attrs, ngModelCtrl) {
ngModelCtrl.$formatters.push(function(modelValue) {
return setDisplayNumber(modelValue, true);
});
// it's best to change the displayed text using elem.val() rather than
// ngModelCtrl.$setViewValue because the latter will re-trigger the parser
// and not necessarily in the correct order with the changed value last.
// see http://radify.io/blog/understanding-ngmodelcontroller-by-example-part-1/
// for an explanation of how ngModelCtrl works.
ngModelCtrl.$parsers.push(function(viewValue) {
setDisplayNumber(viewValue);
return setModelNumber(viewValue);
});
// occasionally the parser chain doesn't run (when the user repeatedly
// types the same non-numeric character)
// for these cases, clean up again half a second later using "keyup"
// (the parser runs much sooner than keyup, so it's better UX to also do it within parser
// to give the feeling that the comma is added as they type)
elem.bind('keyup focus', function() {
setDisplayNumber(elem.val());
});
function setDisplayNumber(val, formatter) {
var valStr, displayValue;
if (typeof val === 'undefined') {
return 0;
}
valStr = val.toString();
displayValue = valStr.replace(/,/g, '').replace(/[A-Za-z]/g, '');
displayValue = parseFloat(displayValue);
displayValue = (!isNaN(displayValue)) ? displayValue.toString() : '';
// handle leading character -/0
if (valStr.length === 1 && valStr[0] === '-') {
displayValue = valStr[0];
} else if (valStr.length === 1 && valStr[0] === '0') {
displayValue = '';
} else {
displayValue = $filter('number')(displayValue);
}
// handle decimal
if (!attrs.integer) {
if (displayValue.indexOf('.') === -1) {
if (valStr.slice(-1) === '.') {
displayValue += '.';
} else if (valStr.slice(-2) === '.0') {
displayValue += '.0';
} else if (valStr.slice(-3) === '.00') {
displayValue += '.00';
}
} // handle last character 0 after decimal and another number
else {
if (valStr.slice(-1) === '0') {
displayValue += '0';
}
}
}
if (attrs.positive && displayValue[0] === '-') {
displayValue = displayValue.substring(1);
}
if (typeof formatter !== 'undefined') {
return (displayValue === '') ? 0 : displayValue;
} else {
elem.val((displayValue === '0') ? '' : displayValue);
}
}
function setModelNumber(val) {
var modelNum = val.toString().replace(/,/g, '').replace(/[A-Za-z]/g, '');
modelNum = parseFloat(modelNum);
modelNum = (!isNaN(modelNum)) ? modelNum : 0;
if (modelNum.toString().indexOf('.') !== -1) {
modelNum = Math.round((modelNum + 0.00001) * 100) / 100;
}
if (attrs.positive) {
modelNum = Math.abs(modelNum);
}
return modelNum;
}
}
};
});
AngularJS Directive was found from: AngularJS number input formatted view
https://jsfiddle.net/benlk/4dto9738/
Very appreciative of what Anguna posted. The only thing it was missing for me was handling the decimal places like currency. I wanted it to automatically add 2 decimal places to the displayed value. However, this should only occur on initial display and then again when leaving a field. I updated the code to handle that scenario.
var app = angular.module("myApp", []);
app.directive('currencyInput', function ($filter) {
return {
require: 'ngModel',
link: function (scope, elem, attrs, ngModelCtrl) {
ngModelCtrl.$formatters.push(function (modelValue) {
var displayValue = setDisplayNumber(modelValue, true);
displayValue = setDecimal(displayValue);
return displayValue;
});
// it's best to change the displayed text using elem.val() rather than
// ngModelCtrl.$setViewValue because the latter will re-trigger the parser
// and not necessarily in the correct order with the changed value last.
// see http://radify.io/blog/understanding-ngmodelcontroller-by-example-part-1/
// for an explanation of how ngModelCtrl works.
ngModelCtrl.$parsers.push(function (viewValue) {
setDisplayNumber(viewValue);
return setModelNumber(viewValue);
});
// occasionally the parser chain doesn't run (when the user repeatedly
// types the same non-numeric character)
// for these cases, clean up again half a second later using "keyup"
// (the parser runs much sooner than keyup, so it's better UX to also do it within parser
// to give the feeling that the comma is added as they type)
elem.bind('keyup focus', function () {
setDisplayNumber(elem.val());
});
elem.bind('blur', function () {
// Add Decimal places if they do not exist
var valStr = elem.val().toString();
valStr = setDecimal(valStr);
elem.val(valStr);
});
function setDisplayNumber(val, formatter) {
var valStr, displayValue;
if (typeof val === 'undefined') {
return 0;
}
valStr = val.toString();
displayValue = valStr.replace(/,/g, '').replace(/[A-Za-z]/g, '');
displayValue = parseFloat(displayValue);
displayValue = (!isNaN(displayValue)) ? displayValue.toString() : '';
// handle leading character -/0
if (valStr.length === 1 && valStr[0] === '-') {
displayValue = valStr[0];
} else if (valStr.length === 1 && valStr[0] === '0') {
displayValue = '';
} else {
displayValue = $filter('number')(displayValue);
}
// handle decimal
if (!attrs.integer) {
if (displayValue.indexOf('.') === -1) {
if (valStr.slice(-1) === '.') {
displayValue += '.';
} else if (valStr.slice(-2) === '.0') {
displayValue += '.0';
} else if (valStr.slice(-3) === '.00') {
displayValue += '.00';
}
} // handle last character 0 after decimal and another number
else {
if (valStr.slice(-1) === '0') {
displayValue += '0';
}
}
}
if (attrs.positive && displayValue[0] === '-') {
displayValue = displayValue.substring(1);
}
if (typeof formatter !== 'undefined') {
return (displayValue === '') ? 0 : displayValue;
} else {
elem.val((displayValue === '0') ? '' : displayValue);
}
}
function setModelNumber(val) {
var modelNum = val.toString().replace(/,/g, '').replace(/[A-Za-z]/g, '');
modelNum = parseFloat(modelNum);
modelNum = (!isNaN(modelNum)) ? modelNum : 0;
if (modelNum.toString().indexOf('.') !== -1) {
modelNum = Math.round((modelNum + 0.00001) * 100) / 100;
}
if (attrs.positive) {
modelNum = Math.abs(modelNum);
}
return modelNum;
}
function setDecimal(val) {
// Add Decimal places if they do not exist
var valStr = val.toString();
// If no decimal then add it
if (valStr.indexOf('.') === -1) {
valStr += '.00';
}
else {
var decimalDigits = valStr.length - (valStr.indexOf('.') + 1);
var missingZeros = 2 - decimalDigits;
for (var i = 1; i <= missingZeros; i++) {
valStr += '0';
}
}
return valStr;
}
}
};
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.11/angular.min.js"></script>
<div ng-app="myApp">
<input type="text" ng-model="myModelValue" currency-input />
</div>
I'm trying to build an event date filter by passing in a time range. I was able to filter for events that are the same date as today but need help to filter events from last week, last month, etc...
$scope.eventDateFilter = function(column) {
if(column === 'today') {
$scope.dateRange = $scope.dateToday;
} else if (column === 'pastWeek') {
//need logic
} else if (column === 'pastMonth') {
//need logic
} else if (column === 'future') {
//need logic
} else {
$scope.dateRange = "";
}
}
Here's my fiddle:
http://jsfiddle.net/c6BfQ/3/
Your help is greatly appreciated.
I would use a custom filter. Here is one I used to filter things created in the last two days, it should give you an idea of how to do yours.
.filter('dateFilter', function() {
return function (objects) {
var filtered_list = [];
for (var i = 0; i < objects.length; i++) {
var two_days_ago = new Date().getTime() - 2*24*60*60*1000;
var last_modified = new Date(objects[i].date_created).getTime();
if (two_days_ago <= last_modified) {
filtered_list.push(objects[i]);
}
}
return filtered_list;
}
});
I have a massive validate function in my backbone model that could be simplified if only I could detect the attribute I'm testing against. There are a few ideas of how I can think to approach this problem, but they all rely on knowing the attribute name I'm testing, without hardcoding it as I am in the id variable below.
Here is an example:
validate : function(attr){
var t = this;
if(attr.user1DobMonth && attr.user1DobMonth != t.get('user1DobMonth')){
var val = jQuery.trim(attr.user1DobMonth.toLowerCase()),
id = 'user1DobMonth',
error = {
attr : id
};
if(val === 'select'){
return error;
}
}
if(attr.user2DobMonth && attr.user2DobMonth != t.get('user2DobMonth')){
var val = jQuery.trim(attr.user2DobMonth.toLowerCase()),
id = 'user2DobMonth',
error = {
attr : id
};
if(val === 'select'){
return error;
}
}
}
The date field doesn't get validated for a format like 2013-02-13, but it works for 2013-12-12. Leading zero seems to be creating problem in any node form. I have "clientside validation" module on. I couldn't find anything related to this bug/issue anywhere, so I am posting here.
Can anyone help me?
There is issue in clientside validation js due to using of parseInt for validating a month & day value of a date. just replace with it
jQuery.validator.addMethod("dateFormat", function(value, element, param) {
var parts = value.split(param.splitter);
var expectedpartscount = 0;
var day = parseInt(parts[param.daypos], 10);
var month = parseInt(parts[param.monthpos], 10);
month = month - 1;
var year = parseInt(parts[param.yearpos], 10);
var date = new Date();
var result = true;
/* if (day.toString().length !== parts[param.daypos].length){
result = false;
}
if (month.toString().length !== parts[param.monthpos].length){
result = false;
}*/
if (year.toString().length !== parts[param.yearpos].length){
result = false;
}
if (param.yearpos !== false){
expectedpartscount++;
date.setFullYear(year);
if (year !== date.getFullYear()) {
result = false;
}
}
if (param.monthpos !== false) {
expectedpartscount++;
date.setMonth(month);
if (month !== date.getMonth()) {
result = false;
}
}
if (param.daypos !== false) {
expectedpartscount++;
date.setDate(day);
if (day !== date.getDate()) {
result = false;
}
}
if (expectedpartscount !== parts.length) {
result = false;
}
return this.optional(element) || result;
}, jQuery.format('The date is not in a valid format'));