angular: programmatically format a number using the $locale information - angularjs

I have included the corresponding locale file and it works fine. In any template I can do things like:
{{ value | number: 2}}
and it correctly formats the number according to the locale info.
Now I need to use the same locale info from javascript code in a controller to build a string.
I'm using a javascript component (a d3 graph to be precise) and I want to build strings to attache to it, so the template system is useless for this, but I'd like to take the locale configuration of numbers and dates from it.
So I'd nee something like this pseudocode:
var formattedValue = $local.format(value, { 'number': 2 });
Or something like that
Anyone knows how can I achieve that?

Try this :
var formattedValue = $filter('number')(value,2);
Working : http://plnkr.co/edit/aC4p95y52YZyoUEdQVzo?p=preview

We can achieve this by implementing a filter.
var app = angular.module('app', []);
app.filter('yourFilter', function(){
return function(string){
// build the string whatever you are trying to achieve
return newString; // return the string you achieved
}
});
for reference, http://blog.trifork.com/2014/04/10/internationalization-with-angularjs/

I could inject the filter like this:
presuApp.run(function ($rootScope, numberFilter) {
var formattedValue = numberFilter(value, 2);
[...]
It's just the name of the filter followed by th 'Filter' suffix.

Related

Filtering for Parameters

When using the $urlMatcherFactory provider to create new parameter types, is there a way to filter types while encoding/decoding or validating them? I need some "date" parameters, and it seems easiest to just create a custom type that can encode/decode them from the URL, as the built-in "date" type does not use the same date formats I want. I need to do this in a config block, as I need to do it before actually defining the states. This means I can only use providers (as far as I know, please correct me if I am wrong).
I found a way to use the date parser service from Angular Bootstrap for decoding the date, by injecting the uibDateParserProvider provider then retrieving the service with $get, but this does not seem like the best way to go. Also, it seems like the $filter provider does not work the same way, as $filterProvider.$get returns an array with an injection function or something like that as the 2nd element. This injection function is not the $filter service. I have not delved deeply enough into the angular source to be able to figure out what it actually is, but would be very interested to find out. I know I could parse the dates out myself, but why do that when there are so many helpful angular services to do it for me?
Here is an example of what I am trying to do (uses ES6):
angular.module('myModule').config(myStates);
function myStates($filterProvider, $urlMatcherFactoryProvider, $stateProvider, uibDateParserProvider) {
const decodeDateFormat = 'yyyy-MM-dd'; // the decoder date format
const encodeDateFormat = 'MMM dd, yyyy'; // the encoder format, which is different from the decoder format
$urlMatcherFactoryProvider.type('mydate', {
// encode when switching states, e.g. `$state.go()`
encode: item => {
const $filter = $filterProvider.$get(); // returns an array like: ['$filter', filterService] (not sure what the 2nd element is)
$filter('date')(item, decodeDateFormat); // this is what I ultimately want to do
},
// decode from the URL so we can use it as a date
// this uses a different format from the encoder date format
decode: item => {
const uibDateParser = uibDateParserProvider.$get(); // returns the uibDateParser service
return uibDateParser.parse(item, encodeDateFormat);
},
// validate
is: item => {
return item == null || angular.isDate(item); // just need to know if it is a date
},
});
$stateProvider.state('myState', {
url: 'my-path?{someParam:mydate}',
someParam: null,
});
}
Is there any way to use services when creating parameter types for the Angular UI Router? Otherwise, how do I get the $filter service from its provider, so I can do the filtering?
I'm able to use the $filter service by getting it from the $injectorProvider it self, e.g., $injectorProvider.$get().get('$filter');.
The following snippet is an example of usage in the config phase.
angular.module('myApp', [])
.config(function($injectorProvider) {
var $filter = $injectorProvider.$get().get('$filter');
console.log($filter('date')(new Date(), 'yyyy-MM-dd'));
});
angular.element(function() {
angular.bootstrap(document, ['myApp']);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.js"></script>

Call Angular $filter using expression string

I am trying to call $filter using a filter expression via a filter string I've stored as metadata. For instance my filter string might look like this:
var filterForMyValue = "number : 2 | someOtherFilter";
This would be no problem I was invoking a similar hardcoded filter via markup:
<span>{{ somevalue | number : 2 | someOtherFilter</span>
However I want to programmatically apply this filter. Doing something like this $filter(myFilterString)(valueToFilter) doesn't work since you can't include the filter parameters or multiple chained filters as a single string. It will only allow you to pass the filter name and then the parameters must be passed separately which I don't want since this is a generic method that needs to apply any filter string to a value. I thought $parse might be of some use but I was unable to find any examples of how it might be combined with $filter to achieve this.
This is in the lines of bluetoft comment, maybe one step closer using parser service instead of compile.
http://plnkr.co/edit/ZyFZ42XAuuE4tRZbxKqn?p=preview
$scope.item = 1.123;
//Option 1
var filterFn = $parse('item |number:2|myFilter');
console.log(filterFn($scope));
//Option 2
$scope.item = $filter('number')($scope.item, 2);
$scope.item = $filter('myFilter')($scope.item);
console.log($scope.item);
There are 2 options. Option1 uses parser and option may be you can create custom filter chain service (this is what internally the parser service would do but this is more in terms of your expected pattern of passing input/filters).
I'm not aware of a way to do EXACTLY what you're asking, but I think the $compile service may come of some help going about this in another manor.
var app = angular.module('myApp',[]);
app.filter('myFilter',function(){
return function(val){
return val * 2;
}
});
app.directive('myDirective',function($compile){
return {
restrict:'E',
link: function(scope,element){
scope.filterForMyValue = "number : 2 | myFilter";
scope.item = 1.123;
var format = '<span>{{item |' + scope.filterForMyValue + '}}</span>';
var compiled = $compile(format)(scope);
element.append(compiled);
}
}
});
Plunkr

BackboneJS - get specific value from Model using .max

So I have this:
var competitionModel = new Competition.CompetitionModel();
competitionModel.contest_id = this.contest_id;
this.insertView('.comp', new Competition.View({model: competitionModel}));
competitionModel.fetch();
So far so good, the Model and its (selected) values are getting display in the <div class="comp">.
Now I want to get a specific value from the same Model, in this case profile_image and it has to be the MAX value from the model. I read something about .max()-method but I dont know how to use it
I have this structure:
<div class="image"></div>
<div class="comp"></div>
1) is it possible? 2) can I use the same methods? like this.insertView('.image', blablab)
So, could anyone help me out?
Ok, judging by your comment the property is an array of things.
You cannot use the backbone max (which only applies to collections) but you can use the underscore max (they are the same thing, in the end, the former is a wrapper for the latter but let's not go into the details). You can see the collection .max() in action here.
You should be able to do something like this:
var max = _.max(competitionModel.get("property"));
Eventually you can pass a function to transform values:
var max = _.max(competitionModel.get("property"), function (element) {
// element is a single item in the list, return a number here.
});
Alternatively you can also use the underscore wrapper like this:
var max = _(competitionModel.get("property")).max(function (e) { ... });
More on max() can be found in the Underscore Docs.

Currency formatting Canadian French with custom filter

I am using a custom filter that utilizes angular's basic currency filter to display a monetary value based on a locale setting of en_CA or fr_CA. The display will either look like $123,456,789.99 or 123.456.789,99$ respectively. My question comes down to how do I make the angular currency filter handle formatting the value or must I do string replacements?
Filter code:
angular.module('plunker').filter('customCurrency',
[ '$filter', function(filter) {
var currencyFilter = filter('currency');
return function(languageCode,amount, currencySymbol) {
if(languageCode=='en_CA'){
currencySymbol='$';
}else if(languageCode=='fr_CA'){
currencySymbol='';
}
return currencyFilter(amount, currencySymbol);
}
} ]);
The plunker is located at http://plnkr.co/edit/7JJhd6.
Just went with the string replacement. The plunker from the original question contains the working example that I ended up using.

How to extend or override existing filters in angularjs?

Is it possible to extend existing "standard" filters (date, number, lowercase etc)?
In my case I need to parse date from YYYYMMDDhhmmss format so I'd like to extend (or override) date filter instead of writing my own.
I prefer to implement the decorator pattern, which is very easy in AngularJS.
If we take #pkozlowski.opensource example, we can change it to something like:
myApp.config(['$provide', function($provide) {
$provide.decorator('dateFilter', ['$delegate', function($delegate) {
var srcFilter = $delegate;
var extendsFilter = function() {
var res = srcFilter.apply(this, arguments);
return arguments[2] ? res + arguments[2] : res;
}
return extendsFilter;
}])
}])
And then in your views, you can use both.. the standard output and the extended behavior. with the same filter
<p>Standard output : {{ now | date:'yyyyMMddhhmmss' }}</p>
<p>External behavior : {{ now | date:'yyyyMMddhhmmss': ' My suffix' }}</p>
Here is a working fiddle illustrating both techniques:
http://jsfiddle.net/ar8m/9dg0hLho/
I'm not sure if I understand your question correctly, but if you would like to extend functionality of existing filters you could create a new filter that decorates an existing one. Example:
myApp.filter('customDate', function($filter) {
var standardDateFilterFn = $filter('date');
return function(dateToFormat) {
return 'prefix ' + standardDateFilterFn(dateToFormat, 'yyyyMMddhhmmss');
};
});
and then, in your template:
{{now | customDate}}
Having said the above, if you simply want to format a date according to a given format this can be done with the existing date filter:
{{now | date:'yyyyMMddhhmmss'}}
Here is the working jsFiddle illustrating both techniques: http://jsfiddle.net/pkozlowski_opensource/zVdJd/2/
Please note that if a format is not specified AngularJS will assume that this is 'medium' format (the exact format depends on a locale). Check http://docs.angularjs.org/api/ng.filter:date for more.
The last remark: I'm a bit confused about the 'parse from' part of your question. The thing is that filters are used to parse an object (date in this case) to string and not vice verse. If you are after parsing strings (from an input) representing dates you would have to look into NgModelController#$parsers (check the "Custom Validation" part in http://docs.angularjs.org/guide/forms).

Resources