How to send array in router navigate? - javascript

Searched for a solution in other questions but nothing helped me..
I wish to redirect to url like,
this.router.navigateByUrl('/products');
In which i need to pass the array and need to get it it in the component which has the active link products using skip location change without showing anything in url.
Array will be like,
products = [{"id":1,"name":"Product One","id":2,"name":"Product Three","id":3,"name":"Product Six"}]
I need to pass this entire array in router link and need to retrieve it in another component (products) active link using skipLocation Change true..
Tried with sharedService but i am getting issue of data loading at right point of time and hence i decided to use via router link..
If this is not a good approach, kindly suggest other alternative without using sharedservice..

You can use Angular Services for a large data.
import { Injectable } from '#angular/core';
import { Observable } from 'rxjs';
import { Subject } from 'rxjs/Subject';
#Injectable()
export class ExampleService {
private subject = new Subject<any>();
updateRouteData(data) {
this.subject.next(data);
}
routeData(): Observable<any> {
return this.subject.asObservable();
}
}
In your components;
For set route data;
import { ExampleService } from '/example.service'
export class ComponentOne{
constructor(private exampleService:ExampleService){
this.exampleService.updateRouteData(data)
}
You can pass data like;
import { ExampleService } from '/example.service'
export class ComponentTwo{
constructor(private exampleService:ExampleService){
this.exampleService.routeData().subscribe(data => {
console.log(data)
})
}

Related

Updating Angular DOM immediately after editing data and retrieving from the database

Am working on a Single page Application built using Angular 8 on the frontend and Laravel on the backend. It is a CRUD application, on the delete functionality, it is working well by deleting the user of the specific id on the database. After the user of the specific id is deleted, am fetching all the products from the database but I want to update the data on the U.I afresh with the new data (excluding the deleted resource).
Kindly assist?
Show.component.ts file
import { Component, OnInit , ViewChild, ElementRef} from '#angular/core';
import { SharedService } from 'src/app/Services/shared.service';
import { AuthService } from 'src/app/Services/auth.service';
import { Router } from '#angular/router';
import { Observable } from 'rxjs';
import { SnotifyService } from 'ng-snotify';
#Component({
selector: 'app-show',
templateUrl: './show.component.html',
styleUrls: ['./show.component.css']
})
export class ShowComponent implements OnInit {
public userData : any[];
public error = null;
constructor(
private Shared : SharedService,
private Auth:AuthService,
private router: Router,
private Notify:SnotifyService
) { }
//Update the data when the DOM loads
ngOnInit() {
this.Shared.checkAll$.subscribe(message => this.userData = message);
}
//Method called when the delete button is triggered from the html
//Inside it we submit the data to the backend via a service and get
//the response
deleteUser(id:number){
return this.Auth.delete(id).subscribe(
data => this.handleDeleteResponse(data),
error => this.handleDeleteError(error)
);
}
//data below contains data from the backend after successful deletion
handleDeleteResponse(data:any){
this.Notify.success(`Successfully Deleted in our records`, {timeout:4000});
}
handleDeleteError(error:any){
console.log(error);
}
}
In you’re handleDeleteResponse method, there is a data if the data is the userData this.userData = data or it’s simple delete the user id from the array in you’re Js in the subscription of your delete method.
Like:
this.userData = this.userData.filter(user => user.id !== idToDelete )
Method 1:
Define a Subject in your service and subscribe to that subject in the service to receive the data. In the component, change the lifecycle hook to 'onChanges'. As soon as the data in the Subject is received/updated (with the deleted records) ngChanges shall reflect it in the DOM.
Method 2:
Track the records on the front-end in the form of list and when the service gives the response of delete as success then delete that very record in the list using ID or any other unique identifier. In this case you need not to populate all the records again.
export class MyComponent implements OnInit, OnChanges {
ngOnChanges() {
// code here
}
ngOnInit() {
// code here
}
}

NodeJS, Angular 2 | Executing method on Observable next

I'm currently getting started with Angular 2 and got stuck on something probably pretty simple:
I have a shared service chatMessageService.ts:
import { Injectable } from '#angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
#Injectable()
export class ChatMessageService {
private messageList = new BehaviorSubject<string>("");
currentMessage = this.messageList.asObservable();
constructor() {
}
public addMessage(msg:string) {
this.messageList.next(msg) }
}
The service is imported by two components, one that calls it's addMessage function to add the message to the Observable and then my chatComponent.ts looks like this (shortened fpr convinience):
import { Component } from '#angular/core';
import { Message } from './message';
import { ChatMessageService } from './chatMessage.service';
#Component({
selector: 'app-chat',
templateUrl: './chat.component.html',
styleUrls: ['./chat.component.css']
})
export class ChatComponent {
conversation: Message[] = [];
//.....
constructor(private chatMessageService: ChatMessageService) { }
addUserMessage(message) {
this.conversation.push({
content: message
});
}
ngOnInit() {
this.chatMessageService.currentMessage.subscribe(message => {this.addUserMessage(message);} )
}
}
My crisis arises at that last subscripion part. When I replace
{this.addUserMessage(message);}
with
{console.log(message)}
the message is printed out perfectly fine. If I call the addUserMessage()-method manually it works just fine. But when I call the method right there, with the message as argument, nothing happens. The method isn't even executed?
Thankful for your insights!
It looks like you need some buffering in the service.
Instead of BehaviorSubject, try
private messageList = new ReplaySubject<string>(10);
See working example: Plunker

cannot display array sent from one component to other in angular2

SERVICE--
import {Injectable} from '#angular/core';
import {UserData} from '../user-data/user-data.component';
#Injectable()
export class UserDataService {
constructor(){}
userdata:UserData[];
getData(){
console.log('service',this.userdata);
return this.userdata;
}
setData(user:any){
this.userdata=user;
console.log(this.userdata);
}
}
USER-DATA-class ---
export class UserData {
firstname: string;
middlename: string;
lastname: string;
email: string;
contact: number;
}
Component1 --
import { Component,OnInit,OnDestroy } from '#angular/core';
import { UserData } from '../../user-data/user-data.component';
import { ViewEditUser } from '../../view-edit-user/view-edit-user.component';
import {UserDataService} from '../../user-data-service/user-data-service.service';
#Component({
selector: 'form-page',
templateUrl: `app/add-user-sidebar/user-form/form.component.html`,
providers:[UserDataService]
})
export class Form implements OnInit,OnDestroy {
userdetail:UserData;
constructor(private service:UserDataService){
}
addUser(first:string,middle:string,last:string,emailid:string,contactno:number){
this.userdetail=({firstname:first,middlename:middle,lastname:last,email:emailid,contact:contactno})
console.log(this.userdetail);
this.service.setData(this.userdetail);
}
ngOnInit(){
}
ngOnDestroy(){
}
}
Component2--
import { Component,Input, OnInit } from '#angular/core';
import { Form } from '../add-user-sidebar/user-form/form.component';
import {UserData} from '../user-data/user-data.component';
import { WelcomePage } from '../welcome-page/welcome-page.component';
import {UserDataService} from '../user-data-service/user-data-service.service';
#Component({
selector:'view-edit',
templateUrl: 'app/view-edit-user/view-edit-user.component.html',
providers: [UserDataService]
})
export class ViewEditUser implements OnInit {
arraydata:any;
constructor(private service:UserDataService){}
// arraydata:any;
printarray(){
console.log(this.arraydata);
}
ngOnInit()
{
this.arraydata=this.service.getData();
console.log("hhghdfghdf",this.arraydata);
}
}
I am new to angular2, I have two components in my module, one component is a form where user inputs data, that data is then sent to a service, when I console.log it then I can see the data in service. but when I try to access that array from the second component then I can't access the data what to do?
If you provide the service on each component, you can't use it for communication, because each component will get a different service instance.
If one component is a parent (ancestor) of the other component, only provide it on the parent component.
Otherwise provide it on a component that is a parent (anjestor) of both or provide it only in #NgModule() to make the service global.
You also need to be aware that it's possible that one component reads, before the other set the value, depending on where you set the value and in what order the components are created.
Using a BehaviorSubject usually avoids this pitfall, because this way it doesn't matter which component is created first or if one component tries to read, while the other hasn't set the value yet.
For shareing between to Angular instances see also How to share service between two modules - #NgModule in angular2?
You nee to use observables to pass data between components.
In your service create a Subject type variable and in the your first component do a .next to pass data to the service and in your 2nd component, subscribe to the service veriable and it will get you the data.
You are not getting the data because of the async behavior of JavaScript which will be handled by observables

Global function available through all app Angular2

I have a PermissionService, which provide user roles. At the server-side data will not be uploaded if the user is not corresponds on role. The back-end is written with asp.net web api, which will use attributes to secure data. On upload page will be static upload user roles, the idea is just to show or hide elements on page which depending from user role.
The PermissionsService check avaiable role in its array. There are methods like isSeller(), isManager(). And all what i want is to provide accessibility from each view. For now i have this implementation.
permission.service
import { Injectable } from "#angular/core";
export enum Roles {
Admin,
Manager,
Moderator,
Seller
}
interface IPermissionDictionary {
[key: string]: boolean;
}
#Injectable()
export class PermissionService {
private permissions: IPermissionDictionary = {};
public constructor() {
this.emitPermissions();
}
private emitPermissions(): void {
let selector = document.querySelectorAll("#roles > span");
let availableRoles = Array.from(selector).map(element => element.textContent);
for (let role in Roles) {
if (!/^\d+$/.test(role)) { // for strings types in Roles
this.permissions[role] = availableRoles.indexOf(role) > -1;
}
}
}
public isInRole(role: string): boolean {
return this.permissions[role];
}
public isAdmin() {
return this.isInRole(Roles[Roles.Admin]);
}
public isSeller() {
return this.isInRole(Roles[Roles.Seller]);
}
public isManager() {
return this.isInRole(Roles[Roles.Manager]);
}
public isModerator() {
return this.isInRole(Roles[Roles.Moderator]);
}
}
app.component
import { Component } from "#angular/core";
import { ROUTER_DIRECTIVES } from "#angular/router";
import { PermissionService } from "./share/permission.service";
import { HomeComponent } from "./home/home.component";
import { OrderComponent } from "./order/order.component";
#Component({
selector: "admin-panel",
templateUrl: "../app/app.template.html",
directives: [ROUTER_DIRECTIVES],
precompile: [HomeComponent, OrderComponent]
})
export class AppComponent {
constructor(private permissionService: PermissionService) {
}
}
main.ts
import { bootstrap } from "#angular/platform-browser-dynamic";
import { AppComponent } from "./app.component";
import { APP_ROUTES_PROVIDER } from "./app.routes";
import { HTTP_PROVIDERS } from '#angular/http';
import { PermissionService } from "./share/permission.service";
bootstrap(AppComponent, [APP_ROUTES_PROVIDER, HTTP_PROVIDERS, PermissionService]);
For now to access the method of PermissionService need to inject it in component constructor. And in template is is use like
<div *ngIf="permissionService.isAdmin()">will show if you are admin</div>
But every time to inject my service in each component where i want to use it seems for me strange. And i just want to get access it from every part of my app like:
<div *ngIf="isAdmin()">will show if you are admin</div>
I think the person who asked this question has another version of Angular2 (perhaps a pre-release?), but in the latest version if you need to export a service for all the app you do it in the following way.
First, in your main.ts you must have a class that you bootstrap, like this:
platformBrowserDynamic().bootstrapModule(AppModule);
In this class "AppModule" (or whatever it is in your case), you should be able to add a global service provider in this way:
...
import {GlobalService} from './global-service.service'
#NgModule({
...
providers: [MyGlobalService],
...
})
export class AppModule{ ...}
In this way MyGlobalService is available for all other components.
Hopefully this will be useful to someone :).
Some option could be to create top level super class with the permission methods and then just subclass in view .ts. Not sure if this suits you as you still need to import super class into your components and extend it. It can also violate the "is-a".

angular 2 subscribe shareService working twice or several times

I have a ShareService in angular 2,
******************************shareService*************************
import { BehaviorSubject , Subject} from 'rxjs/Rx';
import { Injectable } from '#angular/core';
#Injectable()
export class shareService {
isLogin$:BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
CheckUser = this.isLogin$.asObservable();
public isLogin (bool){
this.isLogin$.next(bool);
}
}
and its my another component and subscibe the CheckUser;
***********************another Component*******************************
_shareService.CheckUser.subscribe((val) =>{
*********all of this scope execute for several times just i have one another component and one next function*******
this.isLogin = val;
alert(val);
if(this.isLogin){
console.log("req req req");
this.MyBasket();
}
else if(this.ext.CheckLocalStorage("ShopItems")){
this.ShopItems = JSON.parse(localStorage.getItem("ShopItems"));
setTimeout(() => {
_shareService.sendShopItems(this.ShopItems);
},100);
}
});
my problem is i execute once this.isLogin$.next(bool) but subscribe function execute twice or several times !!!! my basket function is an xhr request this means when user loged in i get the several request to server!!!i cant fix it...i dont know this problem is for angular 2 or not,Anyone have this problem??
last a few days i Involved in this problem!
The problem is that your shareService is getting multiple instances.
One of the solutions is forcing the service to be a singleton.
Something like this should work:
import { provide, Injectable } from '#angular/core';
#Injectable()
export class shareService {
private static instance: shareService = null;
// Return the instance of the service
public static getInstance(/*Constructor args*/): shareService {
if (shareService.instance === null) {
shareService.instance = new shareService(/*Constructor args*/);
}
return shareService.instance;
}
constructor(/*Constructor args*/) {}
}
export const SHARE_SERVICE_PROVIDER = [
provide(shareService, {
deps: [/*Constructor args dependencies*/],
useFactory: (/*Constructor args*/): shareService => {
return shareService.getInstance(/*Constructor args*/);
}
})
];
Everything that is required on your current constructor should be placed where it says constructor args
Now on your components you use the service like this:
#Component({
providers: [SHARE_SERVICE_PROVIDER]
})
And then you can call it like you usually do.
Another solution would be injecting your current service on the main component of the app. See here for more info.
The problem is that the service is singleton and the component subscribe to it each time it created or (I don't see the full code) at the point the
_shareService.CheckUser.subscribe
is placed , so CheckUser should be a method that returns an Observable . if you have plunkr I can edit it .
Another semantic problem is that the observable should end with $ and not the BehaviorSubject.

Categories