Internationalization of dynamic content in Angular? - javascript

Angular.io describes the i18n tag as follows:
The Angular i18n attribute marks translatable content. Place it on
every element tag whose fixed text is to be translated.
So my question is this. What if I have an element whose content is dynamic? Take for example this below table that shows a list of assets. The column, "Description" needs to be in some cases English, and in some cases some other language.
<table class="asset-table">
<thead>
<tr>
<th i18n="##alarm-list-timeon">Time On</th>
<th i18n="##alarm-list-timeoff">Time Off</th>
<th i18n="##alarm-list-asset">Asset</th>
<th i18n="##alarm-list-description">Description</th>
</tr>
</thead>
<tbody *ngIf="showAssets">
<tr *ngFor="let asset of pageItems">
<td>{{asset.timeon}}</td>
<td>{{asset.timeoff}}</td>
<td>{{asset.assetlabel}}</td>
<td i18n>{{asset.description}}</td>
</tr>
</tbody>
</table>
I was thinking something like this:
<table class="asset-table">
<thead>
<tr>
<th i18n="##alarm-list-timeon">Time On</th>
<th i18n="##alarm-list-timeoff">Time Off</th>
<th i18n="##alarm-list-asset">Asset</th>
<th i18n="##alarm-list-description">Description</th>
</tr>
</thead>
<tbody *ngIf="showAssets">
<tr *ngFor="let asset of pageItems">
<td>{{asset.timeon}}</td>
<td>{{asset.timeoff}}</td>
<td>{{asset.assetlabel}}</td>
<td i18n="##{{asset.description}}">{{asset.description}}</td>
</tr>
</tbody>
</table>
...but I was mistaken. Any suggestions?

First, the i18n value is an ID, so it would always be static.
Second, as far as translating content that changes, the only success I have had is a workaround using NgSwitch in the template.
In this example, thingStatus is your variable, and its possible values are 'good', 'bad', and 'unknown'. All of these would each be a separate translation item, with its own i18n ID value.
Obviously, this would fail if thingStatus could have an unmanageable number of possibilities.
<div [ngSwitch]="thingStatus">
<p *ngSwitchCase="good" i18n="status_good>Good</p>
<p *ngSwitchCase="bad" i18n="status_bad>Bad</p>
<p *ngSwitchCase="unknown" i18n="status_unknown>Unknown</p>
</div>

Use this construction
<span
i18n="status text|Status text##statusText"
>{
asset.statusLangCode, select,
bad {Bad}
good {Good}
other {Unknown}
}</span>
And in translation file there will be generated a construct like this (target is added manually)
<source>{VAR_SELECT, select, good {Good} bad {Bad} other {Unknown}}</source>
<target>{VAR_SELECT, select, good {Хороший} bad {Плохой} other {Неизвестный}}</target>
For more info see https://angular.io/guide/i18n#translate-select

Assuming that your backend service returns known possible values, you can do the following:
const values = ['admin', 'teacher', 'librarian']
Add the translated values to sv_SE.json given the previous values as keys
role: {
"admin": "admin",
"teacher": "lärare",
"librarian": "Bibliotekarie"
}
Call the translation in your app.component.html
<div *ngFor="let value of values">
{{ ('role.' + value) | translate }}
</div>

Related

How do i put the serial number in each table row while using {{#each}} loop in handlebars?

I am creating a table to show list of items from the database, but how do I put the serial No. for the list when using an {{#each}} loop:
<table class="table mt-5">
<thead>
<tr>
<th scope="col">No.</th>
<th scope="col">Title</th>
<th scope="col">Category</th>
<th scope="col">Description</th>
<th>Image</th>
</tr>
</thead>
<tbody>
{{#each products}}
<tr>
<th scope="row">1</th>
<td>{{this.Name}}</td>
<td>{{this.Category}}</td>
<td>{{this.Description}}</td>
<td><img style="width:100px" src="/product-images/{{this._id}}.png" alt="Img"></td>
</tr>
{{/each}}
</tbody>
</table>
This is the table I am using. In the <th> tag I have written 1. I want to replace it with the sl. no. This is an .hbs file and I am using Node.js and MongoDB as database.
How can I do it?
Handlebars provides a data-variable, #index, for getting the index of current item in an #each iteration. However, like JavaScript arrays, #index is 0-based, so your result would be 0, 1, 2, ... - which is not what you asked for. To use #index, the impacted line in your template would become:
<th scope="row">{{#index}}</th>
If you require your serial numbers to start a 1 it will require a little more work. There is nothing out-of-the-box from Handlebars that will allow us to add 1 to #index. We would need to write a custom helper, a very simple one. For example:
helpers: {
increment(num) {
return num + 1;
}
}
And then our template would become:
<th scope="row">{{increment #index}}</th>
Here is an example fiddle for reference.
My feeling about this approach is that it is excessive to add a helper for such a simple purpose. I would recommend adding a SerialNumber property to each Product before it is passed to the template, before the res.render() call. It would look something like:
products.forEach((product, index) => {
products[index].SerialNumber = index + 1;
});
This way, the SerialNumber will be available to each Product in your template:
<th scope="row">{{this.SerialNumber}}</th>

take value from one html page to another

I want to take the value.university from my index.html to the universities.html page. How can I do this? Is this possible with maybe hidden value?
<table id="myTable">
<tr class="header">
<th style="width:60%;">State</th>
<th style="width:40%;">University</th>
</tr>
<tr ng-repeat="value in myDynamicData track by $index">
<td>{{value.state}}</td>
<td>{{value.university}}</td>
</tr>
</table>
A purely client-side approach would be to use localStorage, which stores a variable in the client browser. You can use:
var university = "some value here";
//creates a variable in the browser called university, which is now accessible from all pages of your website.
localStorage.setItem("university", university);
Now, in your second page:
var uni= localStorage.getItem("university"); //gets the value of "university" from localStorage
<table id="myTable">
<tr class="header">
<th style="width:60%;">State</th>
<th style="width:40%;">University</th>
</tr>
<tr ng-repeat="value in myDynamicData track by $index">
<td>{{value.state}}</td>
<td>{{value.university}}</td>
</tr>
</table>
Then in the universities.html you can read using window.location.search

Vue.js get unknown Json key for v-for

I built a code analysis tool and I want to set my json Data in a vue Table. However, I need the json Key, which is the Package/File name to the directory which data I want to show.
Here is the json Part (NULLY is the Package):
"folderStatistics": {
"NULLY": {
"Statistiken": {
"Werte": {
"Felder": "0",
"Konstruktoren": "0",
"Methoden": "8",
"Klassen": "1",
"Codezeilen": "191"
}
},
and this is my HTML:
<table class="table table-bordered">
<thead>
<tr>
<th></th>
<th>Felder</th>
<th>Konstruktoren</th>
<th>Methoden</th>
<th>Klassen</th>
<th>Codezeilen</th>
</tr>
</thead>
<tbody>
<tr v-for="value in folderStatistics.NULLY.Statistiken">
<td>{{$key}}</td>
<td>{{value.Felder}}</td>
<td>{{value.Konstruktoren}}</td>
<td>{{value.Methoden}}</td>
<td>{{value.Klassen}}</td>
<td>{{value.Codezeilen}}</td>
</tr>
</tbody>
With "NULLY", it works the Directory, but NULLY should be dynamic.
How can I make that? Does it even work?
documentation
You can have NULLY in a variable say package and use it in view like following:
<tbody>
<tr v-for="(value, key) in folderStatistics[package].Statistiken">
<td>{{key}}</td>
<td>{{value.Felder}}</td>
<td>{{value.Konstruktoren}}</td>
<td>{{value.Methoden}}</td>
<td>{{value.Klassen}}</td>
<td>{{value.Codezeilen}}</td>
</tr>
</tbody>
demo fiddle.

How to display data inside table by ng-repeat using Angular.js

I need one help i need to display data inside table using Angular.js.I am explaining my code below.
$scope.listOfData=[
{
{'date':'2016-01-25 18:14:00','name':'raj','email':'raj#gmail.com','order_status':1,'order_id':1111},
{'date':'2016-02-04 11:26:05','name':'raj','email':'raj#gmail.com','order_status':0,'order_id':2222}
},
{
{'date':'2016-01-23 13:15:59','name':'rahul','email':'rahul#gmail.com','order_status':1,'order_id':3333},
{'date':'2016-01-25 18:14:00','name':'rahul','email':'rahul#gmail.com','order_status':0,'order_id':4444}
}
]
my html table is given below.
<div class="table-responsive dashboard-demo-table">
<table class="table table-bordered table-striped table-hover" id="dataTable" >
<tbody>
<tr>
<td rowspan="2">Date</td>
<td rowspan="2">Name</td>
<td rowspan="2">Email</td>
<td colspan="7">Order</td>
</tr>
<tr>
<td>Order Id</td>
<td>Order status</td>
</tr>
<tr>
<td>date</td>
<td>name</td>
<td>email</td>
<td>orderid</td>
<td>orderstatus</td>
</tr>
</tbody>
</table>
</div>
expected output result.
date name email order
order_id order_status
2016-01-25 raj raj#gmail.com 1111 1
to 2016-02-04 2222 0
The above table is for serial no-1 again for sl no-2 the data will display accordingly.
Here i need suppose 0th index of $scope.listOfData has two set of data some field value like name,email are same so these two sate of data will join and it will display in 1st index of the table.Here date column will contain lower date to higher date like(from date to todate),name and email filed will contain the value one but here different is for order column order_id and order_status is different for each set of data of 0th index from $scope.listOfData so these will again move in a another loop.Please help me.
The following may help you
<div ng-repeat="data in listOfData">
<!--<Do whatever you need here with data.name, data.date etc...>-->
<!--You can keep your table here.-->
</div>
<tr ng-repeat="data in listOfData">
<td>{{data.date}}</td><td>{{data.name}}</td>....
</tr>
PS for header you can use a <thead> tag
Edit :
{
{'date':'2016-01-25 18:14:00','name':'raj','email':'raj#gmail.com','order_status':1,'order_id':1111},
{'date':'2016-02-04 11:26:05','name':'raj','email':'raj#gmail.com','order_status':0,'order_id':2222}
}
You can't with your json format like this, flatten it in a one level array with even index containing "from" and odd containing "to" datas then do the following
<tr ng-repeat="data in listOfData">
<td ng-if="$index %2==0">{{data.date}}</td>
<td ng-if="$index %2==1">To {{data.date}}</td>
...
</tr>
EDIT : can't really make a plunker, here is what by flatten I mean transform this
$scope.listOfData=[
[
{'date':'2016-01-25 18:14:00','name':'raj','email':'raj#gmail.com','order_status':1,'order_id':1111},
{'date':'2016-02-04 11:26:05','name':'raj','email':'raj#gmail.com','order_status':0,'order_id':2222}
},
{
{'date':'2016-01-23 13:15:59','name':'rahul','email':'rahul#gmail.com','order_status':1,'order_id':3333},
{'date':'2016-01-25 18:14:00','name':'rahul','email':'rahul#gmail.com','order_status':0,'order_id':4444}
]
]
Into this :
$scope.listOfData=[
{'date':'2016-01-25 18:14:00','name':'raj','email':'raj#gmail.com','order_status':1,'order_id':1111},
{'date':'2016-02-04 11:26:05','name':'raj','email':'raj#gmail.com','order_status':0,'order_id':2222},
{'date':'2016-01-23 13:15:59','name':'rahul','email':'rahul#gmail.com','order_status':1,'order_id':3333},
{'date':'2016-01-25 18:14:00','name':'rahul','email':'rahul#gmail.com','order_status':0,'order_id':4444}
}
]
So your "from" lines will have even index (0,2,4...) and your "to" lines will have the odds ones (1,3,5,...).
Using $index you can now built properly your lines : $index is given by ng-repeat. ng-if is a directive that won't build the dom element if the condition is not true.
So this
<td ng-if="$index %2==0">{{data.date}}</td>
<td ng-if="$index %2==1">To {{data.date}}</td>
Will always build only one <td> element.

Angular JS object as ng-model attribute name

I'm creating a dynamic angular js application wherein I want to use a textbox as a searchtext for the filter of a table. Here's a preview on what I am doing:
As of now, my code looks like this
<table>
<thead>
<tr class="filterrow">
<td data-ng-repeat="col in items.Properties">
<input id="{{col.DatabaseColumnName}}" type="text"
data-ng-model="search_{{col.DatabaseColumnName}}"/>
<!-- Above Here I want to dynamically assign the ng-model based on Databasecolumnname property-->
</td>
</tr>
<tr>
<th data-ng-repeat="col in items.Properties">{{col.ColumnTitle}}</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="content in items2.Contents | filter: search_{{col.DatabaseColumnName}}: search_{{col.DatabaseColumnName}}">
<td data-ng-repeat="col in items.Properties">
{{content[col.Databasecolumnname ]}}
</td>
</tr>
</tbody>
</table>
I already tried the approach of using $compile but I wasn't able to implement it. Any ideas in an approach? Thanks!
EDIT: Plnkr - plnkr.co/edit/5LaRYE?p=preview
You can do this by setting a base object for your ng-Models. So in your controller you will have:-
$scope.search = {};
and in your view do:-
<input ng-attr-id="{{col.DatabaseColumnName}}" type="text"
data-ng-model="search[col.DatabaseColumnName]"/>
With this your dynamic ng-model will be assigned to the search base object, ex:- if col.DatabaseColumnName is col1 then ngModel would be $scope.search.col1

Categories

Resources