Access the root TreeNode in router v.3-alpha.8 - javascript

With the first router v.3 versions, I was doing that somewhere in my code :
let lastColors: Colors;
let node = this.router.routerState._root;
do {
if(node.value.component.hasOwnProperty('__colors')) {
lastColors = (<any>node.value.component).__colors;
}
} while(node = node.children[0]);
However, the _root: TreeNode<ActivatedRoute> property of RouterState is now private in alpha 8, breaking my code. It seems that now, RouterState isn't exposing the root TreeNode anymore. What's the proper way to explore the components tree now?

Have you tried this.router.routerState.root
export class RouterState extends Tree<ActivatedRoute> {
/**
* #internal
*/
constructor(
root: TreeNode<ActivatedRoute>, public queryParams: Observable<Params>,
public fragment: Observable<string>, public snapshot: RouterStateSnapshot) {
super(root);
}
toString(): string { return this.snapshot.toString(); }
}

Well in fact that was simple, I didn't read the router's .d.ts files with enough attention:
let lastColors: Colors;
let state = this.router.routerState.snapshot;
let route = state.root;
do {
// do something with route.component
} while(route = state.children(route)[0]);
Update: #angular/router is now stable and the API changed, again. Here is the new version :
let state = this.router.routerState.snapshot;
let route = state.root;
do {
// do something with route.component
} while(route = route.children[0]);

Related

Prevent copy of class instance when importing in two different files - JavaScript?

I have a class like this: Code Sandbox
(In the sandbox, I have imported file1 so that that part of code gets executed first and then trying to access the same using file2 however it returns undefined)
import crypto from 'crypto';
const deleteMillis = 3600 * 1000;
class Security {
activeSessions: Record<string, { ua: string }>;
constructor() {
this.activeSessions = {};
}
getSession(session: string, ua: string): { ua: string } | undefined {
const currentSession = this.activeSessions[session];
console.log(this.activeSessions, this.activeSessions[session], session);
if (!currentSession) return;
if (ua !== currentSession.ua) return;
return currentSession;
}
addSession(ua: string): string {
const session = crypto.randomUUID();
this.activeSessions[session] = {
ua
};
setTimeout(() => {
this.removeSession(session);
}, deleteMillis);
return session;
}
removeSession(session: string) {
delete this.activeSessions[session];
}
}
const security = new Security();
export default security;
I want to use security instance of this class into multiple es module files. Let's say file1.js and file2.js.
Now the problem is that when i do an import:
import security from "#/security"; // file-1
import security from "#/security"; // file-2
The problem with the above is that the data doesn't remain synced in both the files and they operate independently.
these two files create two different instances however I wanted to use one instance in both the files. How can I achieve the same? Do I need to create a third file or what exactly should be the approach?
As suggested in the answer, I tried this:
class Security {
activeSessions: Record<string, { ua: string }>;
private static instance: Security;
constructor() {
this.activeSessions = {};
}
getSession(session: string, ua: string): { ua: string } | undefined {
const currentSession = this.activeSessions[session];
console.log(this.activeSessions, this.activeSessions[session], session);
if (!currentSession) return;
if (ua !== currentSession.ua) return;
return currentSession;
}
addSession(ua: string): string {
const session = crypto.randomUUID();
this.activeSessions[session] = {
ua
};
setTimeout(() => {
this.removeSession(session);
}, deleteMillis);
return session;
}
removeSession(session: string) {
delete this.activeSessions[session];
}
static getInstance(): Security {
if (!Security.instance) {
Security.instance = new Security();
}
console.log('Security instance', Security.instance);
return Security.instance;
}
}
const security = Security.getInstance();
export default security;
However this also fails to preserve the instance.
Here's an approach, we define a static method getInstance in the Security class and call it to get Security instance in other files
class Security {
private static instance: Security;
// other methods and variables
static getInstance(): Security {
if (!Security.instance) {
Security.instance = new Security();
}
return Security.instance;
}
}
export default Security;
Usage example
let securityInstance = Security.getInstance();
securityInstance.getSession();
This is called the Singleton design pattern, you can read more about it here Singleton design pattern
The shown code works for me (the session object is the same for both files). It is, however, not clear what you want to achieve with the code.
In file1.js you have security.addSession("abc", "deg") in file2.js you have security.getSession("abc", "def"). (deg vs def).
After calling security.addSession("abc", "deg") the contents of this.activeSessions['abc'] is: {ua : "deg"}.
When you call security.getSession("abc", "def") you have the test if (ua !== currentSession.ua) return; which compares ua which is def with currentSession.ua which is deg and that is not equal, so you return undefined.

How to create Class dynamically in a proper way in Typescript?

I am trying to migrate my app to typescript. I have kind of a base class that is my base library object. My classes created dependent on the base class. Below is a glimpse of my problem.
Below code works but autocomplete doesn't work. Couldn't figure out what should be defined for the type of Model.
const map = new WeakMap();
function weakRef<T>(context: T): T {
// #ts-ignore
if (!map.has(context)) { map.set(context, {}); }
// #ts-ignore
return map.get(context);
}
function getModel(provider: Provider) {
return class Model {
getSomething(key: string) {
return weakRef(provider).configuration(key);
}
};
}
class Provider {
configuration: (key: string) => string;
constructor() {
weakRef(this).configuration = (key: string) => {
return key;
};
weakRef(this).Model = getModel(this);
}
get Model(): any {
return weakRef(this).Model;
}
set Model(model: any) {
weakRef(this).Model = model;
}
}
const provider = new Provider();
const obj = new (provider.Model)();
console.log(obj.getSomething('test')); // This works, but autocomplete doesn't
I don't want to pass provider to the constructor in base model.
Any help is appreciated, thanks.
You can get the return type of a function type with ReturnType<T>.
In this case, ReturnType<typeof getModel> should do the trick.
You can also fix the //#ts-ignore lines by constraining T to be an object type.
const map = new WeakMap();
function weakRef<T extends object>(context: T): T {
if (!map.has(context)) { map.set(context, {}); }
return map.get(context);
}
That said, I think this architecture is unnecessarily complicated. Why not just use this instead of a value tied to this?

set and get data from service angular 5

I am using angular 5
my scenario is from one component im setting the data in service and from another component i'm getting that data|
Component- 1:
makeUser(row){
this.agentsService.setSelectedAgentData(row); // setting the data (row) in agentsService.
const mrf = this.modalService.open(MakeUserComponent);
}
Service:
declaring the varible in class.
public selectedData:any = {};
setter and getter methods are as below
setSelectedAgentData(selectedTableRowData){
this.selectedData = selectedTableRowData;
}
getSelectedAgentData(){
return this.selectedData;
}
Component - 2:
ngOnInit() {
this.userDetails = this.agentsService.getSelectedAgentData();
this.roles = this.agentsService.getRolesList();
}
Here the selectedData value is an empty object when I call the method this.agentsService.getSelectedAgentData() from component -2
Any help would be appreciated.
You can use Subject (rxjs library) for this purpose. So Subject can generate data on the one hand. And on the other hand, you can subscribe to changes in any place.
You service would look like this:
#Injectable()
export class YourService {
public selectedData: Subject<any>;
constructor() {
this.selectedData = new Subject();
}
generateSelectedAgentData(row: string) {
this.selectedData.next(row);
}
}
In your first Component:
makeUser(row){
this.agentsService.generateSelectedAgentData(row);
const mrf = this.modalService.open(MakeUserComponent);
}
In your second Component:
constructor(private ys: YourService){
this.ys.selectedData.subscribe(
data => {
console.log(data);
this.userDetails = data;
});
}

Some of data comes null in java spring and react js

I want to save all data by using react.js and Java Spring. I sent data with REST, but one of data class comes null to collections in MongoDB. I controlled whether or not all data types are equal. I cannot see and solve my errors. I share both Spring data type definitions and react.js definitions.
BildirimGrubu comes null
Java Spring:
package tr.com.innova.watcher;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import java.util.List;
/**
* Created by SBK on 03.09.2016.
*/
#Data
#JsonInclude(JsonInclude.Include.NON_NULL)
public class BildirimGrubu {
String emailMetni;
String smsMetni;
List<Alici> alici;
enum EmailEkTipi{
HICBIRI, EXCEL, PDF
};
EmailEkTipi ekTip;
enum BildirimYontemi{
EMAIL, SMS, HEPSI, HICBIRI
};
BildirimYontemi bildirimYont;
int mesajSayisi;
int mesajKarakter;
}
React.js:
import * as React from "react";
export enum EmailEkTipi{
HICBIRI, EXCEL, PDF
}
export enum BildirimYontemi {
EMAIL, SMS, HEPSI, HICBIRI
}
export enum TetikleyiciTipi{
CRON, SIMPLE
}
export class Alici {
label:string;
value:string;
constructor(name:string,
val:string) {
this.label = name;
this.value = val;
}
}
export class BildirimGrubu {
emailMetni:string;
smsMetni:string;
alici:Array<Alici>;
ekTip:EmailEkTipi;
bildirimYont:BildirimYontemi;
mesajSayisi:number;
mesajKarakter:number;
constructor(emailMetni:string, smsMetni:string, alici:Array<Alici>, ekTip:EmailEkTipi, bildirimYont:BildirimYontemi, mesajSayisi:number,mesajKarakter:number) {
this.emailMetni = emailMetni;
this.smsMetni = smsMetni;
this.alici = alici;
this.ekTip = ekTip;
this.bildirimYont = bildirimYont;
this.mesajSayisi = mesajSayisi;
this.mesajKarakter = mesajKarakter;
}
}
export class Tetikleyici {
tetikleyiciAdi:string;
aciklama:string;
tetikleyiciIcerik:TetikleyiciTipi;
durum:boolean;
bildirimGrubu:BildirimGrubu;
tip:TetikleyiciTipi;
bildirimEkle:boolean;
constructor(tetikleyiciAdi:string, aciklama:string, tetikleyiciIcerik:TetikleyiciTipi, durum:boolean, bildirimGrubu:BildirimGrubu, tip:TetikleyiciTipi, bildirimEkle:boolean) {
this.tetikleyiciAdi = tetikleyiciAdi;
this.aciklama = aciklama;
this.tetikleyiciIcerik = tetikleyiciIcerik;
this.durum = durum;
this.bildirimGrubu = bildirimGrubu;
this.tip = tip;
this.bildirimEkle = bildirimEkle;
}
}
export class Sorgu {
_id:string;
userName:string;
anaSorgu:string;
aciklama:string;
altSorguList:Array<string>;
tetikleyici:Tetikleyici;
sName:string;
constructor(id:string, username:string, anaSorgu:string, aciklama:string, altSorguList:Array<string>, tetikleyici:Tetikleyici, sName:string) {
this._id = id;
this.userName = username;
this.anaSorgu = anaSorgu;
this.aciklama = aciklama;
this.altSorguList = altSorguList;
this.tetikleyici = tetikleyici;
this.sName=sName;
}
}
Data to send DB with REST:
[new Sorgu("1","Hi","select","select sorgusu",["hi","hoy"],new Tetikleyici("tetikle", "hello", TetikleyiciTipi.CRON, true, new BildirimGrubu("a", "a", [["ali","bak"]], EmailEkTipi.EXCEL, BildirimYontemi.HEPSI, 1, 1), TetikleyiciTipi.CRON, true),"sorgu_8")]
I hope to transferred you my problems. Thank you for helps.
While again created classes, I realized that I forgot to add public. Therefore, java cannot access the objects of the class. Don't forget public. :)
Even so, thank you!

Angular2 call observer next from child object

I'll try to explain this as best I can.
I have a service that contains an observable class that performs tasks to update itself. That observable class needs to be pushed out to the app using the observer located in the service. How can I call that observer from the child without creating some sort of dependency loop?
Here is a rough example:
class MyService {
subClass$: Observable<SubClass>;
_subClassObserver: Observer<SubClass>;
constructor(private _subClassStore: SubClass){
this.subClass$ = new Observable(observer => {
this._subClassObserver = observer
}).share();
}
pushData(){
this._subClassObserver.next(this._subClassStore)
}
}
class SubClass {
displayData: string;
displayData2: number;
constructor(){
socket.on('setData', function(obj){
this.displayData = obj.dd1;
this.displayData2 = obj.dd2;
//How to call pushData() in MyService from here to push data to app?
}
}
}
_subClassStore is updating through a stream coming in from socket.io. How do I let MyService know when the SubClass data changes so that it can push it using _subClassObserver.next(_subClassStore)?
EDIT:
I added more details to the example above to show how they are related and utilized.
SubClass is just a listener for a stream of data coming from socket.io and saving the information into the class. It starts listening when MyService is constructed.
The goal of MyService is to provide a bunch these sub classes that can be subscribed to across the app. Each one would allow access to a different data stream and the associated data, but all would be contained within a single service.
The question is how to call the pushData() function in the parent so that it keeps the stream updated for subscribers in the app.
Edit 2:
This might help. below is how it would be written as a service without the sub class. The only reason why I'm not doing this is because there are a substantial amount of these listeners being stored to Observables and abstracting them out into classes makes the information much easier to manage but pushing it to the app is what I can't figure out:
class MyService {
class1$: Observable<DataStream>;
_class1Observer: Observer<DataStream>;
_class1Store: DataStream;
constructor(){
this._class1store = {displayData: 'hello', displayData2: 0};
this.class1$ = new Observable(observer => {
this._class1Observer = observer
}).share();
socket.on('setData', function(obj){
this._class1Store.displayData = obj.dd1;
this._class1Store.displayData2 = obj.dd2;
this._class1Observer.next(this._class1Store)
}
}
interface DataStream = {
displayData: string;
displayData2: number;
}
Instead of function(obj) use ()=> otherwise this won't ponit to the MyService instance.
constructor(){
socket.on('setData', (obj) =>{
this.displayData = obj.dd1;
this.displayData2 = obj.dd2;
//How to call pushData() in MyService from here to push data to app?
}
}
I'm not sure but I think socket is prone to run outside Angulars zone.
Try also
constructor(zone:NgZone){
socket.on('setData', (obj) =>{
zone.run(() => {
this.displayData = obj.dd1;
this.displayData2 = obj.dd2;
//How to call pushData() in MyService from here to push data to app?
});
}
}
To be able to call a method in MyService from SubClass, SubClass needs a reference to MyService
class MyService {
subClass$: Observable<SubClass>;
_subClassObserver: Observer<SubClass>;
constructor(private _subClassStore: SubClass){
_subClassStore.myService = this;
this.subClass$ = new Observable(observer => {
this._subClassObserver = observer
}).share();
}
pushData(){
this._subClassObserver.next(this._subClassStore)
}
}
class SubClass {
displayData: string;
displayData2: number;
myService:MyService;
constructor(zone:NgZone){
socket.on('setData', (obj) =>{
zone.run(() => {
this.displayData = obj.dd1;
this.displayData2 = obj.dd2;
this.myService.pushData();
});
}
}
}

Categories