How should I pass data from my service to snack bar component? - angular-material

I have a snackbar component which I have created like this!
import {Component, ViewEncapsulation, OnInit, OnDestroy} from '#angular/core';
import {
MatSnackBar,
MatSnackBarConfig,
MatSnackBarHorizontalPosition,
MatSnackBarVerticalPosition,
} from '#angular/material';
import { Subscription } from 'rxjs';
import { AuthenticationService } from "../../services/authentication.service";
#Component({
selector: 'snack-message',
templateUrl: './messages.component.html',
styleUrls: [ './mesaages.component.scss' ],
encapsulation: ViewEncapsulation.None
})
export class SnackBarMessages implements OnInit, OnDestroy {
action: boolean = true;
setAutoHide: boolean = true;
autoHide: number = 2000;
horizontalPosition: MatSnackBarHorizontalPosition = 'center';
verticalPosition: MatSnackBarVerticalPosition = 'bottom';
private showMessageSub: Subscription;
messageData: object;
addExtraClass: boolean = false;
constructor(public snackBar: MatSnackBar, public authenticationService: AuthenticationService) {
}
ngOnInit() {
this.messageData = this.authenticationService.getMessageData();
this.showMessageSub = this.authenticationService.getMessageListener()
.subscribe(data => {
this.messageData = data;
});
this.openMessageSnackBar(this.messageData);
}
openMessageSnackBar(data) {
let config = new MatSnackBarConfig();
config.verticalPosition = this.verticalPosition;
config.horizontalPosition = this.horizontalPosition;
config.duration = this.setAutoHide ? this.autoHide : 0;
this.snackBar.open(data.message, data.action, config);
}
ngOnDestroy() {
if (this.showMessageSub) {
this.showMessageSub.unsubscribe();
}
}
}
I have added subject and i have created a subscription which listens to the messageListener in my Authentication Service. Then i call next with my subjectListener with the data I want to pass. I am not getting any call on my component. I don't understand why ? This is my Service!
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Subject } from 'rxjs';
import { Router, ActivatedRoute } from '../../../node_modules/#angular/router';
#Injectable({
providedIn: 'root'
})
export class AuthenticationService {
private mesageListener = new Subject<object>();
private messageData: object;
getMessageListener() {
return this.mesageListener.asObservable();
}
getMessageData() {
return this.messageData;
}
createUser(email: string, password: string) {
const userData: AuthModel = {
email: email,
password: password
}
const requestPath = this.getModes()[`${this.navigatedFrom}`];
this.http.post(`http://localhost:3000/api/${requestPath}/signup`,userData)
.subscribe(response => {
this.messageData = {
message: 'Sign Up Successful. Please Login now!',
action: 'Ok! Got it.'
}
this.mesageListener.next(this.messageData);
});
}
}

Try to use new BehaviorSubject<object>(null); for mesageListener .
you can see more details on Subject and BehavoiurSubject here : angular2-difference-between-a-behavior-subject-and-an-observable/
In Component subscribe to the value of Observable. It should work.

Related

Use NgRx/effects for material autocomplete

I'm trying to use NgRx/effects for my material autocompleted in angular 8.
I have created store, action, effects and reducers but I'm not getting the state after successfully calling the api. The api is returning the correct value.
Action file
import { Action } from '#ngrx/store';
import {IProviderSearchObject} from '../../models/provider.type';
export enum ProviderSearchActionTypes {
SearchProvidersRequest = '[SEARCH_PROVIDER] REQUEST',
SearchProvidersSuccess = '[SEARCH_PROVIDER] SUCCESS',
SearchProvidersFail = '[SEARCH_PROVIDER] FAILED'
}
export class ProviderSearchAction implements Action {
type: string;
payload: {
isRequesting: boolean,
providers: Array<IProviderSearchObject>,
error: boolean,
searchPhrase: string
};
}
export class SearchProvidersRequest implements Action {
readonly type = ProviderSearchActionTypes.SearchProvidersRequest;
constructor(readonly payload: {isRequesting: boolean, searchPhrase: string}) {}
}
export class SearchProvidersSuccess implements Action {
readonly type = ProviderSearchActionTypes.SearchProvidersSuccess;
constructor(readonly payload: {isRequesting: boolean, providers: Array<IProviderSearchObject>}) {}
}
export class SearchProvidersFail implements Action {
readonly type = ProviderSearchActionTypes.SearchProvidersFail;
constructor(readonly payload: {error: boolean}) {}
}
export type ProviderSearchActions = SearchProvidersRequest | SearchProvidersSuccess | SearchProvidersFail;
reducer file
import {IProviderSearchObject} from '../../models/provider.type';
import {ProviderSearchAction, ProviderSearchActionTypes} from '../actions/provider-search.action';
export interface IProviderSearchState {
isRequesting: boolean;
providers: Array<IProviderSearchObject> | null;
error: boolean;
}
const initialProviderSearchState: IProviderSearchState = {
isRequesting: false,
providers: null,
error: false
};
export function providerSearchReducer(state: IProviderSearchState = initialProviderSearchState, action: ProviderSearchAction): IProviderSearchState {
console.log(action, state);
switch (action.type) {
case ProviderSearchActionTypes.SearchProvidersRequest:
return {
isRequesting: true,
providers: null,
error: false
};
case ProviderSearchActionTypes.SearchProvidersSuccess:
return {
isRequesting: false,
providers: action.payload.providers,
error: false
};
case ProviderSearchActionTypes.SearchProvidersFail:
return {
isRequesting: false,
providers: null,
error: true
}
default:
return state;
}
}
import {ActionReducerMap, MetaReducer} from '#ngrx/store';
import {IProviderSearchState, providerSearchReducer} from './provider-search.reducer';
export interface IAppState {
providerSearch: IProviderSearchState;
}
export const reducers: ActionReducerMap<IAppState> = {
providerSearch: providerSearchReducer
};
export const selectProviderSearch = (state: IAppState) => state.providerSearch.providers;
export const metaReducers: MetaReducer<any>[] = [];
Effects file
import {Actions, Effect, ofType} from '#ngrx/effects';
import {IAppState} from '../reducers';
import {ProviderSearchService} from '../../modules/provider-search/services/provider-search.service';
import {Store} from '#ngrx/store';
import {ProviderSearchActionTypes, SearchProvidersSuccess, SearchProvidersFail} from '../actions/provider-search.action';
import {catchError, map, switchMap} from 'rxjs/operators';
import { of } from 'rxjs';
import {IProviderSearchObject} from '../../models/provider.type';
import {Injectable} from '#angular/core';
#Injectable()
export class ProviderSearchEffects {
constructor(private actions$: Actions,
private store: Store<IAppState>,
private providerSearchService: ProviderSearchService) {}
#Effect()
searchProvider$ = this.actions$
.pipe(
ofType<any>(ProviderSearchActionTypes.SearchProvidersRequest),
map(action => action.payload),
switchMap((action) => {
return this.providerSearchService.getProviderByPhrase(action.searchPhrase).pipe(
map((data: Array<IProviderSearchObject>) => new SearchProvidersSuccess({isRequesting: false, providers: data})),
catchError(error => of(new SearchProvidersFail({error: true})))
);
})
);
}
import { ProviderSearchEffects } from './provider-search.effects';
export const effects: Array<any> = [ProviderSearchEffects];
Service file
import { Injectable } from '#angular/core';
import {HttpClient} from '#angular/common/http';
import {environment} from './../../../../environments/environment';
import { Store } from '#ngrx/store';
import * as ProviderSearchAction from '../../../store/actions/provider-search.action';
import {IAppState} from '../../../store/reducers';
import {Observable} from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class ProviderSearchService {
constructor(
private http: HttpClient,
private store: Store<IAppState>
) { }
public getProviderByPhrase = (searchPhrase: string): Observable<any> => {
return this.http.get('https://mydummyapi.com?q=' + searchPhrase);
}
public searchProviderByTermSearch = (searchPhrase: string): any => {
return this.store.dispatch(new ProviderSearchAction.SearchProvidersRequest({isRequesting: true, searchPhrase}));
}
}
Component file
ngOnInit() {
this.providerSearchControl.valueChanges
.pipe(
debounceTime(500),
tap(() => {
this.isLoading = true;
}),
switchMap((value: string) => this.providerSearchService.searchProviderByTermSearch(value))
.pipe(
finalize(() => {
this.isLoading = false;
})
)
)
)
.subscribe((data: Array<IProviderSearchObject>) => {
console.log(data);
if (data && data.length > 0) {
this.providerSearchResult = data;
}
});
}
When the user start typing the autocomplete field then searchProviderByTermSearch method is invoked inside the service file and that dispatches the action.
But after [SEARCH_PROVIDER] SUCCESS call is made nothing is happening.
A store.dispatch is a void, it does not return a value.
The data from the subscribe code, is not an Array<IProviderSearchObject>.
Your flow should be:
dispatch fetch
call service in effects
dispatch fetch success/failure
update state via reducer
read data with selectors
update component
https://ngrx.io/guide/store#diagram

list is updated but values are not reflect in the HTML in angular7?

I have created a website in angular7 in which we have fire the function from 1 component to another component function is fire properly but value are not reflect in the html below we have shared updated fiddle:
//Component1.
import { Component, OnInit } from '#angular/core';
import { Router,NavigationExtras } from "#angular/router";
import {UserService} from "../../service/user.service";
import { FormGroup, FormBuilder, FormControl, FormGroupDirective, NgForm, Validators } from '#angular/forms';
import { DashboardComponent } from '../../dashboard/dashboard.component';
declare var $: any;
#Component({
selector: 'app-innerheader',
templateUrl: './innerheader.component.html',
styleUrls: ['./innerheader.component.css'],
providers : [DashboardComponent]
})
export class InnerheaderComponent implements OnInit {
//declare global varible here....
private loggedUserObject : any = {};
private userImageUrl : any;
constructor(
private router : Router,
private service : UserService,
private formBuilder: FormBuilder,
private dashboard : DashboardComponent) {
}
ngOnInit() {
}
//unblockUser for unblock user
unblockUser(user : any) {
//pass the dataparam in the backend....
var data = {
"user_id" : this.loggedUserObject.user_id,
"block_user_id" : this.selectedUser.id
}
//here we will set url via key wise....
var url = '/api/un-block-user-profile';
//saveDetail function for save data in db...
this.service.saveDetail(data, url).subscribe( (data : any) => {
if(data.status) {
$('#BlockedListModal').on('hidden.bs.modal', function () {
this.dashboard.getUserDetail();
})
//her we will remove user from the updated list of block user...
var index = this.blockUserlist.findIndex(x=>x.id == this.selectedUser.id);
if(index != -1) {
this.blockUserlist.splice(index, 1);
}
//remoive card after accept
this.currentElement.remove();
this.service.successAlert(data.message);
}
});
}
}
//header compeonet 2: here we will fire function from another compeonet
getDashboardDetail() {
//hold user info
var data = {
"user_id" : this.currentUserObject.user_id
}
var url = '/api/time-line-list';
//createUser function for create user in DB
this.service.saveDetail(data, url).subscribe( (data : any) => {
if(data.status) {
if(data.result.article_info.length >0) {
if(this.dashboardArticleList.length == 0) {
this.dashboardArticleList = data.result.article_info;
} else {
this.dashboardArticleList = this.dashboardArticleList.concat(data.result.article_info);
}
}
}
});
}
//In the 2nd Component we have show listing inside model.i have reload the list after close model. please check and tell me what the wrong in my code?

How to fix subscribe not exist in type void

I am new to angular 7 and didn't find any proper answer for similar questions posted.
I am getting Property 'subscribe' does not exist on type 'void' in angular-cli. I tried importing subscribe from rxjs but didn't find that library.
The problem is in the UpdateRecord Function!
product.component.ts code:
the code bellow is exist in compoent.ts of product
import { Component, OnInit } from '#angular/core';
import { ProductService } from 'src/app/shared/product.service';
import { NgForm } from '#angular/forms';
import { ToastrService } from 'ngx-toastr';
import { filter, map } from 'rxjs/operators';
#Component({
selector: 'app-product',
templateUrl: './product.component.html',
styleUrls: ['./product.component.css']
})
export class ProductComponent implements OnInit {
constructor(private service : ProductService, private toastr : ToastrService) { }
ngOnInit() {
this.resetForm();
}
resetForm(form?: NgForm) {
if (form != null)
form.resetForm();
this.service.formData = {
ProductID: null,
ProductName: '',
ProductDescription: '',
Price: 0.00,
Image: '',
Qte: null
}
}
onSubmit(form: NgForm) {
if (form.value.ProductID == null)
this.insertRecord(form);
else
this.updateRecord(form);
}
insertRecord(form: NgForm) {
this.service.postProduct(form.value).subscribe(res => {
this.toastr.success('Inserted successfully', 'Product. Register');
this.resetForm(form);
this.service.refreshList();
});
}
updateRecord(form: NgForm) {
this.service.putProduct(form.value).subscribe(res => {
this.toastr.success('Updated successfully', 'Product. Update');
this.resetForm(form);
this.service.refreshList();
});
}
}
product.service.ts code :
the code bellow is exist in service file related to product
import { Injectable } from '#angular/core';
import { Product } from './product.model';
import { HttpClient } from "#angular/common/http";
#Injectable({
providedIn: 'root'
})
export class ProductService {
formData : Product
list : Product[]
readonly rootURL= 'http://localhost:50369/api'
constructor(private http : HttpClient) { }
postProduct(formData : Product){
return this.http.post(this.rootURL+'/Product', formData);
}
refreshList(){
return this.http.get(this.rootURL+'/Product')
.toPromise().then(res => this.list = res as Product[]);
}
putProduct(formData : Product){
this.http.put(this.rootURL+'/Product/'+formData.ProductID,FormData);
}
}
Thanks in advance,
I missed return :
So in putProduct function in product.service.ts is updated to be :
putProduct(formData : Product){
return this.http.put(this.rootURL+'/Product/'+formData.ProductID,FormData);
}
And it's working now!
Your HttpClient.put function seems to be incorrectly used (you are passing the class as parameter when you should be passing the object).
Look for the function updateHero() in this StackBlitz example.
/** PUT: update the hero on the server. Returns the updated hero upon success. */
updateHero (hero: Hero): Observable<Hero> {
httpOptions.headers =
httpOptions.headers.set('Authorization', 'my-new-auth-token');
return this.http.put<Hero>(this.heroesUrl, hero, httpOptions)
.pipe(
catchError(this.handleError('updateHero', hero))
);
}

Interceptor not setting the authorization token

Hi I'm trying to write a simple Angular 6 interceptor that adds the jwt token to the header when sending requests.
The problem is that the header in the request arrives NULL on the backend, so of course I can't get the authorization token and I'm having trouble figuring out why.
I'm pretty sure the problem is in my js code because if I try to send the same request via any REST client I can see the header in my Java code just fine.
Here's my js code:
import { Component, OnInit } from '#angular/core';
import {Observable} from 'rxjs/Observable';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { UserService } from './user.service';
#Component({
selector: 'app-user',
templateUrl: './user.component.html',
styleUrls: ['./user.component.css']
})
export class UserComponent implements OnInit {
constructor(private http: HttpClient, private userService: UserService) { }
ngOnInit() {
this.userService.getAllUsers().subscribe(
data => {
console.log(data);
/* this.users_from_db=data; */
},
err => {
console.log(err);
}
);
}
users_from_db: Observable<any>;
}
import {Injectable} from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import {Observable} from 'rxjs/Observable';
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};
#Injectable()
export class UserService {
constructor(private http: HttpClient) {}
public getAllUsers(): Observable<any> {
return this.http.get<any>('http://localhost:8080/users/get-all');
}
}
import { Injectable } from '#angular/core';
import {HttpInterceptor, HttpRequest, HttpHandler, HttpSentEvent, HttpHeaderResponse, HttpProgressEvent,
HttpResponse, HttpUserEvent, HttpErrorResponse} from '#angular/common/http';
import { Observable } from 'rxjs/Observable';
import { Router } from '#angular/router';
import {TokenStorage} from './token.storage';
import 'rxjs/add/operator/do';
const TOKEN_HEADER_KEY = 'Authorization';
#Injectable()
export class Interceptor implements HttpInterceptor {
constructor(private token: TokenStorage, private router: Router) { }
intercept(req: HttpRequest<any>, next: HttpHandler):
Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> {
let authReq = req;
if (this.token.getToken() != null) {
console.log("authorizing...");
authReq = req.clone({ headers: req.headers.set(TOKEN_HEADER_KEY, 'Bearer ' + this.token.getToken())});
console.log(authReq);
}
if (!authReq.headers.has('Content-Type')) {
authReq = req.clone({ headers: req.headers.set('Content-Type', 'application/json') });
}
return next.handle(authReq).do(
(err: any) => {
if (err instanceof HttpErrorResponse) {
console.log(err);
console.log('req url :: ' + req.url);
if (err.status === 401) {
this.router.navigate(['login']);
}
}
}
);
}
}
The value of the token is surely there when I do this.token.getToken()in the intercept function. I checked by printing the value in the browser console.
Any help is appreciated, thanks.
This is my interceptor:
import { Injectable } from "#angular/core";
import { HttpRequest, HttpHandler, HttpEvent, HttpErrorResponse, HttpInterceptor } from "#angular/common/http";
import { Observable, BehaviorSubject, throwError } from "rxjs";
import { catchError, map, filter, take, switchMap, finalize } from "rxjs/operators";
import { AppConsts } from "../consts";
#Injectable()
export class JwtInterceptor implements HttpInterceptor {
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(this.addTokenToRequest(request)).pipe(
map(res => res),
catchError(err => {
if (err instanceof HttpErrorResponse && err.status === 401 && err.headers.has("Token-Expired")) {
// here code to refresh token if needed
} else {
return throwError(err);
}
})
);
}
private addTokenToRequest(request: HttpRequest<any>, token: string = null): HttpRequest<any> {
if (token) {
request = request.clone({ setHeaders: { Authorization: `Bearer ${token}` } });
}
else {
const currentUser = JSON.parse(localStorage.getItem(AppConsts.DEFAULT_USER_STORAGE_NAME));
if (currentUser && currentUser.token) {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${currentUser.token}`
}
});
}
}
return request;
}
}
You also can see a simple example - http://jasonwatmore.com/post/2016/08/16/angular-2-jwt-authentication-example-tutorial

Ionic 3 HTTP request not working on ios ,but works on android?

I have an Ionic 3 application that calls a Spring Boot API to login into Mobile App,My Spring Boot application is hosted in Aws.It works on android But it doesn't work on ios ,It Says Cross Issue I tried Many Solutions from internet But did not get the result.
The error I am getting is
response with status: 0 for url : null
this is my working spring boot controller
#CrossOrigin
#RestController
#RequestMapping("/api/customerr")
public class loginController extends NamedParameterJdbcDaoSupportClass{
#Autowired
LoginService loginService;
#Autowired
LoginValidation loginValidation;
#RequestMapping(value="/getUser", method = RequestMethod.POST)
public Response getUsers( #RequestBody UserRequest userRequest ) throws Exception {
List<User> users = null;
try {
loginValidation.getUsers(userRequest.getSsoid(), userRequest.getPassword() );
} catch (ValidationExceptions ex) {
ex.printStackTrace();
return new Response("400", ex.getMessage());
}
try {
users = loginService.getUsers(userRequest.getSsoid(),userRequest.getPassword() );
} catch (Exception ex) {
return new Response("400", ex.getMessage());
}
for(User u: users )
{
if(u.getStatus().getStatusId() == 2)
{
return new Response("300", u.getSsoid());
}
}
return new Response("200", users);
}
}
this is my ionic provider/service
import { Http, Response} from '#angular/http';
import { Injectable } from '#angular/core';
#Injectable()
export class loginService {
data:any;
constructor(public http : Http){}
getAllUsers(authData){
alert("api users")
return new Promise(resolve=>{
this.http.post('http://someAddress:8080/api/customerr/getUser', authData)
.map(res=>res.json())
.subscribe(data=>{
this.data=data;
resolve(this.data)
})
})
}
}
This is the login page where I am calling the api
import { Component, ViewChild } from '#angular/core';
import { Alert,AlertController,IonicPage,Loading,LoadingController,NavController,MenuController } from 'ionic-angular';
import { FormBuilder, FormGroup, Validators, NgForm } from '#angular/forms';
import { EmailValidator } from '../../validators/email';
import { CustomerPage } from '../customer/customer';
import { loginService } from '../../providers/loginservice/login.servie';
import {Response} from '#angular/http';
import { ToastController } from 'ionic-angular';
import { CustomerdetailsPage } from '../customerdetails/customerdetails';
#IonicPage()
#Component({
selector: 'page-login',
templateUrl: 'login.html',
})
export class LoginPage {
#ViewChild('f') loginForm: NgForm;
loginResponse:any;
constructor(
public navCtrl: NavController,
public loadingCtrl: LoadingController,
public alertCtrl: AlertController,
public menu:MenuController,
private loginservice : loginService,
private toastCtrl: ToastController
){
}
ionViewWillEnter(){
this.menu.enable(false)
}
ionViewWillLeave(){
this.menu.enable(true)
}
loginUser() {
console.log("login data");
console.log(this.loginForm.value);
this.loginservice.getAllUsers(this.loginForm.value).then(
(data:any) =>
{
this.loginResponse = data.json();
alert("data");
alert(this.loginResponse.code);
if(this.loginResponse.code === '200')
{
if(this.loginResponse.data.length !== 0)
{
let key1 = 'islogIn';
localStorage.setItem(key1, "true");
this.navCtrl.setRoot(CustomerPage);
}
else if(this.loginResponse.data.length == 0)
{
let toast = this.toastCtrl.create({
message: 'invalid username or password',
duration: 3000,
position: 'bottom'
});
toast.onDidDismiss(() => {
console.log('Dismissed toast');
});
toast.present();
}
}
else if (this.loginResponse.code === '300')
{
let toast = this.toastCtrl.create({
message: 'user is deactivated',
duration: 3000,
position: 'bottom'
});
toast.onDidDismiss(() => {
console.log('Dismissed toast');
});
toast.present();
}
},
(error)=>{
alert(error);
}
);
}
}
And this the app.module.ts
#NgModule({
declarations: [
..
LoginPage,
...
],
imports: [
BrowserModule,
HttpClientModule,
HttpModule,
IonicStorageModule.forRoot(),
IonicModule.forRoot(MyApp),
],
bootstrap: [IonicApp],
entryComponents: [
.
.
LoginPage,
.
.
],
providers: [
Network,
StatusBar,
SplashScreen,
{provide: ErrorHandler, useClass: IonicErrorHandler},
Storage,
SocialSharing,
File,
FileOpener,
DatabaseProvider,
SQLitePorter,
SQLite,
GlobalProvider,
PageserviceProvider,
loginService,
syncService
]
})
export class AppModule {}
Please Use Native HTTP API for IOS
https://ionicframework.com/docs/native/http/

Resources