Is there something similar to AngularJS $interpolate in Angular2+?
I would like to achieve this (in JS/TS code) but with Angular2+:
EDIT
The main goal to achieve is to $interpolate string without having
knowledge of transform pipe which is used inside string to
interpolate.
JS
var myApp = angular.module('myApp',[]);
myApp.controller('myCtrl', myCtrl);
var JsonTranslation = {
"txt1": "Cash {{ value | currency: 'USD'}}",
"txt2": "Number {{ value | number: 3}}"
};
function myCtrl($scope, $interpolate) {
$scope.txt1 = $interpolate(JsonTranslation.txt1)({value: 50000});
$scope.txt2 = $interpolate(JsonTranslation.txt2)({value: 50000.123456});
}
HTML
<div ng-controller="myCtrl">
<div>{{txt1}}</div> <!-- Cash USD50,000.00 -->
<div>{{txt2}}</div> <!-- Number 50,000.123 -->
</div>
Working jsfiddle http://jsfiddle.net/3nf7cza4/
Yes:
`Cash ${this.currency.transform(value, 'USD')}`
Where this.currency is the injected pipe you want to use and transform is the function in the pipe which converts your value.
I assume currency is an angular pipe (can't remember if it is or not) so you'd simply inject it like so:
import {CurrencyPipe} from '#angular/core';
constructor(private currency: CurrencyPipe) {}
Related
Because of the following quote in this thread
The best practice is never use JQuery or angular.element() for DOM manipulation inside controllers. Controllers are only used for our business logic.
I have moved a big function that calls CodeMirror and JQuery outside a controller. The big function is used to combine the content of two textareas. JSBin
Html:
<div ng-app="myApp" ng-controller="myCtrl">
<textarea ng-model="area1">area1</textarea>
<textarea ng-model="area2">area2</textarea>
<div>First: {{area1}}, {{area2}}</div>
<div id="output"></div>
<script>
function bigfunction(area1, area2) {
// a big function, the following is for the sake of simplicity
return "Second: " + area1 + ", " + area2
}
var output = bigfunction({{area1}}, {{area2}});
$("#output").html(output)
</script>
</div>
Javascript:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.area1 = "initial textarea1";
$scope.area2 = "initial textarea2"
});
Does anyone know why {{area1}} and {{area2}} in the script are not recognised?
The problem is that you're mixing JavaScript with AngularJS templates.
var output = bigfunction({{area1}}, {{area2}});
You cannot expect inline JavaScript to work using AngularJS templates. Here's what happens: the HTML file (template) is loaded and the inline JS is parsed and executed. It fails because it contains erroneous syntax ({{area1}}). This occurs before AngularJS is even loaded. Also, JavaScript code is evaluated but once, so even if the template actually replaced the {{area1}} with a string, the code would not be reevaluated and would not produce a different output. You will need to change your approach entirely.
I'm guessing that you would like to perform the joining of the two scope variables outside the controller and perhaps add extra logic to that. You can either move the code to a service and then use it in your controller, or use a directive (I don't know your exact use case, so it's hard for me to say which approach will make more sense).
Since what you described is simple concatenation of two model values, a directive appears to make sense. Your HTML could look like this:
<div ng-app="myApp" ng-controller="myCtrl">
<textarea ng-model="area1">area1</textarea>
<textarea ng-model="area2">area2</textarea>
<div>First: {{area1}}, {{area2}}</div>
<output area1="area1" area2="area2"></output>
</div>
And in the JS, add this simple directive:
app.directive('output', function() {
return {
restrict: 'E',
template: '<div id="output">Second: {{area1}}, {{area2}}</div>',
scope: {
area1: "=",
area2: "="
}
};
});
If for some reason you wish to add extra logic to your directive, you can always do that in the linking function.
Were you to add a service, the HTML would again require only a minor change:
<div ng-app="myApp" ng-controller="myCtrl">
<textarea ng-model="area1">area1</textarea>
<textarea ng-model="area2">area2</textarea>
<div>First: {{area1}}, {{area2}}</div>
<div>{{output}}</div>
</div>
And the JS could look like this:
app.controller('myCtrl', function($scope, joiner) {
$scope.area1 = "initial textarea1";
$scope.area2 = "initial textarea2";
$scope.$watchGroup(["area1", "area2"], function() {
$scope.output = joiner.join($scope.area1, $scope.area2);
});
});
app.service('joiner', function() {
this.join = function(a1, a2) {
return "Second: " + a1 + ", " + a2;
};
});
The service can contain any logic you need.
the script tag seem to have no access to angular vars. See Pass Angular scope variable to Javascript to check for a solution.
You can try like this:
$scope.area1 = "initial textarea1";
$scope.area2 = "initial textarea2";
function bigfunction(area1, area2) {
// a big function, the following is for the sake of simplicity
return "Second: {{area1}} {{area2}}"
}
var output = bigfunction($scope.area1, $scope.area2);
$compile(angular.element(document.querySelectorAll('#output')[0]).html(output))($scope);
or you can try directive like this:
app.directive('outputDir', function() {
return {
restrict: 'EA',
scope: {
area1: "=",
area2: "="
},
template: '<div>Second: {{area1}}, {{area2}}</div>'
};
});
All the best.
You could try this:
<script>
window.onload=function bigfunction() {
var area1=angular.element(document.querySelector('[ng-controller="myCtrl"]')).scope().area1;
var area2=angular.element(document.querySelector('[ng-controller="myCtrl"]')).scope().area2;
result= "Second: " + area1 + ", " + area2;
$("#output").html(output);
}
</script>
You can retrieve the angular js scope variable in javascript in this way.
I have read about the module way of defining a filter:
myApp.filter('filtername', function() {
return function() {
};
});
But what if I am using a simple function controller for my angular app and not as a module?
I.e. all I have at the top of my html is:
<html ng-app ng-controller="MyApp">
and then I include a js file with a simple controller:
function MyApp($scope, $http){
}
but I need to define a custom filter - in my particular case I'm trying to order an ngRepeat using Justin Klemm's object ordering filter. So how can I define a filter not using the module style syntax?
If you want create a new filter in your app you could define the your custom filter like below:
in your js
angular.module("yourModule")
.filter("yourFilretName",function(){
return function(value,arg1,arg2 .....){
var result = [];
// filter processing the object that pass the filtering, must be push on the result array
return result;
}
})
in your template
<your-tag ng-repeat="book in bookList | yourFilretName :arg1:agr2:....:argn>
.....
</your-tag>
<div ng-app="myApp" ng-controller="myCtrl">
<ul>
<li ng-repeat="item in items | filter: myFilter">{{ item }}</li>
</ul>
...
var myApp= angular.module("myApp", []);
myApp.controller('myCtrl', function($scope ) {
function myFilter(item) {
return item == "some condition"
}
})
I have an application that deals with different currencies. I get currency symbol from a web service and store that symbol in the controller's $scope.
$scope.symbol = '€';
When I try to show that in html,
This is working:
{{ 1500 | currency:"€" }}
This is not working
{{ 1500 | currency:symbol }}
here's a plunker. Any ideas?
If you want to bind html or markup you need to use "ng-bind-html" and mark the content as trusted on your controller. I'm unaware of any way of how to do this with the mustache binding mechanism. But this is the approach we've been using when needing to bind markup.
Make the code trusted in the controller
Wrap the filter in a custom filter - Limitation is that you'll still need ng-bind-html
Below are 3 options available to you:
Controller
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope,$sce) {
$scope.nonTrustedSymbol = '€';
$scope.trustedSymbol = $sce.trustAsHtml('€');
})
.filter('currencyWithNumberFilter', ['$filter','$sce',
function ($filter, $sce) {
return function (input, curr) {
var formattedValue = $filter('number')(input, 2);
return $sce.trustAsHtml(curr + formattedValue);
}
}]
)
.filter('currencyWithCurrencyFilter', ['$filter','$sce',
function ($filter, $sce) {
return function (input, curr) {
var formattedValue = $filter('currency')(input,curr);
return $sce.trustAsHtml(formattedValue);
}
}]
);
Markup
<body ng-controller="MainCtrl">
"Vanilla" controller & number filter:
<span ng-bind-html=trustedSymbol></span>{{ 1500 | number:2 }}
<br/>
Custom filter, internally making use of Number filter for formatting:
<span ng-bind-html="1500 | currencyWithNumberFilter:nonTrustedSymbol"></span>
<br/>
Custom filter, internally making use of Currency filter for formatting:
<span ng-bind-html="1500 | currencyWithCurrencyFilter:nonTrustedSymbol"></span>
</body>
Working sample
var app = angular.module('app', []);
app.controller('MainCtrl', function($scope,$sce) {
$scope.nonTrustedSymbol = '€';
$scope.trustedSymbol = $sce.trustAsHtml('€');
})
.filter('currencyWithNumberFilter', ['$filter','$sce',
function ($filter, $sce) {
return function (input, curr) {
var formattedValue = $filter('number')(input, 2);
return $sce.trustAsHtml(curr + formattedValue);
}
}]
)
.filter('currencyWithCurrencyFilter', ['$filter','$sce',
function ($filter, $sce) {
return function (input, curr) {
var formattedValue = $filter('currency')(input,curr);
return $sce.trustAsHtml(formattedValue);
}
}]
);
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.min.js"></script>
</head>
<body ng-controller="MainCtrl">
"Vanilla" controller & number filter:
<span ng-bind-html=trustedSymbol></span>{{ 1500 | number:2 }}
<br/>
Custom filter, internally making use of Number filter for formatting:
<span ng-bind-html="1500 | currencyWithNumberFilter:nonTrustedSymbol"></span>
<br/>
Custom filter, internally making use of Currency filter for formatting:
<span ng-bind-html="1500 | currencyWithCurrencyFilter:nonTrustedSymbol"></span>
</body>
</html>
to an addition to Rohan's answer, where ng-bind-html was the solution, you could also use isoCurrency module.
if you have the ISO 4217 currency code (3 chars length e.g. USD, EUR, etc) isoCurrency can output the right format, fraction size and symbol.
// in controller
$scope.amount = 50.50;
$scope.currency = 'USD';
// in template
{{ amount | isoCurrency:currency }} // $50.50
isoCurrency
Demo
Try this in your controller:
$scope.symbol = '€';
Plunker
If using JQuery (Otherwise do the same thing but in pure javascript, it will take much more code but is possible, basically create a html dom element and insert your input as innerHTML to it, then read it's innerText)
function unescapeHTML(html) {
return $("<div />").html(html).text();
}
And then of course
$scope.price=unescapeHTML('€');
To display currency symbol in angular js you need provide HTML entity for currency symbols below are the examples and usage in through code and in template :
Inside your Template example of Euro:
Item Price<span style="font-weight:bold;">{{price | currency:"€"}}</span>
example of Rupee:
Item Price<span style="font-weight:bold;">{{price | currency:"₹"}}</span>
Also check below url
http://www.cs.tut.fi/~jkorpela/html/euro.html
From controller :
Inject $filter in your controller
$scope.price=$filter('currency')($scope.price,'€')
<a href="#/search?query={{address}}" ng-repeat="address in addresses">
{{address}}
</a>
generates links that are not url encoded if I understand correctly. What is the proper way to encode #/search?query={{address}}?
Example address is 1260 6th Ave, New York, NY.
You can use the native encodeURIComponent in javascript.
Also, you can make it into a string filter to utilize it.
Here is the example of making escape filter.
js:
var app = angular.module('app', []);
app.filter('escape', function() {
return window.encodeURIComponent;
});
html:
<a ng-href="#/search?query={{address | escape}}">
(updated: adapting to Karlies' answer which uses ng-href instead of plain href)
#Tosh's solution will return #/search?query=undefined if address is undefined in
<a ng-href="#/search?query={{address | escape}}">
If you prefer to get an empty string instead for your query you have to extend the solution to
var app = angular.module('app', []);
app.filter('escape', function() {
return function(input) {
if(input) {
return window.encodeURIComponent(input);
}
return "";
}
});
This will return #/search?query= if address is undefined.
You could use the encodeUri filter: https://github.com/rubenv/angular-encode-uri
Add angular-encode-uri to your project:
bower install --save angular-encode-uri
Add it to your HTML file:
<script src="bower_components/angular-encode-uri/dist/angular-encode-uri.min.js"></script>
Reference it as a dependency for your app module:
angular.module('myApp', ['rt.encodeuri']);
Use it in your views:
<a href="#/search?query={{address|encodeUri}}">
Tosh's answer has the filter idea exactly right. I recommend do it just like that. However, if you do this, you should use "ng-href" rather than "href", since following the "href" before the binding resolves can result in a bad link.
filter:
'use strict';
angular.module('myapp.filters.urlEncode', [])
/*
* Filter for encoding strings for use in URL query strings
*/
.filter('urlEncode', [function() {
return window.encodeURIComponent;
}]);
view:
<a ng-href="#/search?query={{ address | urlEncode }}" ng-repeat="address in addresses">
{{address}}
</a>
this is a working code example:
app.filter('urlencode', function() {
return function(input) {
return window.encodeURIComponent(input);
}
});
And in the template:
<img ng-src="/image.php?url={{item.img_url|urlencode}}"
I am new to Angular.js. I currently have the following html code, where I define my div with my file html ( ng-include ) and my controller ( ng-controller ):
<div id="customerinformation-maxi" ng-include="'pages/customerinformation-maxi.html'" ng-controller="customerInformationMaxiController" class="col-md-12"></div>
This is the html code for the called html in directive ng-include ( customer-information.html ):
<div class="row">
<div class="col-md-2">
<span>Customer Number</span>
<span>{{customer.number}}</span>
</div>
<div class="col-md-2">
<span>Portfolio</span>
<span>{{custom.portfolio}}</span>
</div>
</div>
This is the js controller:
angularRoutingApp.controller('customerInformationMaxiController', function($scope, $http) {
//Here i need to load the model variable with a literal text {{customer.number}} and {{customer.portfolio}}, how could do it? using scope object? with a json file?
});
Here I need to load the model variable with a literal text {{customer.number}} and {{customer.portfolio}}.
How could do it? Using scope object? With a json file?
Thanks for any help.
Yes, you should do it using the $scope object.
To get a general overview, here is a hello-world example:
<div ng-controller="HelloController">
{{ helloMessage }}
</div>
And in you controller's code (js file or script tag into the html):
var myApp = angular.module('myApp',[]);
myApp.controller('HelloController', ['$scope', function($scope) {
$scope.helloMessage= 'Hello World!';
}]);
But I foresee some nesting in the provided snippet of your question, so you 're probably dealing with a collection of objects which means that you have to iterate through it, in the html part, using the ng-repeat directive, like:
<tr ng-repeat="customer in customers>
<td>{{customer.number}}</td>
<td>{{customer.portfolio}}</td>
</tr>
So, your controller's functionality should contain the customers object, like:
angularRoutingApp.controller('customerInformationMaxiController', function($scope, $http) {
var customers=[
{
number:'123',
portfolio: 'blah blah'
},
{
number:'124',
portfolio: 'blah blah'
},
{
number:'125',
portfolio: 'blah blah'
}
];
});
For further reference, you could read two respective example I have written:
Angular.js Controller Example
Angular.js JSON Fetching Example
The second one is only to see a sample usage of traversing collections, it is not meant that you have to use json, as you stated in your question; but I see that you also defined the $http service in your controller, so if it's about data that are going to be fetched from a remote destination, the JSON Fetching Example should probably help you better).
You should use scope objects to give values to your modal variables.
angularRoutingApp.controller('customerInformationMaxiController', function($scope, $http) {
$scope.customer.number = 'sample number';
$scope.customer.portfolio = 'sample portfolio';
});