Angular 5- Storing current route in variable *with id* - html

I am using routing in Angular to pull the url and store it in a global variable. It works well, except for when the url has an 'id' in it.
For example, my Url == '/site/1' however....
this.authService.current_route = this.router.url
// '/site' (not 'site/1' or 'site/:id')
How do I refactor to make this work?
My html looks like:
<span id="sitehead"> <a [routerLink]="['/site', site.id ]" (click)="changeroute()"> Site:</a></span>
My component:
import { Component, OnInit, Input } from '#angular/core';
import { DataService } from '../data.service';
import { Http } from '#angular/http';
import * as d3 from 'd3';
import { AuthService } from "../services/auth.service";
import { Router } from "#angular/router";
#Component({
selector: 'app-summary',
templateUrl: './summary.component.html',
styleUrls: ['./summary.component.css'],
})
export class SummaryComponent implements OnInit {
#Input() site;
constructor(private _dataService: DataService, private http: Http, public authService: AuthService, private router:Router ) {
}
changeroute(){
this.authService.current_route = this.router.url
console.log(this.authService.current_route)
}
Thanks!! Let me know if I can clarify

There's probably a less complicated way to get the current url, but in the past, I created a function that does it. Hopefully it suits your immediate needs.
constructor(route: ActivatedRoute) {
const path = this.getPath(route.snapshot);
}
private getPath(route: ActivatedRouteSnapshot): string {
const urlSegments = route.pathFromRoot.map(r => r.url);
return '/' + urlSegments.filter(segment => !!segment && segment.length).join('/');
}

Related

Angular 'Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.'

I'm creating an Angular app which shows list of projects and list of users from postgresql database, but I'm having issues with showing list of users in html.
The problem is that Angular is considering my array as an object no matter what I do.
The same code worked for projects but didn't work for users.
This is my service:
import { environment } from "../../../environments/environment";
import { Observable } from 'rxjs';
import { Projet } from '../modele/projet.model';
import { Test } from '../modele/test.model';
import { HttpParams,HttpClient } from "#angular/common/http";
import { Injectable } from "#angular/core";
import { map } from 'rxjs/operators';
import { User } from '../modele/user.model';
import { Financement } from '../modele/financement.model';
#Injectable()
export class WebService {
constructor(private httpClient: HttpClient) { }
serverUrl: string = "http://localhost:8080/"
get(url: string): Observable<any> {
return this.httpClient.get(this.serverUrl + url);
}
}
The component :
import { Component, OnInit } from '#angular/core';
import { User } from '../../shared/modele/user.model';
import { Router } from '#angular/router';
import { WebService } from '../../shared/sevices/web.service';
import { FormGroup, FormBuilder, FormControl, Validators, Form } from '#angular/forms';
#Component({
selector: 'app-show-users',
templateUrl: './show-users.component.html',
styleUrls: ['./show-users.component.scss']
})
export class ShowUsersComponent implements OnInit {
ngOnInit(): void {
this.getData();
}
usersList: Array<User>
user: User
myForm: FormGroup;
constructor(private webService: WebService, private formBuilder: FormBuilder,private router: Router) { }
getData(): void {
this.webService.get("showUsers").subscribe(res => {
let response = JSON.parse(JSON.stringify(res))
this.usersList = response.data
})
}
}
The html :
<tr *ngFor="let user of usersList">
<td>{{user.name}}</td>
<td>{{user.username}}</td>
<td>{{user.email}}</td>
</tr>
This is the server response :
server response
NB: the EXACT same code worked for the object PROJECT
You need to make sure that the variable you pass into *ngFor is an array. You can make sure of this with Array.from(v) and can also strip any keys of an Object that might be sent from the serverside with Object.values(v):
this.webService.get("showUsers").subscribe(res => {
this.usersList = Array.from(Object.values(res.data.body.data));
})
In my case, I have a simple approach, but I spent a lot of time. You could try this:
datas: any;
this.token = JSON.parse(window.localStorage.getItem('token'));
this.authService.getData(this.token.id).subscribe(data => {
this.datas = data;
})
In the HTML template just use this.datas.id, this.datas.username instead of an *ngFor
You don't need this code:
let response = JSON.parse(JSON.stringify(res))
this.usersList = response.data
simply use:
this.userlist = res
Youe complete method:
this.webService.get("showUsers").subscribe(res => {
this.userlist = res
});

ViewEncapsulation.None not working with innertHTML

I'm actually developing an angular application and I have to put an [innerHTML] element in a div.
My code
Like that :
something.component.html
<section class="mx-auto" *ngFor="let publication of publication">
<div [innerHTML]="publication.content"></div>
</section>
So in ts :
something.component.ts
import { Component, OnInit, ViewEncapsulation } from '#angular/core';
import { Subscription } from 'rxjs';
import { ActivatedRoute } from '#angular/router';
import { Title, Meta } from '#angular/platform-browser';
import { Publication } from '../publication.model';
import { PublicationsService } from '../publication.service';
#Component({
selector: 'app-free-publication',
templateUrl: './something.component.html',
styleUrls: ['./something.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class FreePublicationComponent implements OnInit {
publication: Publication[] = [];
suggestions: Publication[] = [];
private routeSub: Subscription;
getId: any;
isLoading = false;
constructor(public publicationsService: PublicationsService, private route: ActivatedRoute, private titleService: Title, private meta: Meta) {
this.getId = this.route.url['_value'][1].path;
this.getId = + this.getId;
}
ngOnInit() {
this.isLoading = true;
// main publication
this.routeSub = this.route.params.subscribe(params => {
this.publicationsService.getPublication(params['publicationId']).then(dataPublication => {
for (let i = 0; (dataPublication.content.match(/wp-content/g) || []).length; i++) {
dataPublication.content = dataPublication.content.replace('https://aurelienbamde.com/wp-content/', 'assets/content/');
}
this.titleService.setTitle(dataPublication.title);
this.meta.addTag({ name: 'keywords', content: dataPublication.post_tag });
this.publication = [dataPublication];
});
});
}
}
And my innertHTML do not return the style of the html doc that I send.
My tests
With a console.log() at the end of ngOnInit, I can see my html with all of the styles attributs, but by inspecting the div of the innerHTML, there is no style inside.
My question
So I well implement ViewEncapsulation.None as you see, there is an action on other elements, so it works, but not on my innerHTML.
Do you have any idea, problem of version ? Or coworking with others elements ?
Thanks in advance for your time !
And I wish you success in your projects.
You must bypass the security imposed by angular for dangerous content (HTML content not generated by the app). There is a service, called DomSanitizer that enables you to declare a content as safe, preventing angular to filter potentially harm things to be used like styles, classes, tags etc. You basically need to pass your content through this sanitizer using a pipe:
<div [innerHTML]="dangerousContent | safeHtml"></div>
Your SafeHtmlPipe would be something like this:
#Pipe({name: 'safeHtml'})
export class SafeHtmlPipe implements PipeTransform {
constructor(protected sanitizer: DomSanitizer) {}
transform(value: string): SafeHtml {
return this.sanitizer.bypassSecurityTrustHtml(value)
}
}
There are other bypassSecurityTrust* methods in DomSanitizer:
bypassSecurityTrustScript
bypassSecurityTrustStyle
bypassSecurityTrustUrl
bypassSecurityTrustResourceUrl
You can find more info in Angular docs.

Angular2: json does not exist on type object

I am beginner. I am not able to solve this problem. i have read the other errors but still i am not able to understand.
While i am doing .map or .subscribe to the service it gives me error like Property 'json' does not exist on type object.
This is my: continents.component.ts
import { Component, OnInit } from '#angular/core';
import { DataContinentsService } from '../../services/dataContinents.service';
import 'rxjs/add/operator/map';
#Component({
selector: 'app-continents',
templateUrl: './continents.component.html',
styleUrls: ['./continents.component.css'],
providers: [DataContinentsService]
})
export class ContinentsComponent implements OnInit {
continent: any;
constructor(private dataContinentService: DataContinentsService) { }
public getContinentInfo() {
this.dataContinentService.getContinentDetail()
.map((response) => response.json())
.subscribe(res => this.continent = res.json()[0]);
}
ngOnInit() {}
}
This is my Service: DataContinentsService
import { Injectable } from '#angular/core';
import {HttpClientModule, HttpClient} from '#angular/common/http';
// import 'rxjs/add/operator/map';
#Injectable()
export class DataContinentsService {
constructor(private _http: HttpClient) {}
public getContinentDetail() {
const _url = 'http://restcountries.eu/rest/v2/name/india?fulltext=true';
return this._http.get(_url);
}
}
This is my Template: continents.component.html
<h1>Continents</h1>
<h3>Name: {{continent.name}}</h3>
<h3>Capital: {{continent.capital}}</h3>
<h3>Currency: {{continent.currencies[0].code}}</h3>
<button (click)="getContinentInfo()">get details</button>
I'm guessing that you've been reading some outdated documentation.
The old Http class used to return a response that did have a json() method.
The old Http class has been retired, and you are now properly using the HttpClient class. HttpClient's get() method returns an Observable of any - it maps the response's json to an object for you. Typically, you'd specify the type of the object, like so:
this.http.get<SomeObject>(url);
In lieu of that, you just get an Object.
In either case, there's no json() method on the returned object.
So, your service should do this:
public getContinentDetail(): Observable<Continent[]> {
const _url = 'http://restcountries.eu/rest/v2/name/india?fulltext=true';
return this._http.get<Continent[]>(_url);
}
you should subscribe something like this
this.dataContinentService.getContinentDetail().subscribe(continents: Continent[] =>
this.continent = continents[0]);
}

retrieve the method from auth.services.ts to login.component.ts in json

app/auth/auth.services.ts:
import {Injectable} from '#angular/core';
import {Router} from '#angular/router';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
import {User} from './user';
import {Http, Headers, RequestOptions} from '#angular/http';
import 'rxjs/add/operator/map';
#Injectable()
export class AuthService {
result: any;
constructor(private router: Router, private _http: Http) {}
getUsers() {
return this._http.get('/api/users').map(result => this.result = result.json().data);
}
}
http://localhost:3000/api/users :
{"status":200,"data":[{"_id":"5a63f4da17fc7e9e5548da70","name":"Jonson Doeal"},{"_id":"5a63faf417fc7e9e5548da71","name":"Jonson Bol"},{"_id":"5a64f44de87b3e2f80437c6b","name":"aaaa"}],"message":null}
I would like to retrieve data in json from the getUsers method so that I cancompare values
for () {
if (json_value_name == this.temp) {
}
}
login.component.ts:
import {AuthService} from './../auth/auth.service';
import {Component, OnInit} from '#angular/core';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
constructor(
private authService: AuthService
) {}
ngOnInit() {
}
onSubmit() {
this.authService.getUsers();
console.log('this.authService.getUsers() ' + JSON.stringify(this.authService.getUsers()));
}
}
the console returns:
this.authService.getUsers(){"_isScalar":false,"source":{"_isScalar":false},"operator":{}}
I would like it to return in this form:
{"status":200,"data":[{"_id":"5a63f4da17fc7e9e5548da70","name":"Jonson Doeal"},{"_id":"5a63faf417fc7e9e5548da71","name":"Jonson Bol"},{"_id":"5a64f44de87b3e2f80437c6b","name":"aaaa"}],"message":null}
you need to use subscribe
onSubmit() {
this.authService.getUsers().subscribe(data => {console.log(JSON.stringify(data)});
}
Your best bet would something like this:
private myData: any[];
ngOnInit() {
myData = this.authService.getUsers();
}
onSubmit() {
console.log('this.authService.getUsers() ' + JSON.stringify(myData));
}
What you are receiving is the expected result from that method call. The http calls in angular return observables. That means you need to subscribe to what you are returning. Depending on what you are trying to do you may want to restructure your service or component to fully utilize the pattern.
In order to print your data try this in your component:
onSubmit() {
this.authService.getUsers().subscribe((data) => {
console.log(`users ${data}`)
});
}
Hopefully this can get you started on using observables.

Angular 5 HTTP get response error Property 'body' does not exist on type 'Object'

I am working on Angular 5 with Http.
Getting this error while serve the application..
import { Component, OnInit } from '#angular/core';
import { Router, ActivatedRoute, ParamMap } from '#angular/router';
import { HttpClient } from '#angular/common/http';
import 'rxjs/add/operator/switchMap';
#Component({
selector: 'app-post-detail',
templateUrl: './post-detail.component.html',
styleUrls: ['./post-detail.component.css']
})
export class PostDetailComponent implements OnInit {
body: string;
recent: {};
constructor(
private route: ActivatedRoute,
private router: Router,
private http: HttpClient,
) { }
ngOnInit() {
let id = this.route.snapshot.paramMap.get('id');
let userId = this.route.snapshot.paramMap.get('userid');
this.getUserPosts(userId);
this.http.get('https://jsonplaceholder.typicode.com/posts/'+id)
.subscribe((data)=>{
this.body = data.body;
});
}
}
I dont know Why I am getting this error and I assign the type as string in the class based on the syntax.
Response of API as below,
(data)=>{
this.body = data.body;
}
data is not json. You need to run .json() on data. Or you could run map before subscribe:
this.http.get('https://jsonplaceholder.typicode.com/posts/'+id)
.map(res => res.json())
.subscribe((data)=>{
this.body = data.body;
});
In order to use map, you need to import it:
import 'rxjs/add/operator/map'
See more examples here: https://angular.io/api/http/Http
EDIT:
The response is typed - you need to create an interface for the response:
interface SomeResponse {
Body: SomeType;
}
And make the request like this:
this.http.get<SomeResponse>'https://jsonplaceholder.typicode.com/posts/'+id)
.subscribe((data)=>{
this.body = data.body;
});
Again, more examples here: https://codingthesmartway.com/angular-4-3-httpclient-accessing-rest-web-services-with-angular/