Hii all I am trying to post data to json server using post method , but unfortunately I have erros, my app have buttons follow, likes etc , I want when user clicks follow numbers increase and saved to the json file , so now when user clicks button I get the following error :
Note: am using fakes json server : Fake Json server
Error: Insert failed, duplicate id
at Function.insert (C:\Users\jelly\AppData\Roaming\npm\node_modules\json-server\node_modules\lodash-id\src\index.js:49:18)
at C:\Users\jelly\AppData\Roaming\npm\node_modules\json-server\node_modules\lodash\lodash.js:4374:28
at arrayReduce (C:\Users\jelly\AppData\Roaming\npm\node_modules\json-server\node_modules\lodash\lodash.js:683:21)
at baseWrapperValue (C:\Users\jelly\AppData\Roaming\npm\node_modules\json-server\node_modules\lodash\lodash.js:4373:14)
at LodashWrapper.wrapperValue (C:\Users\jelly\AppData\Roaming\npm\node_modules\json-server\node_modules\lodash\lodash.js:9052:14)
at create (C:\Users\jelly\AppData\Roaming\npm\node_modules\json-server\lib\server\router\plural.js:221:52)
at Layer.handle [as handle_request] (C:\Users\jelly\AppData\Roaming\npm\node_modules\json-server\node_modules\express\lib\router\layer.js:95:5)
at next (C:\Users\jelly\AppData\Roaming\npm\node_modules\json-server\node_modules\express\lib\router\route.js:137:13)
at next (C:\Users\jelly\AppData\Roaming\npm\node_modules\json-server\node_modules\express\lib\router\route.js:131:14)
at Route.dispatch (C:\Users\jelly\AppData\Roaming\npm\node_modules\json-server\node_modules\express\lib\router\route.js:112:3)
POST /statuses 500 13.873 ms - -
Here is service
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import {Status } from '../model/statuses.model';
import { Comment } from '../model/comments.model';
#Injectable({
providedIn: 'root'
})
export class UserService {
status: Status[];
constructor(private http: HttpClient) { }
statusUrl = 'http://localhost:3000/statuses';
commentsUrl = 'http://localhost:3000/comments';
getStatuses() {
return this.http.get<Status[]>(this.statusUrl);
}
addStatus(status: Status) {
return this.http.post(this.statusUrl, status);
}
addComments(comment: Comment) {
return this.http.post(this.commentsUrl, comment);
}
}
here is ts file :
import { Component, OnInit } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { UserService } from '../service/user.service';
import { Status } from '../model/statuses.model';
import { Comment } from '../model/comments.model';
import {FormBuilder, FormGroup, Validators} from '#angular/forms';
#Component({
selector: 'app-user-profile',
templateUrl: './user-profile.component.html',
styleUrls: ['./user-profile.component.scss']
})
export class UserProfileComponent implements OnInit {
status: Status[];
comment: Comment[];
constructor(private formBuilder: FormBuilder, private http: HttpClient, private userService: UserService) { }
addForm: FormGroup;
ngOnInit() {
this.addForm = this.formBuilder.group({
id: [],
name: ['', Validators.required],
city: ['', Validators.required],
description: ['', Validators.required],
});
this.userService.getStatuses()
.subscribe( data => {
this.status = data;
console.log(data);
console.log(this.status);
});
}
addComments() {
this.userService.addComments(this.addForm.value)
.subscribe(data => {
this.comment.push(this.addForm.value);
});
}
followButtonClick(statusId) {
const statusToUpdate = this.status.filter(status => status.id === statusId)[0];
statusToUpdate.followers++;
statusToUpdate.following++;
this.persistStatus(statusToUpdate);
}
likesButtonClick(statusId) {
const statusToUpdate = this.status.filter(status => status.id === statusId)[0];
statusToUpdate.like++;
this.persistStatus(statusToUpdate);
}
persistStatus(status) {
this.userService.addStatus(status)
.subscribe(data => {
this.status = status;
});
}
}
Here is json file :
{
"statuses": [
{
"id": 1,
"statusId": 20,
"likes": 121,
"following": 723,
"followers": 4433
}
]
}
Here is model
export class Status {
id: number;
statusId: number;
like: number;
following: number;
followers: number;
}
what am I doing wrong in my code ????
From documentation of the fake json-server you are using,:
Id values are not mutable. Any id value in the body of your PUT or
PATCH request will be ignored. Only a value set in a POST request will
be respected, but only if not already taken.
You are trying to update an existing status, so you need a put call not post. Something like this:
updateStatus(status: Status) {
return this.http.put(this.statusUrl + '/' + status.id, status);
}
And use it in the persistStatus function.
persistStatus(status) {
his.userService.updateStatus(status)
.subscribe(data => {
this.status = [status];
});
}
Related
I'm looking for help for the implementation of Revolut #revolut/checkout npm package with Angular 7
declared the main script at angular.json:
"scripts": [
"node_modules/#revolut/checkout/cjs/index.js"
]
Put the indicated script at the index.html head:
<script>!function(e,o,t){e[t]=function(n,r){var c={sandbox:"https://sandbox-merchant.revolut.com/embed.js",prod:"https://merchant.revolut.com/embed.js",dev:"https://merchant.revolut.codes/embed.js"},d=o.createElement("script");d.id="revolut-checkout",d.src=c[r]||c.prod,d.async=!0,o.head.appendChild(d);var s={then:function(r,c){d.onload=function(){r(e[t](n))},d.onerror=function(){o.head.removeChild(d),c&&c(new Error(t+" is failed to load"))}}};return"function"==typeof Promise?Promise.resolve(s):s}}(window,document,"RevolutCheckout");</script>
my checkout component:
import { Component, Input, OnInit } from '#angular/core';
import { Subject } from 'rxjs';
declare let RevolutCheckout: any;
#Component({
selector: 'app-revolutwidget',
templateUrl: './revolutwidget.component.html',
styleUrls: ['./revolutwidget.component.scss']
})
export class RevolutwidgetComponent implements OnInit {
#Input() payOrder : any;
#Input() billingData : any;
revolutCheckout = RevolutCheckout;
checkoutResult$ = new Subject<string>();
constructor() { }
async ngOnInit() {
try {
console.log(this.billingData)
this.checkoutResult$.subscribe(res => {
console.log(res);
if(res === 'success'){
this.onSuccess();
} else if(res === 'error'){
this.onError();
} else if (res === 'cancel'){
this.onCancel();
}
})
this.revolut()
}catch(err){
console.log(err);
}
}
async revolut(){
const billingData = this.billingData
const checkoutResult = this.checkoutResult$;
this.revolutCheckout(this.payOrder.payOrderId,this.payOrder.mode).then(function (instance) {
instance.payWithPopup({
onSuccess() {
checkoutResult.next('success')
},
onError(){
checkoutResult.next('error')
},
onCancel(){
checkoutResult.next('cancel')
},
locale: "es",
...billingData
})
})
}
onSuccess(){
console.log('successs');
}
onError(){
console.log('error');
}
onCancel(){
console.log('cancel');
}
}
The widget is working but I'm getting this (non critical?) error after compilation at the browser's console before the app ends loading:
index.js:2 Uncaught ReferenceError: exports is not defined
at index.js:2:1
where index.js is node_modules/#revolut/checkout/cjs/index.js
I didn't found any example about implementing Revolut with Angular anywhere, so any help would be appreciated.
Thank you
can any one please tell me why I can not loop through this array?
In ngOnInit, everything works fine. I got an array that I successfully display in the template.
But in ngAfterViewInit, console.log show the array but when looping through with "for of" or "forEach", nothing works.
import { JobsService } from '../jobs.service';
import {Job} from '../models/Job';
#Component({
selector: 'app-job',
templateUrl: 'job.component.html'
})
export class JobComponent implements OnInit, AfterViewInit {
title = 'Job';
jobs: Job[] = [];
InProcess = '';
CurrentPartner = '';
ShowProcess = false;
sended = '';
constructor(private jobsService: JobsService) {
}
ngOnInit() {
this.jobs = this.jobsService.getJobs();
}
ngAfterViewInit() {
console.log(this.jobs); // Show the array
// Nothing happened when looping through the array
this.jobs.forEach((oneJob) => {
console.log(oneJob);
});
}
}
Screenshot of the console in Google Chrome
The content of the service:
import { HttpClient, HttpErrorResponse } from '#angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import {Job} from './models/Job';
interface IJob {
message: string;
jobs: any[];
}
#Injectable({
providedIn: 'root'
})
export class JobsService {
constructor(private httpClient: HttpClient) { }
private REST_API_SERVER = 'http://localhost:8080/myband/api/getjobs.php';
private REST_API_SERVER_SEND = 'http://localhost:8080/myband/api/sendjob.php';
jobList: Job[] = [];
errorMessage: any;
message: string;
static handleError(err: HttpErrorResponse) {
let errorMessage = '';
if (err.error instanceof ErrorEvent) {
errorMessage = `An error occurred: ${err.error.message}`;
} else {
errorMessage = `Server returned code: ${err.status}, error message is: ${err.message}`;
}
console.error(errorMessage);
return throwError(errorMessage);
}
public getJobs() {
this.requestJobs().subscribe(
iJob => {
this.message = iJob.message;
for (const job of iJob.jobs) {
const oneJob: Job = new Job(job);
this.jobList.push(oneJob);
}
},
error => this.errorMessage = error as any
);
return this.jobList;
}
public requestJobs(): Observable<IJob> {
return this.httpClient.get<IJob>(this.REST_API_SERVER).pipe(
catchError(JobsService.handleError)
);
}
}
The first thing I want to say to you is about isolation of responsibilities.
Your service must have just one job: provider one way to access your data; It means your logic inside getJobs() method could be done in your component.
export class JobsService {
constructor(
private httpClient: HttpClient,
) {}
private REST_API_SERVER = 'http://localhost:8080/myband/api/getjobs.php';
public requestJobs(): Observable<IJob> {
return this.httpClient.get<IJob>(this.REST_API_SERVER);
}
}
Now, you can handler your data in your component.
import { JobsService } from '../jobs.service';
#Component({
selector: 'app-job',
templateUrl: 'job.component.html'
})
export class JobComponent implements OnInit, AfterViewInit {
title = 'Job';
jobs$;
InProcess = '';
CurrentPartner = '';
ShowProcess = false;
sended = '';
constructor(private jobsService: JobsService) {
}
ngOnInit() {
this.jobs$ = this.jobsService.requestJobs();
}
ngAfterViewInit() {
this.jobs$
.pipe(
map(() => {}), // change your data here
catchError(() => {}) // handler your error here;
)
.subscribe(
() => {} // have access to your final data here.
);
}
}
Things to know:
You can remove the subscribe() execution and use the async pipe in your template;
The use of the operator map in pipe() is optional, you can handler your final data directly from your first callback subscribe().
You can convert your Observable to Promise using toPromise() method in one observable. Don't forgot async / await in your ngAfterViewInit.
Let me know if there is something I can help.
Try:
Object.keys(this.jobs).forEach(job => {
console.log(this.jobs[job]);
});
Try to assign an iterator function with below part replacement by this code:
// Nothing happened when looping through the array
this.jobs.forEach(oneJob, function(value, key) {
console.log(key + ': ' + value);
});
Usage of forEach in AngularJS:
For documentation try to check AngularJS forEach Docs
Syntax:
someIterable.forEach(object, iterator, [context])
Please check below example
class Job {
id: any;
status: any;
constructor(obj: any) {
this.id = obj.id;
this.status = obj.status;
}
}
let arr = [
{
id: 1,
status: "job"
}, {
id: 2,
status: "job2"
}
];
let newArr: any = [];
arr.forEach(a => {
let obj: Job = new Job(a);
newArr.push(obj);
})
console.log(newArr);
newArr.forEach((a: any) => {
console.log(a);
})
I develop an Ionic 3.9 chat with Firebase and I have the following error:
TypeError: this.db.list(...).subscribe is not a function
Here is my code:
import { Component } from '#angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { AngularFireDatabase } from 'angularfire2/database';
#IonicPage()
#Component({
selector: 'page-consersation',
templateUrl: 'conversation.html',
})
export class ConversationPage {
username: string = '';
message: string = '';
_chatSubscription;
s;
messages;
constructor(public db: AngularFireDatabase,
public navCtrl: NavController, public navParams: NavParams) {
this.username = this.navParams.get('username');
this._chatSubscription = this.db.list('/conversation').subscribe( data => {
this.messages = data;
});
}
sendMessage() {
this.db.list<any>('/conversation').push({
username: 'romain',
message: this.message
}).then( () => {
// message is sent
});
this.message = '';
}
}
Can you help me please?
In this.db.list('/conversation').subscribe( you are missing something between the .list(...) and the .subscribe(...
What you're missing is either .valueChanges() or .snapshotChanges()... You can read about the differences at the AngularFire2 documentation here.
I typically use .valueChanges() most often, so for a quick example with .valueChanges() your code would be:
this._chatSubscription = this.db.list('/conversation').valueChanges().subscribe( data => {
this.messages = data;
);
EDIT - corrected code below. Not supposed to set a variable equal to the whole .subscribe... Define your pointer/listener, and then subscribe to it separately.
this._chatSubscription = this.db.list('/conversation').valueChanges()
this._chatSubscription.subscribe( data => {
this.messages = data;
);
2nd EDIT - after new error message that OP posted as answer.
That new error looks like it's due to version conflicts - check out this question with multiple possible solutions.
When you're getting the following error polyfills.js:3 Uncaught TypeError: Object(...) is not a function..., try the following code below:
this._chatSubscription = this.db.object('/conversation').valueChanges().subscribe(data => {
this.messages = data;
});
I am doing an Angular 4 application with node js backend. I did the login form, and all is good I want to implement the function "remember me".
This my login service:
import { Injectable } from '#angular/core';
#Injectable()
export class loginService{
rememberMe: boolean;
constructor() { }
login(credentials) {
sessionStorage.setItem('Name', credentials.firstName);
sessionStorage.setItem('token', credentials.token);
}
getCostumer() {
const user = {
Name: sessionStorage.getItem('firstName'),
token: sessionStorage.getItem('token')
}
This is the component:
constructor(private signInService: SignInService, private router: Router,
public dialog: MatDialog, private authService: AuthService) { }
ngOnInit() { }
login(costumer) {
this.loginService.login(costumer).subscribe((data) => {
this.authService.login(data);
this.router.navigate(['home']);
this.dialog.closeAll();
}, err => {
this.message = err._body;
console.log(this.message);
});
}
}
Use localStorage instead of sessionStorage
In your case, you can do something like this:
if (isRemberMeChecked) {
...
localStorage.setItem('Name', credentials.firstName);
localStorage.setItem('token', credentials.token);
...
} else {
...
sessionStorage.setItem('Name', credentials.firstName);
sessionStorage.setItem('token', credentials.token);
...
}
If you want to get isRemberMeChecked value globally you can use angular service
What you want to do here is use localStorage for the rememberMe and credentials.firstName. The credentials.token you can store in the sessionStorage:
login(credentials) {
localStorage.removeItem('Name');
localStorage.removeItem('RememberMe');
sessionStorage.setItem('token', credentials.token);
if(rememberMe){
localStorage.setItem('Name', credentials.firstName);
localStorage.setItem('RememberMe', JSON.stringify(this.rememberMe));
}
}
After a reload it will fetch the RememberMe and Name:
if(JSON.parse(localStorage.getItem('RememberMe')) !== null)
{
this.name = localStorage.getItem('Name');
this.rememberMe = JSON.parse(localStorage.getItem('RememberMe'));
}
In an angular 5 app, there is a route guard that check from an API if an object exists:
//guard.ts excerpt
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> | Promise<boolean> | boolean {
return this.clientService.get(next.params.id).switchMap( data => {
return Observable.of(true);
})
.catch( err => Observable.of(false))
}
//route.ts excerpt
{ path: ':id', canActivate: [ ClientDetailGuard ], component: ClientDetail }
this works perfect, but I am wondering if is there a way to pass the data retrieved from my service to next the route/component (ClientDetail), so I won't need to call the service again this again.
I tried to add
next.data.client = data;
before the return of Observable(true) but in the component, the ActivatedRoute's data does not have this value set.
Or should I use something like Resolve?
I know I can achieve this using some state container or a shared service to store/retrieve data, but I wouldn't like to do this at this time, as long as the app is not complex.
I could do this using a Resolver instead of a guard
//route.ts
{ path: ':id', resolve: { client: ClientDetailResolver }, component: ClientDetail }
//resolver.ts
#Injectable()
export class ClientDetailResolver implements Resolve {
constructor(private clientService: ClientService, private router: Router, public location: Location) {
}
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<any>|Promise<any>|any {
return this.clientService.get(route.params.id)
.catch( err => {
//handle error
const path = this.location.path();
this.router.navigate(["error", err.status], { skipLocationChange: true })
.then( () => {
this.location.replaceState(path);
});
return Observable.empty();
})
}
}
You seem to be under-estimating the power of services. Services are the best way to save/store data or states between components. You can set the data from any component, pull the data from any component. You don't have to worry about putting data in for the next route, instead you go to the next route and subscribe to your data on ngOnInit and boom, got everything you need. Here is an example of just how simple it really is.
Example of service
import { Injectable } from '#angular/core';
import { BehaviorSubject, Subscription } from 'rxjs';
#Injectable()
export class AppService {
alertData = new BehaviorSubject({
type: '',
message: '',
timer: 0,
showing: false
});
constructor() {}
setAlertData(data: AlertModel) {
this.alertData.next(data);
}
}
Example of using service
this.subscription$.push(this._as.alertData.subscribe((data: AlertModel) => {
this.alertData = data;
if (data.showing) {
this.alertIsShowing = true;
}
else {
this.alertIsShowing = false;
}
}));