How to translate the content of an attribute with angular-translate - angularjs

in my mongo schema i have an enum with predefined types:
let MeterSchema = new Schema({
[...]
type: {
type: String,
enum: ['Prepayment', 'TimeOfDay', 'PowerExport']
},
[...]
}
What i want is to display this value internationalized with i18n files on my angular view.
I looked at the Variale replacement of angular translate (https://angular-translate.github.io/docs/#/guide/06_variable-replacement), but could not figure it out how do it properly with this.
At the moment i translate it that way:
View
<div class="md-summary">{{vm.getMeterType(meter) | translate}}</div>
Controller
public getMeterType(meter): String {
return 'app.masterData.meters.type.' + meter.type;
}
But i think there has to be a better way to this.

The answer is actually pretty simple:
<div class="md-summary">{{'app.masterData.meters.type.' + meter.type | translate}}</div>
I don't know why i didn't use string concatenation in the first place.

Related

Newbee in Angular, how to use dictionaries?

I'm a C# programmer trying to learn Angular and Ionic.
I'd like to do something as we usually do in C# with dictionaries:
export class HomePage {
private times = [
{key: 'clockOn', value: '09:00'},
{key: 'lunchTime', value: '12:00'},
{key: 'backToWork',value: '13:00'},
{key: 'clockOff', value: '18:00'}
];
}
getHour(name: string) {
if(this.times[name] === 'clockOn'){
console.log('time: ' + this.times[name].value);
}
On HTML
<ion-datetime class="time" id="coff" displayFormat="HH:mm"
[(ngModel)]="cOff" (ionChange)="getHour('clockOn')">
</ion-datetime>
And on Chrome console I see:
clockOnundefined
First of all, is this the correct sintax to access the member 'value'?
this.times[0].value
I want to know if is it possible to access an array element using a string as indexer (key) like we do in C# with dictionaries
For example:
this.times['clockOn'].value //would bring me its value like '09:00'
or the only way to access a element is using numbers as indexers? Like below
this.times[0].key // bring me 'clockOn'
this.times[0].value // bring me '09:00'
Dictionary is Angular/ JavaScript does not work same as C#.
So your code:
this.times['clockOn'].value
this will not work.
You will have to use
this.times[0].key // bring me 'clockOn'
this.times[0].value // bring me '09:00'
If you want access with key like array[key] returning the value run the loop in this manner:
<td *ngFor="(key, value) in dictionary">
{{value}}
</td>
Hope it helps.
Personally I would just modify your data structure, if they are just hardcoded values.
private times = {
clockOn: '09:00',
lunchTime: '12:00',
backToWork: '13:00',
clockOff: '18:00'
};
getHour(key: string)
{
if (this.times[name] === 'clockOn')
{
console.log('time: ' + this.times[name].value);
}
}
<span *ngFor="(key, value) in times" *ngClick=getHour(key)>{{value}}</span>
Having an object with unique keys where you can use bracket notation to look up the desired item is more effective as it allows for quick simple look ups.
If you wanted to use the original data structure you would have to pass in the index of the repeat item so you can access the correct item in the array.
so your mark up would look like this:
<span *ngFor="time in times" let i=index; *ngClick=getHour(i)>{{value}}</span>
getHour(index: number)
{
if (this.times[index].key === 'clockOn')
{
console.log('time: ' + this.times[index].value);
}
}

Pass variable to component view to be used as filter

I've build a simple component that allows passing a filter as a parameter, and I'm trying to use that parameter in the component view, but I don't know how. It gets passed as a string so it's treated as a string in the component view and thus not working.
Basically it looks something like this:
<number-compare value="some.value" filter="currency"/>
And in the component view:
<span> {{ numCompCtrl.value | numCompCtrl.value.filter }} </span>
But that doesn't work because it gets interpreted as {{ 10 | "currency" }}
I've tried to handle it in the controller instead, and apply the filter there but it gets really messy when the filter needs multiple parameters so the easiest thing by far would be if I could get the simple way working.
Is it possible?
Actually, I just discovered that I had already solved this previously with another filter as a workaround 🙈
(function() {
'use strict';
angular
.module('core')
.filter('dynamic', dynamic);
dynamic.$inject = ['$interpolate'];
function dynamic($interpolate) {
return function(value, name) {
if (!name) {
return value;
}
var result = $interpolate('{{ value | ' + name + ' }}');
return result({ value: value });
};
}
})();
And used like this:
{{ numCompCtrl.value | dynamic: numCompCtrl.value.filter }}

string.format a string in AngularJS dynamically

I have a translate directive that takes a key and provides the text in the current locale which could be any language.
So for example you can do either:
<p translate="yes">#App.MyString</p>
or
<p>{{'#App.MyString' | translate }}</p>
And it will print in the language of the selected culture.
<p> This is my string </p>
The filter in place to handle translations is:
export class TranslateFilter {
public static build(getTextCatalog: Infrastructure.IGettextCatalog) {
var filter = (resourceKey, resourceType, resourcePrefix) => {
if (resourcePrefix != null) {
resourceKey = `${resourcePrefix}.${resourceKey}`;
}
return getTextCatalog.getString(`#${resourceType}.${resourceKey}`);
};
return filter;
}
}
I want to now also try to combine this with string.Format.
So if the #App.KeyString contains a string like this: 'Hi {0}. Welcome to {1}' I can do a string.Format using dynamic values.
I can do that within the controller but I was wondering if there's a way it could be done on the html file.
For example something like this:
<p translate="yes" format="{{scope.name}},{{scope.place}}">#App.MyString</p>
or
<p>{{'#App.MyString' | translate | format:[$scope.name, $scope.place] }}</p>
would print
'Hi Nick! Welcome to Narnia'
Any ideas?

filter and unfilter on ng-click with buttons

hello i have a couple of buttons i want to filter data with, but i can't figure out how to make it unfilter when i click the button again. I use the normal filtering expression like:
<tr ng-repeat='ledata in datas | filter:thecondition'></tr>
where the thecondition may vary depending on the button clicked, the button's code is the following
ng-click="thecondition = {type: 1}"
also how can i mark it with ng-class? make the button look pressed? thanks.
My recommendation is that try to implementing your own custom filter.
Something close to:
custom filter:
angular.module('myApp', []).filter('myFilter', function() {
return function(items, param1, param2) {
return items.filter(function(item){ /* your custom conditions */ });
};
});
and in your html
<li ng-repeat="item in items | myFilter:'car': 2">
Of course you could extend and perform the actions that are more suited to your app needs.
The reason why I recommend the custom filter is because it will allow you a better separation from the view and the business logic; which is more aligned with the MVVM design pattern behind angular.
For toggling the filter, try this:
ng-click="thecondition = thecondition ? '' : {type: 1}"
The ternary operator will set thecondition to an empty string if it has a value, and to the object with type : 1 if it's empty.
To set the class with ng-class, try this:
ng-class="{depressed_button: thecondition}"
When thecondition is truthy, the class depressed_button will be applied. It's up to you to define the depressed_button class in a stylesheet or elsewhere.

Nested curly braces with AngularJS

I'm currently working on a project using angular-translate. The goal for me is to create a translation map which allows a developer to change an object model without breaking the translation.
For example, say I have an order saved inside my scope:
$scope.order = {
numberOfItems: 5,
// ...
};
And a translation map with a property displaying the number of items:
var translationsEN = {
itemsNumber: "{{numberOfitems}} item(s)",
// ...
};
var translationsFR = {
itemsNumber: "{{numberOfItems}} article(s)",
// ...
};
With this map, I could easily do this:
{{'itemsNumber' | translate:order}}
But if a developer would like to change the name of the numberOfItems property, he will have to change the translation map too, which is pretty fastidious... So, I've changed my translation map for this:
var translationsEN = {
itemsNumber: "{{number}} item(s)",
// ...
};
var translationsFR = {
itemsNumber: "{{number}} article(s)",
// ...
};
Now, a developer just have to transmit a simple object with the necessary values, like this:
<span translate="order.misc.itemsNumber"
translate-values="{ number:{{order.numberOfItems}} }">
</span>
But, as you can see, I'm no longer using filters but directives. I can't find any way to do something like this:
{{'order.misc.itemsNumber' | translate:'{ number:{{order.numberOfItems}} }'}}
This doesn't work either:
{{'order.misc.itemsNumber' | translate:'{ number:order.numberOfItems }'}}
Is there any solution allowing me to use filters or should I just use directives?
Try without the quotes:
{{'order.misc.itemsNumber' | translate: {number: order.numberOfItems}}}

Resources