Angular 7 ngx-translate change run time transaltion without refresh page - translate

Notes: I tired all questions & answers related to this topic.
I want to Translate Typescript variable Value without refresh page on change language Dropdown .
I trying To change the language-wise data change. I success to change to HTML Bind: value on dropdown value change but not update TypeScript Bind: value.
i use ngx-translate
I referer Links: but not success
angular-ngx-translate-usage-in-typescript
ngx-translate-in-ts-file-angular
ngx-translate-with-dynamic-text-on-ts-file
components.ts
import { Component, OnInit } from '#angular/core';
import { TranslateService } from '#ngx-translate/core';
#Component({
selector: 'app-translate',
templateUrl: './translate.component.html',
styleUrls: ['./translate.component.css']
})
export class TranslateComponent implements OnInit {
typeScriptvalue: string;
simpleProducts:any[]=[ {
name:'English',
id:'en'
},
{
name:'French',
id:'fr'
}];
constructor(private translate: TranslateService) {
this.typeScriptvalue = this.translate.instant('HOME.TITLE');
}
ngOnInit(): void {
}
changeevent(e)
{
console.log(e);
this.translate.use(e.value);
}
}
component.html
<label><b> HTML Bind</b></label> : <div>{{ 'HOME.TITLE' | translate }}</div> <br>
<label><b>TypeScript Bind</b></label> : <div>{{ typeScriptvalue }}</div> <br>
<label>
Change language : <div class="dx-field-value">
<dx-select-box [dataSource]="simpleProducts" displayExpr="name" valueExpr="id" (onValueChanged)="changeevent($event)"></dx-select-box>
</div>
</label>

After long research I have finally got the best solution.
You can reassign the Typescript variable on the subscriber method. use method
changeevent(e)
{
console.log(e);
this.translate.use(e.value).subscribe(data => {
this.typeScriptvalue = this.translate.instant('Home.Title');
});
}

Related

Can't get html element using js file in SPFX

I am trying to build dynamic content from a SharePoint list using SPFX. I'd like to use jQuery to build an accordion view of the data. The issue is that I can't even seem to get the element once the page is rendered.
In my code I am requiring a file called ota.js with the following code:
console.log('Start');
function otaExpand(){
console.log('otaExpand Function Called');
let spListContainer = document.getElementById('spListContainer');
console.log(spListContainer);
}
window.addEventListener("load", otaExpand());
In my ts file this is my render method:
public render(): void {
this.domElement.innerHTML = `
<div>
<div id="spListContainer">TEST</div>
</div>
`;
//this._renderListAsync();
//($('.accordion', this.domElement) as any).accordion();
}
When I review the console, I get my messages, but the element itself comes back as null.
console.log
I am using SharePoint 2019 on premise with the following configuration.
+-- #microsoft/generator-sharepoint#1.10.0
+-- gulp-cli#2.3.0
`-- yo#2.0.6
node --version
v8.17.0
I should also mention I am using TypeScript with no JavaScript framework.
Does anyone know why I can't access this element from my js file?
Thanks!
My overall goal is to call list data and apply an accordion style to it (https://jqueryui.com/accordion), but I can't even get passed capturing the element to change it.
I've tried calling my code from a js file as well as trying to put the code directly in the html. Neither worked.
OK, I finally figured out what I was doing wrong. I was calling my jQuery in the render() method rather than in _renderList where this.domElement actually makes sense.
Here's my code in case anyone wants to avoid the pain I put myself through. This allows you to specify a list in the site and you just need to add the fields you want to display.
import { Version } from '#microsoft/sp-core-library';
import {
BaseClientSideWebPart,
IPropertyPaneChoiceGroupOption,
IPropertyPaneConfiguration,
PropertyPaneChoiceGroup,
PropertyPaneCustomField,
PropertyPaneTextField
} from '#microsoft/sp-webpart-base';
import { escape } from '#microsoft/sp-lodash-subset';
import styles from './GetSpListItemsWebPart.module.scss';
import * as strings from 'GetSpListItemsWebPartStrings';
import {
SPHttpClient,
SPHttpClientResponse
} from '#microsoft/sp-http';
import * as jQuery from 'jquery';
import 'jqueryui';
import { SPComponentLoader } from '#microsoft/sp-loader';
import PropertyPane from '#microsoft/sp-webpart-base/lib/propertyPane/propertyPane/PropertyPane';
export interface IGetSpListItemsWebPartProps {
title: string;
description: string;
listField: string;
}
export interface ISPLists {
value: ISPList[];
}
export interface ISPList {
ID: string;
Title: string;
Website: {
Description : string,
Url : string
};
Description : string;
}
export default class GetSpListItemsWebPart extends BaseClientSideWebPart<IGetSpListItemsWebPartProps> {
private _getListData(): Promise<ISPLists> {
return this.context.spHttpClient.get(this.context.pageContext.web.absoluteUrl + "/_api/web/lists/GetByTitle('" + this.properties.listField + "')/Items",SPHttpClient.configurations.v1)
.then((response: SPHttpClientResponse) => {
return response.json();
});
}
private _renderListAsync(): void {
this._getListData()
.then((response) => {
this._renderList(response.value);
})
.catch(() => {});
}
private _renderList(items: ISPList[]): void {
let listData = `
<h1>${this.properties.title}</h1>
<h2>${this.properties.description}</h2>
<div class="accordion">
`;
items.forEach((item: ISPList) => {
let Description : string;
item.Description ? Description = item.Description : Description = "";
listData += `
<h3> ${item.Title}</h3>
<div>
<table>
<tr>
<td>OTA URL</td>
<td>${item.Website.Description}</td>
</tr>
<tr>
<td>Description</td>
<td>${Description}</td>
</tr>
</table>
</div>
`;
});
listData += '</div>';
this.domElement.innerHTML = listData;
const accordionOptions: JQueryUI.AccordionOptions = {
animate: true,
collapsible: true,
icons: {
header: 'ui-icon-circle-arrow-e',
activeHeader: 'ui-icon-circle-arrow-s'
}
};
jQuery('.accordion', this.domElement).accordion(accordionOptions);
}
public render(): void {
this._renderListAsync();
}
protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration {
return {
pages: [
{
header: {
description: strings.PropertyPaneDescription
},
groups: [
{
groupName: strings.BasicGroupName,
groupFields: [
PropertyPaneTextField('title',{
label: strings.TitleFieldLabel
}),
PropertyPaneTextField('description', {
label: strings.DescriptionFieldLabel
}),
PropertyPaneTextField('listField', {
label: strings.ListFieldLabel
})
]
}
]
}
]
};
}
public constructor() {
super();
SPComponentLoader.loadCss('//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css');
}
}
Your code from the "ota.js" file is probably called before your HTML is initialized (i.e. before the "render()" function is executed). To make sure this is the case, you could add log to the "render()" function to see when it's called.
In other words, "window.load" event happens long before "render()" function is called. This is how web parts are loaded - dynamically after full load of the page. Or "window.load" does not happen at all - web parts may be loaded by the user when using the page designer, i.e. without page reload.
To fix the issue, you should get the element after it's created, i.e. after the "render()" function creates the element you are trying to get.

Angular variable in component not rendering in template

Answer: I was using title: 'myTitle' instead of title = 'myTitle' ;(
I have just generated a new Angular app with one new component.
The problem is when i initialize a variable inside the class component and try to output it in the template using {{}} it is not showing variable's value.
In the main - App-Root Component it is written just like my code but there it is working :(
content.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'app-content',
templateUrl: './content.component.html',
styleUrls: ['./content.component.sass']
})
export class ContentComponent {
title: 'Content'
}
content.component.html
<h3>{{title}}</h3>
This is how you should bind values :
In component.ts :
public title:any = 'Content';
in component.html :
<h1> {{title}} </h1>
Here is a working example : demo
Use the angular variable as below
title: string="Content"
For eg
Try this, I have created a sample MyComponent class as below.
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-my-component',
templateUrl: './my-component.component.html',
styleUrls: ['./my-component.component.css']
})
export class MyComponentComponent implements OnInit {
private myVariable:string="Hello World"
constructor() { }
ngOnInit() {
}
}
my-component.component.html
<p>
{{myVariable}}
</p>
Make sure add the above component in app.component.html which is the bootstrapping component as below
<app-my-component></app-my-component>
also in app.module as below in declartion section
declarations: [
AppComponent,
TopBarComponent,
ProductListComponent,
MyComponentComponent
],
bootstrap: [ AppComponent ]

How to display an [object Object] on angular UI?

I am trying to display the response of my backend api http://localhost:3000/api/radar_life_cycle on the angular UI but somehow I get the output as [object Object] ,console.log on the response shows the correct object but not on the UI,what am I missing?any guidance on how to display the object on UI?
html
<textarea rows="6" [(ngModel)]="enteredValue"></textarea>
<hr>
<button (click)="get_radar_lifecycle_data()">Search</button>
<p>{{newPost}}</p>
component.ts
import { Component, OnInit, Injectable } from '#angular/core';
import { HttpClient } from "#angular/common/http";
import { Subject } from "rxjs";
import { map } from 'rxjs/operators';
#Component({
selector: 'app-radar-input',
templateUrl: './radar-input.component.html',
styleUrls: ['./radar-input.component.css']
})
export class RadarInputComponent {
constructor(private http: HttpClient) {}
newPost = '';
get_radar_lifecycle_data(){
this.http.get('http://localhost:3000/api/radar_life_cycle',{params:this.enteredValue}).subscribe(response => {
console.log(response);
this.newPost = response
});
}
}
response:-
{message: "Posts fetched successfully!", posts: Array(1)}
CURRENT OUTPUT:-
You need inspect your object structure by json pipe
Display your object property by ngFor because result return Array.
https://stackblitz.com/edit/angular-d17ggk
You can use the built-in JSON pipe that Angular has which is included in #angular/common and is imported with BrowserModule or CommonModule:
<textarea rows="6" [(ngModel)]="enteredValue"></textarea>
<hr>
<button (click)="get_radar_lifecycle_data()">Search</button>
<p>{{newPost | json}}</p>
For more info about the pipe, check out the JsonPipe API.
By referring {message: "Posts fetched successfully!", posts: Array(1)}!
You can use *ngFor to display the Array like:
<div *ngFor="let item of newPost?.posts">
{{ item.milestone }}
</div>
or to display properties:
{{ newPost?.message }}
Edit:
Change:
newPost = '';
to:
newPost: any;
and you already have access of object of that array so you just need to do:
{{ item.milestone }}
Working Demo

Where to find current user info inside the user JSON object?

I am trying to find out how to get certain data belonging to the current logged-in user such as full name, email, etc.
The Firefox console outputs this:
----- header.component.ts -----
this.user:
{}
authService.getUser()
Object { _isScalar: false, source: {…} }
this.authService.me()
Object { _isScalar: false, _subscribe: me() }
-------------------------------
This prints out what the authService can provide using console.log() (see the TypeScript code below).
I look through the Object returned by the authService.getUser() method and also the one returned by the this.authService.me() method, but I cannot manage to find where any of the info is located.
I noticed in the HTML code (in a part that was made by the Mean.io generator and not by me) that it references "user.fullname" to display the user's full name in the header bar, but how? And how would you access other pieces of information such as the user's email, phone number, etc?
My profile component TypeScript file looks like this:
import { Component, OnInit, Input } from '#angular/core';
import { Router } from '#angular/router';
import { AuthService } from '../auth/auth.service';
#Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.scss']
})
export class HeaderComponent implements OnInit {
#Input() user: any = {};
constructor(
private authService: AuthService,
private router: Router
) { }
ngOnInit() {
console.log("----- header.component.ts -----");
console.log("this.user:");
console.log(this.user);
console.log("-------------------------------");
}
profile(): void {
this.navigate('/profile');
}
logout(): void {
this.authService.signOut();
this.navigate('/auth/login');
}
navigate(link): void {
this.router.navigate([link]);
}
}
And my profile component HTML file looks like this:
<header >
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css?family=ZCOOL+XiaoWei" rel="stylesheet">
<mat-toolbar color="primary">
<a [routerLink]="['/']" class="logo"></a>
<a [routerLink]="['/']" class="toolbar-buttons"> Home </a>
<a class="toolbar-buttons"> Deals </a>
<a [routerLink]="['/about']" class="toolbar-buttons"> About </a>
<span class="example-spacer"></span>
<a class="links side" [routerLink]="['/auth/login']" *ngIf="!user">Login</a>
<div>
<a class="links side" *ngIf="user" [matMenuTriggerFor]="menu">
<mat-icon>account_circle</mat-icon>{{user.fullname}}
</a>
<mat-menu #menu="matMenu">
<button mat-menu-item *ngIf="user && user.isAdmin" [routerLink]="['/admin']">admin</button>
<button mat-menu-item (click)="logout()">logout</button>
<button mat-menu-item (click)="profile()">profile</button>
</mat-menu>
</div>
</mat-toolbar>
</header>
It turns out the user is not settled instantly, It waits for some ajax response, You could use ngOnChanges event and then access the user object like this
ngOnChanges(){
if(this.user && this.user.fullname){
//Do your work here
}
}

Integrating WinJS and Angular2

I'm trying to wrap a WinJS rating control in an Angular2 component. When I debug, I can see that WinJS.UI.processAll(); is being called and executed. But I don't see the rating control.
How can I make it work?
Dashboard.cshtml:
#{
ViewBag.Title = "Dashboard";
}
<my-app></my-app>
<script src="/jspm_packages/system.js"></script>
<script src="/config.js"></script>
<script>
System.import('reflect-metadata')
.then(function () {
System.import('angular2')
.then(function () {
System.import("/js/app");
});
});
</script>
app.js:
import { Component, View, bootstrap } from 'angular2';
import 'reflect-metadata';
import 'winjs';
#Component({
selector: 'my-app'
})
#View({
template: '<div data-win-control=\'WinJS.UI.Rating\' data-win-options=\'{averageRating: 3.4}\'></div>'
})
class MyAppComponent {
constructor() {
}
onInit() {
WinJS.UI.processAll();
}
}
bootstrap(MyAppComponent);
As requested by #wonderfulworld
First of all, according to Adding the Windows Library for JavaScript to your page you must add the css file to your html.
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/winjs/4.3.0/css/ui-light.min.css">
Second thing, from alpha37+ you must import and implement the lifecycle hook you're using, onInit in this case (see remove LifecycleEvent).
import { Component, View, bootstrap, OnInit} from 'angular2/angular2';
import 'reflect-metadata';
import 'winjs';
#Component({
selector: 'my-app'
})
#View({
template: '<div data-win-control=\'WinJS.UI.Rating\' data-win-options=\'{averageRating: 3.4}\'></div>'
})
class MyAppComponent implements OnInit {
onInit() {
WinJS.UI.processAll();
}
}
And that would be all. Here's the plnkr.
Glad it helped ;)

Resources