Reload a component from another component - javascript

I was trying to reload a component using the below code
reload() {
this.router.routeReuseStrategy.shouldReuseRoute = () => false;
this.router.onSameUrlNavigation = 'reload';
this.router.navigate(['/'], { relativeTo: this.route, queryParamsHandling: 'preserve' });
}
But in a service file, I was using the below block of code in a service file to get query params
constructor(
private route: ActivatedRoute,
private generalSettings: GeneralSettingsService,
private httpClient: HttpClientService,
private toastrService: ToastrService,
) {
this.route.queryParams.subscribe(params => {
this.module = params['module'];
this.env = params['env'];
console.log(this.module, this.env)
});
}
Once I reload the component, I am not able to get the query params.

Related

Global Variables undefined in ng-template

I am using a globals file to set key data needed for the application. Everything works until you use the browser refresh button. Once that is clicked, all the data I am loading from the globals.ts file comes back as undefined when the template is loaded. After the template is loaded, the promise populates the data. I need the promise data to populate before the ng-template binding.
Notice that I am trying to populate the global data by calling this.globals.init(token) from the app.component. Then in the helpful-links template I am trying to build a url based on data passed in from the parent component (myAccount.component). Oddly enough, data in the parent component also uses the globals file, and populates fine. Where did I go wrong?
-app.component
constructor(public globals: Globals){}
async ngOnInit() {
...
this.globals.init(token);
...
}
-Globals.ts
#Injectable()
export class Globals {
async init(token:string): Promise<any>{
if(token === undefined || token === '') {
token = this.oidcSecurityService.getIdToken();
}
const decoded = jwt_decode(token);
console.log(decoded, '<<<<<<<<<--------- decoded!', this.title)
this.email = decoded.email;
await this.get('getuserdata', {}).toPromise()
.then(async (res) => {
// THIS IS THE NEEDED DATA THAT COMES BACK AFTER THE BINDING. all except localstorage is undefined
localStorage.setItem('email', res['body'][0].email);
this.userRole = res['body'][0].title;
this.setUserId(res['body'][0].userid);
this.userid = res['body'][0].userid;
this.email = res['body'][0].email;
this.subscriberid = res['body'][0].fk_tk_subscriber_id;
this.isManagerRole = res['body'][0].title === 'HR Admin' ? true : false;
this.setTitle(res['body'][0].title);
this.profilePic = res['body'][0].profilephotourl;
});
}
-my7Account.component.html file
...
<app-tk-helpful-links [glob]='this.globals'></app-tk-helpful-links>
...
--helpful-links template
#Component({
selector: 'app-tk-helpful-links',
templateUrl: './tk-helpful-links.component.html',
styleUrls: ['./tk-helpful-links.component.scss']
})
export class HelpfulLinksComponent implements OnInit {
#Input() glob: Globals;
public res: {};
subscription: Subscription;
async getHelpfulLinks(): Promise<any> {
if(this.globals.userid === undefined) {
this.globals.init('');
}
return this.dataSvc.get(`gethelpfulLinks/${this.glob.userid}/${this.glob.subscriberid}`, {})
.subscribe(res => {
this.res = res['body'];
});
}
constructor(
private dataSvc: TkDataService,
public globals: Globals
) {
}
async ngOnInit() {
this.getHelpfulLinks();
}
}

I want to make a query based on the current logged in user id in Angular using firebase as my back-end

I've created a bookmarking feature which if the users clicks at the bookmark button the user's id will be save to that documents bookmark array in firebase which is working fine.
But i want to show all bookmarks by a user in the bookmark page/tab (it's a news site btw the documents have title, picture, article, bookmarks and so on kind of data).
I've got it to work manually
bookmarks$: Observable<lajmiId[]>;
bookmarksBehaviorSubject : BehaviorSubject<string|null>;
constructor(
private afs: AngularFirestore,
public authService: AuthService,
private ls: LoginService) {
this.bookmarksBehaviorSubject = new BehaviorSubject(null);
this.bookmarks$ = this.bookmarksBehaviorSubject.pipe(
switchMap(string => this.afs.collection<lajmiId>('lajmet', ref =>
ref.where('bookmarks', 'array-contains', 'manually_written_uid')).valueChanges())
);
}
Which works however when i try to pas in the uid dynamically based on the current logged in user it's not working,
var uid = this.authService.userData.uid;
this.bookmarksBehaviorSubject = new BehaviorSubject(null);
this.bookmarks$ = this.bookmarksBehaviorSubject.pipe(
switchMap(string => this.afs.collection<lajmiId>('lajmet', ref =>
ref.where('bookmarks', 'array-contains', uid)).valueChanges())
);
This gives me an error of undefined since it's trying to read the uid before the data is ready to be used since the data is asynchronous.
I've tried putting the code in the ngOnInit() block same result.
I've tried creating an observable with the uid data still same result.
i just can't seem to figure this out.
My authServise looks something like this:
import { User } from '../core/user';
export class AuthService {
userData: Observable<any>;
constructor(
public afs: AngularFirestore, // Inject Firestore service
public afAuth: AngularFireAuth, // Inject Firebase auth service
public router: Router,
public ngZone: NgZone, //ngZone service to move outside scope warning
private dialogRef: MatDialog
) {
this.afAuth.authState.subscribe(user => {
if (user) {
this.userData = user;
localStorage.setItem('user', JSON.stringify(this.userData));
JSON.parse(localStorage.getItem('user'));
}
})
}
}
My User.ts contains the User interfase.
Any help is much appreciated.
In your auth service you need to make the user as an Observable and then you can easily subsribe it on ngOnInit.
Suppose your auth.service.ts
export class AuthService{
user$:Observable<any>;
constructor(private router: Router,
private afAuth: AngularFireAuth,
private db:AngularFirestore,
) {
this.user$ = this.afAuth.authState.pipe(
switchMap(user => {
if (user) {
//here you get the logged in user cred like uid
//you can use uid to refer in your collection
return this.afs.collection<lajmiId>(`lajmet/${user.uid}`).valueChanges()
} else {
return of(null)
}
})
)
}
}
This will always give you the current logged in user and then you can easily subscribe after importing your authservice in the component you are trying to fetch.
this.authService.user$.take(1).subscribe(data=>{
//data of the user logged in
})

ERROR Error: Cannot insert a destroyed View in a ViewContainer

I have designed a page generator by configuration app and it works fine and generate components and render them on the page as good as it should.
But when i try to render a new page by new configuration, i get this error ERROR Error: Cannot insert a destroyed View in a ViewContainer! right when the generator service try to render the first component on the page after cleaning the page.
The pages configuration arrives from pageConfigService at ngOnInit in NemoContainerComponent and error appears when pageGenerator try to render the WidgetContainerComponent.
** UPDATE **
Page will be generate after changing the rout, all of the routes base component is the NemoContainerComponent and when route changes, the NemoContainerComponent destroyed and created again.
** UPDATE **
This is NemoContainerComponent:
#Component({
selector: 'nemo-container',
templateUrl: './nemo-container.component.html',
encapsulation: ViewEncapsulation.None
})
export class NemoContainerComponent {
private subscription: Subscription = new Subscription();
#ViewChild(ChildReferenceDirective) childReference: ChildReferenceDirective;
constructor(
private pageGenerator: PageGeneratorService,
private route: ActivatedRoute,
private routeService: RouteService,
private router: Router,
private storeEngine: StoreEngineService,
private pageConfigService: PageConfigService
) {
this.subscription.add(route.params.subscribe((params) => {
this.routeService.setRouteService = params;
}));
let activeRoute = router.url.split('/').join(' ');
document.body.className += ' ' + activeRoute;
}
ngOnInit() {
this.pageGenerator.containerRef = this.childReference.viewReference;
this.subscription.add(this.pageConfigService
.get(this.route.data['value'].page)
.subscribe(data => {
this.pageGenerator.renderNewPageByConfigurationFile(data.json)
}));
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
WidgetContainerComponent is here:
#Widget({
typeName: 'widget-container',
displayName: '',
type: 'parent',
settings: []
})
#Component({
selector: 'widget-container',
templateUrl: "widget-container.component.html",
encapsulation: ViewEncapsulation.None
})
export class WidgetContainerComponent {
#ViewChild(ChildReferenceDirective, { read: ViewContainerRef }) childRef;
get childReference(): ViewContainerRef {
return this.childRef;
}
private data: ObjectInterface = {};
set widgetData(value: ObjectInterface) {
for (let item in value) {
this.data[item] = value[item];
}
}
get widgetData(): ObjectInterface {
return this.data;
}
public id: string = '';
}
** UPDATE **
angular pack version: 4.4.6
** UPDATE **
thanks in advance for your helps :)

Binding data to user (firebase)

So I have created working user authentication, and a page which contains 3 inputs and a “create user” button.
The data form inputs is pushed to firebase, but I don’t think it is binded to the logged user.
here is code:
export class ProfilePage {
profileData: AngularFireObject<Profile>
profile = {} as Profile;
constructor(private afAuth: AngularFireAuth, private afDatabase: AngularFireDatabase,
public navCtrl: NavController, public navParams: NavParams) {
}
ionViewDidLoad() {
console.log('ionViewDidLoad ProfilePage');
}
createProfile() {
this.afAuth.authState.take(1).subscribe(auth => {
this.afDatabase.object(`profile/${auth.uid}`).set(this.profile)
.then(() => this.navCtrl.setRoot(MainPage));
})
}
}
the data on firebase looks like this:
With your data structure, here is the "standard" javascript code to get the data for the current user:
var userId = firebase.auth().currentUser.uid;
return firebase.database().ref('/bike-it-app/profile/' + userId).once('value').then(function(snapshot) {
var firstname = snapshot.val().firstname;
var lastname = snapshot.val().lastname;
var username = snapshot.val().username;
// ...
});
Note that here we use "once". You could alternatively use "on", depending on your requirements, see https://firebase.google.com/docs/database/web/read-and-write#listen_for_value_events

Can I save data in guard before loading page

Current routing configuration:
//...
{
path: 'foo/:id',
component: SomeComponent,
canActivate: [SomeGuard]
},
//...
Then in guard I call permission service to get access for component:
#Injectable()
export class SomeGuard implements CanActivate {
constructor(private service: Service) {
}
canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
const id = parseInt(next.params['id']);
return this.service.getPermissions(id).then(permissions => {
if (permissions.canView) {
return true;
}
return false;
});
}
}
But in the component I utilize the same permissions endpoint, which means I call it twice in a row to get to one page:
//...
constructor(private route: ActivatedRoute,
private service: Service) {
}
ngOnInit() {
this.id = parseInt(this.route.snapshot.params['id']);
this.service.getPermissions(this.id).then(permissions => {
// ...
});
}
//...
So it would be great to just save the permissions data in the route and utilize it by both guard and the component. I tried using resolve, but it turns out resolve only activates after the guards, which is no good. So how can i save permissions data?
This looks like the kind of task for a caching service. Permissions do not change often so they are the perfect candidate for caching. That way even multiple visits to the same resource would not trigger multiple HTTP requests for permission checks.
Edit: Since you need permissions to be loaded each time, you could listen for RouteNavigationStart and clear the cache. If this becomes too cumbersome to maintain in the PermissionsService you could extract the logic into a separate service.
You could something like this in the service you use to get your permissions:
// Permissions service
private permissionCache;
constructor(
router: Router,
) {
// clear cache when a route navigation starts
router.events
.filter(event => event instanceof NavigationStart)
.subscribe(event => this.permissionCache = {})
}
getPermissions(id) {
if (permissionCache[id]) {
return Observable.of(permissionCache[id]);
} else {
// get the permissions
permissionCache[id] = response;
return Observable.of(response);
}
});

Categories

Resources