I need to make an angular filter that will take full names, and initialise the first name, leaving only the last name, except in certain cases (e.g. Van Aanholt).
So the following:
Yohan Cabaye
Oscar
Jordi Alba Ramos
Patrick Van Aanholt
Hatem Ben Arfa
Will be shown as:
Y. Cabaye
Oscar
J. Ramos
P. Van Aanholt
H. Ben Arfa
Any help would be appreciated.
UPDATE: This is what I've tried...
angular.module('euroFilters', [])
.filter('initialiseName', function() {
return function(name) {
var nameArr = name.split(' ');
var firstName = nameArr[0];
var firstNameInitial = nameArr[0][0] + ". ";
var lastName = nameArr[nameArr.length - 1];
var secondaryLastName = nameArr[nameArr.length - 2];
// If only one name (standard)...
if (nameArr.length <= 1) {
return firstName;
}
// If more than one name, and contains "Van" or "Ben" (exception)...
else if (secondaryLastName === "Van" || secondaryLastName === "Ben") {
return firstNameInitial + " " + secondaryLastName + " " + lastName;
}
// If more than one name (standard)...
else if (nameArr.length > 1) {
return firstNameInitial + lastName;
}
};
});
Is there a more elegant way to write this? How would it convert into a switch statement, for example?
You can use split and join for that. String are array like objects, so you can use index on them.
angular.module('app', []);
angular.module('app').filter('initialiseFirstName', function () {
return function (name) {
var parts = name.split(/\s+/);
if (parts.length <= 1) {
return name;
}
var first = parts[0][0] + '.';
return first + ' ' + parts.slice(1).join(' ');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
{{'John Ket'|initialiseFirstName}}
</div>
This should do what you need:
<div ng-app="app">
{{'John Von Koten'|initialiseFirstName}}
</div>
<script>
angular.module('app', []);
angular.module('app').filter('initialiseFirstName', function () {
function checkName(name){
var prefixes = ['Van', 'Ben', 'Von'];
for(var i = 0; i < prefixes.length; i++){
if(name.indexOf(prefixes[i]) > 0){
return true;
}
}
return false;
}
return function (name) {
var parts = name.split(/\s+/);
if (parts.length <= 1) {
return name;
}
if(parts.length > 2){
if(checkName(name)){
return parts[0][0] + '. ' + parts[1] + ' '+ parts[2];
}
}
var first = parts[0][0] + '.';
return first + ' ' + parts.slice(1).join(' ');
}
});
</script>
Related
Here are date and time.
Date 2018-05-25T10:35:04.000Z
Expected Output = 3 days 12 hours
I want to display date and time same like as a give above. Currently, I am using moment.js. Is there any way to display like above?
Alternatively to Zvi's suggestion, you could use the AngularJS date filter
Say in your controller you have 2 dates:
app.controller('AppCtrl', function($scope) {
ctrl = this;
ctrl.date1 = new Date("2018-05-22T22:35:04.000Z");
ctrl.date2 = new Date("2018-05-25T10:35:04.000Z");
});
And in HTML, you'd display the difference with the date filter:
{{ctrl.date2 - ctrl.date1 | date:"dd 'days' HH 'hours'"}}
Here's a working JSFiddle example
You can use this moment-precise-range.
Here's full example:
calcDiff = (date : string) => {
let diff_in_string = '';
let original_date = moment(date);
let date_time_now = moment();
let diff_in_object: any = moment-presice.preciseDiffBetweenDates(original_date, date_time_now, true);
if (diff_in_object.days > 0) {
diff_in_string = diff_in_string + diff_in_object.days + ' ';
if (diff_in_object.days === 1) {
diff_in_string += 'Day '
} else {
diff_in_string += 'Days '
}
}
if (diff_in_object.hours > 0) {
if (diff_in_object.days > 0) {
diff_in_string += 'and ' + diff_in_object.hours + ' '
} else {
diff_in_string += diff_in_object.hours + ' '
}
if (diff_in_object.hours === 1) {
diff_in_string += 'Hour '
} else {
diff_in_string += 'Hours '
}
}
diff_in_string += 'ago'
return diff_in_string;
}
You should consider using The HumanizeDuration library (you can check this answer).
It allows you to translate in any language you want the difference between two dates the way you want.
For example :
var yourdate= moment().set({'year': 2018, 'month': 5, 'day': 22});
var today = moment();
var duration = moment.duration(today.diff(yourdate));
var humanized = humanizeDuration(duration, { units: ['d', 'h'], language: language, round: true });
You can also format it with spacers, etc.
I'm learning angularjs and got an exercise that wants me to Use angular filter to show a title in the following format :
first letter of each word upper cased and each other letter lower cased also
remove any non-English letters from the title. For example:
A title with the name
“##THIS is a Title!!”
should be changed to
“This Is A Title”
I'm getting each title from an array of objects and present them like so.
<div ng-repeat="obj in objects">
<h3 class="panel-title">{{obj.Title}}</h3>
</div>
i understand that filter receives an array and filters through it . but this requires me to filter the string.
been searching for a while, how can i do this?
please refer below fiddle
http://jsfiddle.net/HB7LU/28315/
<div ng-controller="MyCtrl">
Hello, {{ name | ordinal|capitalize }}
</div>
var myApp = angular.module('myApp',[]);
//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});
function MyCtrl($scope) {
$scope.name = 'Super hero!!12##3';
}
myApp.filter('ordinal', function() {
// Create the return function
// set the required parameter name to **number**
return function(strTitle) {
// Ensure that the passed in data is a number
// If the data is not a number or is less than one (thus not having a cardinal value) return it unmodified.
strTitle=strTitle.replace(/[^a-zA-Z ]/g, "")
return strTitle;
}
});
myApp.filter('capitalize', function() {
return function(input){
if(input.indexOf(' ') !== -1){
var inputPieces,
i;
input = input.toLowerCase();
inputPieces = input.split(' ');
for(i = 0; i < inputPieces.length; i++){
inputPieces[i] = capitalizeString(inputPieces[i]);
}
return inputPieces.toString().replace(/,/g, ' ');
}
else {
input = input.toLowerCase();
return capitalizeString(input);
}
function capitalizeString(inputString){
return inputString.substring(0,1).toUpperCase() + inputString.substring(1);
}
};
});
angular.module('app', []).filter('myFilter', function(){
return function(input){
if(!input)
return;
var out = '';
var english = /^[A-Za-z0-9 ]*$/;
for(var letter of input)
if(english.test(letter))
out += letter;
var result = '';
for(var i = 0; i < out.length; i++)
result += out[i][(i === 0 || out[i-1] == ' ') ? 'toUpperCase' : 'toLowerCase']();
return result;
}
})
<script src="//code.angularjs.org/snapshot/angular.min.js"></script>
<body ng-app="app">
<input ng-init='text="##THIS is a Title!!"' type='text' ng-model='text'>
<p>{{text | myFilter}}</p>
</body>
The view:
<div class="numbers">
{{calc.amount || 0 }}
</div>
<div class="keypad">
<div class="number-slot"><button ng-click="numberPressed(1)" class="number">1</button></div>
</div>
The controller:
app.controller('pay-amount', function ($scope, $state, $cordovaBarcodeScanner, ionicMaterialInk) {
$scope.numberPressed = function (number) {
console.log(number + " pressed!");
$scope.calc = {
amount: "" + $scope.calc.amount + number
}
};
ionicMaterialInk.displayEffect();
});
There are no errors till numberPressed(1) is called:
"ionic.bundle.js:26794 TypeError: Cannot read property 'amount' of
undefined".
Upon inspecting $scope, I can't find the "calc" object I defined in the view. What am I missing here?
You need to declare the $scope variable before using it,
$scope.calc = {amount:0};
DEMO
Try this,
$scope.numberPressed = function (number) {
console.log(number + " pressed!");
$scope.calc = {amount:''};
$scope.calc = {
amount: "" + $scope.calc.amount + number
}
console.log($scope.calc);
};
Your calc was never set on the $scope so it tries to find amount on undefined
You could make 2 simple changes
$scope.calc = {};
$scope.numberPressed = function (number) {
console.log(number + " pressed!");
$scope.calc.amount = ($scope.calc.amount || 0) + number
}
or
$scope.calc = { amount: 0 };
$scope.numberPressed = function (number) {
console.log(number + " pressed!");
$scope.calc.amount = $scope.calc.amount + number
}
Try this,
$scope.calc = { amount: 0 };
$scope.numberPressed = function (number) {
console.log(number + " pressed!");
$scope.calc.amount = $scope.calc.amount + number
}
I'm trying to mask the first 5 digits of SSN using a filter which should look something like this
XXX-XX-1234
What I came up with so far:
// <td>{{SocialSecurityNumber | ssn}}
angular.module('ng').filter('ssn', function () {
return function (ssn) {
if (!ssn) {
return '';
}
var value = ssn.toString().trim().replace(/^\+/, '');
if (value.match(/[^0-9]/)) {
return ssn;
}
return (ssn.slice(0, 3).replaceWith('*') + '-' + ssn.slice(4, 5).replaceWith('*') + '-' + ssn.slice(4)).trim();
};
});
Strings have no .replaceWith function in JavaScript. You can use .replace, though.
I'm not sure what value.match(/[0-9]/) is supposed to do either. It seems like you can just remove it. This will return true if the value has even one digit, which it should anyway. Perhaps you mean /[^0-9]/
return "XXX-XX-" + ssn.slice(5);
You can mask the input box without changing your model value then, this code must help. Here is the working code Plunkr / Github
var app = angular.module('myapp', []);
app.controller('MainCtrl', function($scope) {
$scope.modelssn = '';
});
app.directive("ssnInput",function(){
return {
require:'ngModel',
link: function(scop, elem, attr, ngModel){
$(elem).mask("999-99-9999");
var temp;
var regxa = /^(\d{3}-?\d{2}-?\d{4})$/;
$(elem).focusin(function(){
$(elem).val(temp);
});
$(elem).on('blur',function(){
temp = $(elem).val();
if(regxa.test($(elem).val())){
$(elem).val("XXX-XX" + temp.slice(6));
}
});
}
}
});
<!DOCTYPE html>
<html ng-app="myapp">
<head>
<script src="https://code.jquery.com/jquery.js"></script>
<script src="https://cdn.rawgit.com/digitalBush/jquery.maskedinput/master/src/jquery.maskedinput.js"></script>
<script data-require="angular.js#1.5.x" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.11/angular.min.js" data-semver="1.5.11"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
Enter SSN <input type="text" ng-model="modelssn" ssn-input >
<p>Real SSN {{modelssn}} </p>
</body>
</html>
## I faced the similer issue. Below is the solution for that :
angular
.module('app')
.directive('ssnOnly', function () {
return {
require: 'ngModel',
link: function (scope, element, attr, ngModelCtrl) {
var flag = 0;
function fromUser(text) {
if (text) {
var transformedInput = text.replace(/[^0-9 -]/g, '');
if (text.length < 3) {
flag = 0;
} else if (text.length > 3 && text.length < 6) {
flag = 1;
}
if (transformedInput !== text) {
ngModelCtrl.$setViewValue(transformedInput);
ngModelCtrl.$render();
alert("Only Numbers Allowed !!!");
} else {
if (transformedInput.length == 3 && flag == 0) {
transformedInput = transformedInput + '-';
flag = 1;
} else if (transformedInput.length == 6 && flag == 1) {
transformedInput = transformedInput + '-';
flag = 2;
}
if (transformedInput.length == 4 || transformedInput.length == 7)
{
var id = transformedInput;
var last = id.substr(id.length - 1);
if (last != '-') {
transformedInput = transformedInput.substring(0, transformedInput.length - 1);
transformedInput = transformedInput + '-' + last;
}
}
ngModelCtrl.$setViewValue(transformedInput);
ngModelCtrl.$render();
}
return transformedInput;
}
return undefined;
}
ngModelCtrl.$parsers.push(fromUser);
}
};
})
<input type="text" class="form-control" ssn-only ng-model="ssnNumber" placeholder="SSN" maxlength="11">
I've got a javascript function that we use in a legacy system that alters the format of an input field as you type;
function checkValidDate(dateStr) {
if (dateStr && dateStr != '') {
dateStr = dateStr.replace('/', '');
dateStr = dateStr.replace('/', '');
var d_f_m = dateStr;
var d_f_d = dateStr;
var d_f_y = dateStr;
var err_msg = '';
var d_s_day = d_f_d.slice(0, 2);
d_s_day = d_s_day + "/";
var d_s_month = d_f_m.slice(2, 4);
d_s_month = d_s_month + "/";
var d_s_year = d_f_y.slice(4, 8);
//Now we check the year to see if it is only 2 digis, if is, add 2 more
if (d_s_year.length == 2) {
d_s_year = '19' + d_s_year;
}
return d_s_day + d_s_month + d_s_year;
} else {
return null;
}
}
I've been trying to convert this function to an angularjs directive using ngModel but I just can't seem to sort it out. Would anyone know how to convert this to an angular directive?
Many thanks!
Not sure if you wanted it validated as you type or after you leave a field. Either can work, though the below is implemented to validate after you leave the field (lose focus).
The existing algorithm was used, though it looks like it handles only very specific cases (i.e. 2 digit day, 2 digit month, 2-4 digit year) and could be improved. For the moment, it was copied as is. JSFiddle is here http://jsfiddle.net/pSh4R/18/
HTML:
<div ng-app='app'>
Please enter a date
<br/>
<input type='text' dateformat ng-model='myDate'></input>
(Hit TAB when done)
<hr/>
Model Value : {{myDate}}
</div>
Directive Declaration:
var app = angular.module('app',[]);
app.directive('dateformat', function(){
return {
restrict : 'A',
scope : {
dateStr : '=ngModel'
},
link : function(scope, element){
element.bind('focusout', function (){
scope.$apply(function(){
scope.dateStr = checkValidDate(scope.dateStr);
});
});
function checkValidDate(dateStr) {
if (dateStr && dateStr != '') {
dateStr = dateStr.replace('/', '');
dateStr = dateStr.replace('/', '');
var d_f_m = dateStr;
var d_f_d = dateStr;
var d_f_y = dateStr;
var err_msg = '';
var d_s_day = d_f_d.slice(0, 2);
d_s_day = d_s_day + "/";
var d_s_month = d_f_m.slice(2, 4);
d_s_month = d_s_month + "/";
var d_s_year = d_f_y.slice(4, 8);
//Now we check the year to see if it is only 2 digis, if is, add 2 more
if (d_s_year.length == 2) {
d_s_year = '19' + d_s_year;
}
return d_s_day + d_s_month + d_s_year;
} else {
return null;
}
}
}
};
})
There are a billion ways to do what you want. Here is a quick solution I threw together to get your started:
JS:
var app = angular.module('myApp', []);
app.directive('dateValidator', function() {
return function(scope, element, attrs) {
// Watch for changes to the date model
scope.$watch('date', function(newVal, oldVal) {
if (!angular.equals(newVal, oldVal)) {
var formattedDate = checkValidDate(newVal);
if (formattedDate) {
element.text(formattedDate);
}
}
});
});
});
HTML:
<input type="text" date-validator date="myDate" ng-model="myDate" />
I recommend that you write a custom angular validator. There are some good articles on it. Here is one that I like:
Form Validation with AngularJS
The form and its containing fields have special properties appended to them that you can leverage for binding expressions and client-side validation:
$pristine, $dirty, $valid, $error