Angular 2 service localstorage - javascript

I'm trying to do a ToDoList in service with localstorage.
add.component.ts
export class AddComponent implements OnInit {
item: Item[];
constructor(
private router: Router,
private itemService: ItemService) {
}
addTodo() {
this.itemService.save();
this.router.navigate(['./list']);
}
ngOnInit() {}
}
item.service.ts
#Injectable()
export class ItemService {
private itemsUrl = 'items';
private headers = new Headers({'Content-Type': 'application/json'});
private todos: any;
private currentItem: any;
constructor(
private http: Http,
private item: Item) {
this.currentItem = (localStorage.getItem('currentItem')!==null) ? JSON.parse(localStorage.getItem('currentItem')) : [ ];
this.todos = this.currentItem;
}
save(): Promise<Item> {
return this.http
.post(this.itemsUrl, {headers: this.headers})
.toPromise()
.then((res: Response) => {
this.todos.push({
id: this.item.id,
title: this.item.title,
message: this.item.message,
done: false
});
this.todos.title = '';
this.todos.message = '';
localStorage.setItem('currentItem', JSON.stringify(this.todos))
return this.todos;
})
.catch(this.handleError);
}
private handleError(error: any): Promise<any> {
console.log('An error occured', error);
return Promise.reject(error.message || error);
}
}
item.ts
export class Item {
id: number;
title: string;
message: string;
}
add.component.ts
<div class="container">
<form (submit)="addTodo()">
<div class="form-group">
<label>Id:</label>
<input [(ngModel)]="id" class="textfield form-control" name="id">
</div>
<div class="form-group">
<label>Titulo:</label>
<input [(ngModel)]="title" class="textfield form-control" name="title">
</div>
<div class="form-group">
<label>Mensagem:</label>
<input [(ngModel)]="message" class="textfield form-control" name="message">
</div>
<button type="submit" class="btn btn-success">Save</button>
</form>
</div>
If I add localstorage in add.component.ts it works! But if a try to do it as a service I have an error : EXCEPTION: Uncaught (in promise): Error: DI Error Error: DI Error
I don't know what to do. I search how to do it but I don't found an answer that would help me.
Does anyone know how to fix it?

Localstorage is not an angular service. It's just a native JS object controlling the browser's localstorage. Therefor you can not inject it. If you want to have service functionality, you can wrap the native localstorage in an angular LocalStorageService

You don't want to inject Item into ItemService. You really want to have a get function that accepts an Item as an argument and retrieves it from localStorage.

As PierreDuc said, local storage is feature of the user browser. According to this it should work with all major browsers.
Because it browser feature and not part of angular it doesn't need to be injected.
More of how to use localStorage you can read here.
If you still want to use it as an angular service I recommend you to use this library.

Related

how to use nest-keycloack-connect to login a user

am working on a nest project and am trying to handle authentication using keycloack and i did connect my app to keycloack service
KeycloakConnectModule.register({
authServerUrl: 'http://localhost:8080/auth',
realm: 'demo',
clientId: 'nest-app',
secret: 'c3e273bc-3286-44a6-bc21-82195718f0fb',
// Secret key of the client taken from keycloak server
}),
and i did use the decorators and they did work fine
#Controller()
export class UserController {
constructor(private readonly userService: UserService) {}
#Get('/public')
#Unprotected()
getpublic(): string {
return `${this.userService.getHello()} from public`;
}
#Get('/user')
#Roles('user')
getUser(): string {
return `${this.userService.getHello()} from user`;
}
#Get('/admin')
#Roles('admin')
getAdmin(): string {
return `${this.userService.getHello()} from admin`;
}
#Get('/all')
#AllowAnyRole()
getAll(): string {
return `${this.userService.getHello()} from all`;
}
}
now am wondering how to login and register a user from the nestjs server i did look and i did find that i can inject the
constructor(
#Inject(KEYCLOAK_INSTANCE) private keycloak: any,
) {}
now how am suppose to use that because theres no documentation on how to use the service and theres no autocomplete when i do
this.keycloack.login() // for example
can you help please ?

Ngfor doesn't actualize on reloading page (Angular + RXJS)

Hi i'm building a chat app with angular for a school project i'm using firebase for my backend and i have an issue with my ngfor.
For exemple if i reload the page i will see nothing unless i hover my routerlink on my navbar. However sometime it will work after some time on the page without any action
When i recieve message i need to be on the page to see them ...
When i reload my page in first time my array is empty this may be what makes the ngfor bug
array on reload.
I'm using ngOnInit() to subscribe :
messages: Message[];
messageSubscription: Subscription;
constructor(private messageService: MessageService, private router: Router) {
}
ngOnInit(): void {
this.messageSubscription = this.messageService.messageSubject.subscribe(
(messages: Message[]) => {
console.log(messages)
this.messages = messages;
}
);
this.messageService.getMessage();
this.messageService.emitMessage();
}
ngOnDestroy(): void {
this.messageSubscription.unsubscribe();
}
This is my html template :
<div *ngFor="let message of messages" class="message-box">
<img [src]="message.photoURL" class="profile-picture">
<div class="content-box">
<div class="information">
<p class="username">{{message.displayName}}</p>
<p class="date">{{message.createdAt | date: 'short'}}</p>
</div>
<p class="text">{{message.text}}</p>
</div>
</div>
Here you can find my service with my getMessage() function and emitMessage():
messages:Message[] = [];
messageSubject = new Subject<Message[]>();
constructor() { }
emitMessage(){
this.messageSubject.next(this.messages);
}
saveMessage(newMessage: Message){
firebase.database().ref('/message').push(newMessage);
}
getMessage(){
firebase.database().ref('/message')
.on('value', (data) => {
this.messages = data.val() ? Object.values(data.val()): [];
this.emitMessage();
});
}
And this is the repo of my project: https://github.com/Zuxaw/AngularChatApp
If anyone has a solution I'm interested
Problem is, your firebase library is not Angular specific.
This means you some times need to make sure its code, mostly its event callbacks, run within an Angular zone (google to read about it) to make sure a change detection 'tick' is invoked when data changes.
message.service.ts
import { Injectable, NgZone } from '#angular/core';
// ...
constructor(private zone: NgZone) { }
// ..
getMessage(){
firebase.database().ref('/message')
.on('value', (data) => {
this.zone.run(() => {
this.messages = data.val() ? Object.values(data.val()): [];
this.emitMessage();
});
});
}
I think you might need to use the child_added event instead of value in your getMessage method.
Check if you're receiving data on time in your getMessage method, if not it's most probably, because of the event.
But one thing that I don't understand is why you're calling emitMessage inside getMessage and also calling it inside your component after getMessage, try to evade that.

Inject store into errorhandler class Angular

I am trying to implement sentry error handling into my application, now I have it set up and working as expected.. but now I want to be able to pass user information on the Sentry object for better error logging.
So I have the following setup
export class SentryErrorHandler implements ErrorHandler {
userInfo: UserInfo;
constructor(
private _store: Store<AppState>
) {
this.getUserInfo();
}
getUserInfo() {
this._store.select('userInfo')
.subscribe(result => {
this.userInfo = result;
});
}
handleError(err: any): void {
Sentry.configureScope((scope) => {
scope.setUser({
email: this.userInfo?.emailAddress,
id: this.userInfo?.id?,
});
});
const eventId = Sentry.captureException(err.originalError || err);
Sentry.showReportDialog({ eventId });
}
}
and I am providing the error handler like so in my root module
// ...
{ provide: ErrorHandler, useClass: SentryErrorHandler }
// ...
but what happens is, when I start my application I get the following error
Obviously im doing something wrong here, any help would be appreciated!
This error is happening because without the #Injectable decorator Angular cannot wire up dependencies for the class (even using it in providers).
So all you have to do is add the #Injectable() decorator in your error class.
See a demo here:
https://stackblitz.com/edit/angular-ctutia

Module not reloading after JSON.parse error

I have a test page for QA where our QA can replicate the behavior of the server by passing json to a mock service.
Everything works as intended when I use a valid json, but when I use an invalid json I receive an error, which is regular. The problem I have is that the page doesn't update anymore after this json error, even with a valid json.
Here is an extract of the test page component:
export class QaTestComponent implements OnInit {
modules: Module[];
pageState: PageState;
mockModulesValue: string;
mockPageStateValue: string;
constructor(private moduleService: MockModuleService, private pageStateService: MockPageStateService) { }
getModules() {
this.moduleService.getModules().then(modules => this.modules = modules);
}
updateModules() {
let jsonModules = JSON.parse(this.mockModulesValue);
this.moduleService.setModules(jsonModules);
this.getModules();
}
Here is the html file with the function call:
<div class="qa-test-interface-setup-datas-type col-md-6">
<h3 class="qa-test-interface-setup-datas-type-title">Modules</h3>
<textarea name="" id="" cols="30" rows="10" class="qa-test-interface-setup-datas-type-textarea" [(ngModel)]="mockModulesValue"></textarea>
<button class="qa-test-interface-setup-datas-type-button" (click)="updateModules()">Update</button>
</div>
And here is the mock service:
export class MockModuleService implements ModuleService {
raw: Module[] = aJsonArray;
response: Module[] = this.raw;
setModules(mockModules: Module[]) {
this.response = mockModules == null ? this.raw : mockModules;
}
getModules(): Promise<Module[]> {
return Promise.resolve(this.response);
}
}
I tried logging to see if a valid mockModuleValues was blocked in a component or a service after an error but I can see it goes through until getModules().
So after some research I came to the point where I did my json parsing inside a try/catch to avoid the error killing my subscriber.
updateModules() {
if(this.mockModulesValue) {
try {
let jsonModules = JSON.parse(this.mockModulesValue);
this.moduleService.setModules(jsonModules);
this.getModules();
} catch(e) {
alert(e);
}
}
}

Angular 2 get image src from authorized request

I'm using angular2-jwt to authorize the requests. I've got a get request which retrieves multiple documents from the API.
A document can have multiple images which also need to be fetched using an authorized request.
So obviously calling them directly with doesn't work.
I followed this example: https://stackoverflow.com/a/40862839/909723
I've got two questions:
Without the async i get : GET http://localhost:4200/[object%20Object] 404 (Not Found)
And with the async i get : Invalid argument '[object Object]' for pipe 'AsyncPipe' I tried it with the 'data:image/jpg;' and without
Part of the template
<md-card *ngFor="let document of documents">
<md-toolbar color="accent" *ngIf="getDocName(document)">
<span class="nowrap">{{getDocName(document)}}</span>
<span class="country-full-width"></span>
</md-toolbar>
<md-card-content>
<div *ngFor="let image of getImages(document)">
<img class="image" [src]="getImageSrc(image.image_id) | async" />
</div>
</md-card-content>
</md-card>
I've got a service which uses angular2-jwt - AuthHttp
#Injectable()
export class ImageService {
constructor(public authHttp: AuthHttp, public http: Http, public sanitizer: DomSanitizer) {}
getImageSrc(id, type){
let url = Config.apiUrl + "/images/" + id + "/thumb.jpg"
let headers = new Headers();
headers.append('Content-Type', 'image/jpg');
return this.authHttp.get(url, {
headers: headers,
responseType: ResponseContentType.Blob
})
.map(res => {
return new Blob([res["_body]"]], {
type: res.headers.get("Content-Type")
});
})
.map(blob => {
var urlCreator = window.URL;
return this.sanitizer.bypassSecurityTrustUrl(urlCreator.createObjectURL(blob));
})
}
}
This is the function called in the template
getImageSrc(id)
{
return this.imageService.getImageSrc(id)
//.subscribe (
// data => data,
// err => console.log(err)
//);
}
Hope someone can help
I have faced the same problem and this solution helped: http://blog.jsgoupil.com/request-image-files-with-angular-2-and-an-bearer-access-token
Although you may need to change the way in which options are added to http request (in UrlHelperService) according to your angular version 2/4.
Also you need to change:
Observable
to
Observable<any>
all ower the place.
And
private _result: BehaviorSubject = new BehaviorSubject(null);
to
private _result: BehaviorSubject<any> = new BehaviorSubject('');

Categories