I'd like to modify the currency filter to handle custom money formats in the input value.
(eg., AUD 3.00 -> $3.00).
One option is to write my own filter from scratch. However this seems like a lot of duplication, given the existing filter is great, I just need to trim a few characters off the front first.
Ideally, I'd have something like this:
.filter('money', function($filters) {
return function(text){
var currency = text.substring(4)
return $filters('currency')(currency)
};
});
Is is possible to either:
Call one filter from another?
Access the internal methods (eg, formatNumber() shown here
What other options are open to me for this?
Call one filter from another?
Yes and the best solution I found was to create a new filter:
angular.module('ui.filters').filter('customCurrency',
[ '$filter', function(filter) {
var currencyFilter = filter('currency');
return function(amount, currencySymbol) {
return currencyFilter(amount.substr(4), currencySymbol);
}
} ]);
This transforms values like "AUD 30.00" to "$30.00"
You cannot, from what I tried, as of version 1.0.1 override a filter. I tried to create a filter using the same name and trying to reference the original filter causes an infinite loop.
Here is an excellent point to consider:
However, I would suggest not doing so - even if that is allowed.
Predefined filters are the public API of AngularJS. What if some parts
of AngularJS use some of them internally or one day you install some
add-on which depends on that filter?
See also, basically the same conclusion even though I believe op didn't really need a custom filter.
Access the internal methods (eg, formatNumber())?
If the function is not exposed then the authors deemed it wasn't a public api they wanted to make available. The authors might have a particular implemetation specific function that might not be obvious right away.
PS: The module is whatever you need the filter to be in. I separate some functionality in different modules and require them when I build my main module
var App = angular.module('App', [ 'ui' ]);
The best way to do this is,
<div> {{amount | currency:'$'}} </div>
in your html.
This will automatically rip off the first few characters that correspond to the currency type and replace them with the string argument '$' you pass.
Angular's currency filter allows you to use the default currency symbol from the locale service, or you can provide the filter with a custom currency symbol. If your app will be used only in one locale, it is fine to rely on the default currency symbol. However, if you anticipate that viewers in other locales might use your app, you should provide your own currency symbol to make sure the actual value is understood.
For example, if you want to display account balance of 1000 dollars with the following binding containing currency filter: {{ 1000 | currency }}, and your app is currently in en-US locale. '$1000.00' will be shown. However, if someone in a different local (say, Japan) views your app, her browser will specify the locale as ja, and the balance of '¥1000.00' will be shown instead. This will really upset your client.
In this case, you need to override the default currency symbol by providing the currency filter with a currency symbol as a parameter when you configure the filter, for example, USD$1,000.00. This way, Angular will always show a balance of 'USD$1000' and disregard any locale changes.
See the notes on localization: http://docs.angularjs.org/guide/i18n
Related
I would like to make a react floating date filter that works exactly like the default filter. The default filter has equals, greater than, less than, not equal and in range. I would like to preserve the behavior of these filters. The only things that I would like to change is the input format. The input format of the date is for the default is mm/dd/yy and I would like to change is that I can input a date like this 09 Mar 2019. Is there an easy way to change the date format? If not will I have to create a custom filter? And if I do have a make a custom one, where can I find the implementation of the default one as reference.
what I would like to modify
you can't (currently) do it with the current datefilter because it internally uses <input type="date" /> (if using chrome, otherwise just a text field) which always takes the browsers locale as described in https://stackoverflow.com/a/9519493/885338
also described in https://github.com/ag-grid/ag-grid/issues/1029 (has also a vue.js example)
so you will either have to
follow the steps outline here https://github.com/ag-grid/ag-grid/issues/2233
which modifies the prototype of the DateFilter and is a rather hacky solution
because it will overwrite every DateFilter and modifies (via prototype) ag-grid code. It worked for our cases, but might not in yours.
create a custom filter
and use the default filter https://github.com/ag-grid/ag-grid/blob/master/packages/ag-grid-community/src/ts/filter/dateFilter.ts as a reference.
if you create a custom filter you could supply additional params like the desired date format via FilterParams
The method init(params) takes a params object with the items listed below. If the user provides params via the colDef.filterParams attribute, these will be additionally added to the params object, overriding items of the same name if a name clash exists.
taken from: https://www.ag-grid.com/javascript-grid-filter-component/#ifilter-params
with that you could write a date filter that can work with different date formats (for example with using moment.js) by supplying the format via colDef.filterParams
Ag-Grid has some nice examples for Dates -> https://www.ag-grid.com/javascript-grid-date-component/
also see https://github.com/ag-grid/ag-grid/issues/1029#issuecomment-393546876 for this exact, still unresolved, issue and an example for vue.js which you may use as a starting point for your react based filter
I've been looking at using Angular Schema Form to define all my forms for my project but one thing that stood out to me massively is that when we define a select/drop-down element, the values have to be specified then and there in the JSON. This doesn't strike me as very flexible as I want these values to be retrieved from my Angular controller/factory as they are currently available on the scope.
I've done quite a bit of searching on how to get round this but haven't found a definitive solution or anything that worked for me so I decided to try to extend the Select myself and add a mapping to the schemaFormDecoratorsProvider.
I have followed the documentation for Extending Schema Form, and now have an HTML snippet which defines my Select control and this is being rendered when I define it in my JSON schema. What I want to be able to do is to specify the ng-options attribute either in part as a whole via the JSON schema. I have tried to do this but nothing seems to result in the select options being rendered.
Here is part of my select control:
<select ng-model="$$value$$"
ng-model-options="form.ngModelOptions"
sf-changed="form"
schema-validate="form"
ng-options="item.value as item.name for item in form.titleMap"
ng-disabled="form.readonly">
</select>
Where ng-options is defined, I want to be able to either specify titleMap in my JSON and it be resolved to an object on my scope or I can pass the name of the collection in my JSON and then pass that in where form.titleMap currently sits.
Anybody had any experience doing this? To me is seems like a fairly reasonable requirement but can't find much help on the web about it.
Many thanks.
There are add-ons designed to support dynamic data selection, the library has no preference and leaves it up to the developer to select the most appropriate for their needs, however I built the Material Design decorator to include the capabilities of angular-schema-form-external-options in the decorator so the add-on is not needed. The bootstrap decorator does not have this capability at this stage.
The angular-schema-form-external-options library is basic but covers most requirements for simple dynamic drop down data population
The angular-schema-form-dynamic-select is a more robust and feature full option with a variety of configurable options.
I am using the "taxonomy display" module. I use to so that I can sort my taxonomy terms by title, instead of by ID, as it does by default. However, I also created a taxonomy template called:
taxonomy-term--product_literature_category.tpl.php
If I enable the "taxonomy display" module and override the taxonomy view for this path:
/taxonomy/term/%
... it also overrides the template I specified above. It would make more sense that the order would be to take my custom template override the module. But it doesn't seem to work that way. But if I disable "taxonomy display", it again takes my template into account.
I have two choices:
Enable "taxonomy display" and find a way to override taxonomy-term--product_literature_category.tpl.php
Disable "taxonomy display" and find a way to sort taxonomy terms by my own custom sorting parameters.
I would imagine 1 being difficult (because it doesn't make much sense to use two templates for the same thing). That is why I'm leaning towards an easier way to sort taxonomy views by default, or some other way to specify the ordering of taxonomy terms.
Does anyone know how to do this?
UPDATE
Right now I am going to settle with figuring out a hook to change the sorting of taxonomy terms via a module. That way I can override the sorting for only specific vocabularies. Any pointers to nudge me in that direction would be highly appreciated?
UPDATE 2
I've created teaser_sorter.module and added this function:
function teaser_sorter_views_query_alter(&$view, &$query)
{
print '<pre>'; print_r($view); print_r($query); die();
}
I also made sure my module supports views:
function teaser_sorter_views_api() {
return array(
'api' => 3,
);
}
I can't get it to ever reach my "die". In other words, it's never called. In fact, I also tried overriding "hook_views_pre_execute", but that doesn't ever get called either.
Any ideas?
view : <google-taxonomy-category class="googlecategoryselectiontool" field-name="goo_cat_id" cat-sel=""></google-taxonomy-category>
"class" used for template setup so if I want to use any.tpl then I simply have to write tplname. if no class value given then it will take default template.
"field-name" it will consist name of the request variable which you want to set on checkbox. by default its value going to be "selected_value[]" if no value passed for it.
"cat-sel" it will consist of data of which category need to be selected when html load. it will take value like <?php echo htmlspecialchars(json_encode($selected_value)); ?> in
which $selected_value is the array of all category id which need to be selected.
I am having 2 pages
parent page consist a link, on click of this link i am calling an javascript function
function callPage( productId ){
var product = document.getElementById(ProductId).id;
var OpptyId = {!oppty.Id};
var urlToOpen = "/apex/" + '{!namespacePrefix}' + 'testPage?product='+product+'&OpptyId'=OpptyId ;
window.open(urlToOpen ,'','resizable=0,location=0,status=0,scrollbars=0,width=850,height=350,top=100,left=220')
}
where Oppty Id is taken from controller.
While in my child page I am getting all these paramiters as
ProductValueId = ApexPages.currentPage().getParameters().get('product');
opptyValue = ApexPages.currentPage().getParameters().get('OpptyId');
and these fields are then used in javascript as
function setValue()
{
var productId = '{!productValueId}';
window.parent.opener.document.getElementById(productId).value='{!productValue}';
}
where {!productValue} is taken from controller.
I am not understanding how and where should i make changes for soving my checkmarx issue.
So, please help me as I would want to submit the application for code review.
Best Regards
You are taking the query string parameter product, reading it into the productValueId controller member/property and then directly outputting it into the Visualforce page.
So basically whatever I give you on the query string ends up output into the page response.
With some effort it may be possible to encode a query string that will break out of your JavaScript and execute whatever I wan't.
E.g.
/apex/ABC__testPage?product=productId';alert('xss&OpptyId=006100000000001
Or something like that. To be fair, Visualforce will encode the expression for you.
Checkmarx has found the potential path. You will need to either remove this direct path or provide sufficient justification that it isn't open to XSS.
One helpful thing to do is enforce the data type on the values read from the query string. E.g. Explicitly use Id rather than string as the type for productValueId.
Then you could also verify that the records referenced in the query string params are actually valid for the current user. I.e. they haven't changed some of the values to gain access to records they otherwise shouldn't see.
Incidentally, the Salesforce StackExchange is a great place to ask Salesforce specific questions.
I have a site that will be displaying lots of number entry fields. The user will be entering the numbers, or using large plus & minus buttons to increment them.
These numbers will be things like age, annual income, percentages, or consumer prices.
I want to build a single, standard way of dealing with these numbers.
I explored the filters like {{priceOfCoffee | currency}}, which will work for those simple items, but when I get to the others, I have extra requirements.
For example, I want the annual income to have a $ prepended, group the 000s but have no decimal. I'll also want to restrict input to only numbers, etc.
I know I can do these with custom filters, or directives, but I'm just not sure whether it makes sense to create several custom filters, or a directive to which I can pass parameters.
Thoughts?
Thanks,
Scott
If you only care about formatting a single piece of text use a filter. If you want to reuse an entire block of content use a directive. It's difficult to be more specific with only a generic description of the application.
I had an application where I got medication information from the server which I needed to format, but I also wanted to use it in multiple places in the app. So I made a directive so I could reuse the entire block of content, but within that directive information about the dosage was formatted with filters.