I have a blog feed in my Angular App connected with Contentful. Thanks to the Contentful javascript sdk.
https://www.contentful.com/developers/docs/javascript/tutorials/using-contentful-in-an-angular-project/
I'm trying to display the Title and the Text field. Here is my code:
import { Component, OnInit } from '#angular/core';
import {Observable} from 'rxjs';
import {ContentfulService} from '../../services/contentful/contentful.service';
import { Entry } from 'contentful';
#Component({
selector: 'app-blog',
templateUrl: './blog.component.html',
styleUrls: ['./blog.component.scss']
})
export class BlogComponent implements OnInit {
private posts: Entry<any>[] = [];
constructor(private postService: ContentfulService) {}
ngOnInit() {
this.postService.getPosts()
.then(posts => {
this.posts = posts;
console.log(this.posts);
});
}
}
And the html:
<div *ngFor="let post of posts">
{{ post.fields.title }}
<div>{{ post.fields.text }}</div>
</div>
The title field is displayed well because it is just a string field but the text field is RichText and display [object Object].
Indeed it contain several object. It seems like the Object is divided in several pieces.
https://www.contentful.com/developers/docs/concepts/rich-text/
Does somebody have already display Contentful RichText in an Angular App ?
Is there a specific way to do it?
First, you must install rich-text-html-renderer from your terminal:
npm install #contentful/rich-text-html-renderer
Then, you can import it from your Component:
import { documentToHtmlString } from '#contentful/rich-text-html-renderer';
and use it, simply like that:
_returnHtmlFromRichText(richText) {
if (richText === undefined || richText === null || richText.nodeType !== 'document') {
return '<p>Error</p>';
}
return documentToHtmlString(richText);
}
Finally, 'call the function' from your html like so:
<div [innerHtml]="_returnHtmlFromRichText(post.fields.text)">
</div>
You can also add some options to customise your rich text, more information here. Also, you should code a function similar to _returnHtmlFromRichText in your Contentful service to be able to reuse it later.
I created an Angular library that can render rich text using Angular components: https://github.com/kgajera/ngx-contentful-rich-text
Why use this over #contentful/rich-text-html-renderer? If you need to customize the default mark-up, it allows you to use your Angular components which you can't do using the documentToHtmlString function and [innerHTML].
Related
sorry about my english.
I use sessionstorage for keeping data. In sessionstorage have data enter image description here
but in html, not showing data form sessionstorage. when I get only {{currentUser}} in html show like this enter image description here
mycode services
import { Injectable } from '#angular/core';
const USER_KEY = 'auth-user';
#Injectable({
providedIn: 'root'
})
export class TokenStorageService {
constructor() { }
signOut(): void {
window.sessionStorage.clear();
}
public saveUser(user: any): void {
window.sessionStorage.removeItem(USER_KEY);
window.sessionStorage.setItem(USER_KEY, JSON.stringify(user));
}
public getUser(): any {
const user = window.sessionStorage.getItem(USER_KEY);
if (user) {
return JSON.parse(user);
}
return {};
}
}
html
<div class="container" *ngIf="currentUser; else loggedOut">
<header class="jumbotron">
<h3>
<strong>{{ currentUser.employee_code }}</strong> Profile
</h3>
</header>
<p>
<strong>Token:</strong>
{{ currentUser.accessToken.substring(0, 20) }} ...
{{ currentUser.accessToken.substr(currentUser.accessToken.length - 20) }}
</p>
<p>
<strong>Emp:</strong>
{{ currentUser }}
</p>
</div>
{{ currentUser }}
<ng-template #loggedOut>
Please login.
</ng-template>
and component
import { Component, OnInit } from '#angular/core';
import { TokenStorageService } from '../../../services/token-storage.service';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
currentUser: any;
constructor(private token: TokenStorageService) { }
ngOnInit(): void {
this.currentUser = this.token.getUser();
console.log(this.currentUser = this.token.getUser())
}
}
how i can do to use please help me
this image for {{ currentUser|json}}
{{ currentUser|json}}
In TokenStorageService change getUser() method.
public getUser(): any {
return JSON.parse(window.sessionStorage.getItem(USER_KEY));
}
In HTML you are printing {{ currentUser }} Which will be an object. You need to specify the property of object.
Note: If you want to see the object in html use json pipe. ({{ currentUser | json }})
if I could see it correctly in your attached image, It is an array not an object, so you will need to use it like currentUser[0], to check it on your own please use
{{ currentUser | json}} in HTML it will show the exact content.
Hi, I have created a similar app with the source code provided by you stackblitz link here. I have made some modifications to mimic the login scenario.
You should be able to see the data on the initial load of the data. As the component is being initialized for the first time. But whereas when you change the user with the change user button. Although the session storage data changes. You won't be able to see the new data. In order to see these kinds of dynamic changes, you need to make use of Observables/Subjects.
Edit 1: The issue here was that the key & value stored in the local storage as stored as strings. So while storing we have to do JSON.Stringify() and JSON.Parse() while extracting back. This is explained in detail here.
I want to use the PrimeNG autocomplete component but it doesn't work as expected. If you type something in the input field, the completeMethod is executed, but the results aren't shown. I tested the completeMethod first and it works fine and filters the array correctly, but the component don't show the suggestion list with my values, instead it shows the loading spinner all the time. After you type something else, press any other key or click elsewhere the results are shown up, but the loading spinner is still there.
I've already searched for solutions, but found nothing useful for my problem. I read there are some common simliar problems with the dropdown click, so i tried to apply these fixes, but it doesn't help me neither.
The Component, which holds the autocomplete, its ChangeDetectionStrategy is set on OnPush
Here is my Code:
Component:
<p-autoComplete
[formControlName]="formName"
[suggestions]="options"
(completeMethod)="filterMethod($event)"
[dropdown]="true"
field="label"
[multiple]="true"
[forceSelection]="true"
[minLength]="3"
(onDropdownClick)="handleDropdownClick($event)"
></p-autoComplete>
Filter Method:
filterMethod(event: { query: string; originalEvent: any }) {
this.service
.getSelectItemsByService(this.id)
.subscribe(options => {
this.options = this.filter(event.query, options).slice();
});
}
private filter(query: string, options: SelectItem[]): SelectItem[] {
return query
? options.filter(value =>
value.label
.toLowerCase()
.trim()
.includes(query.toLowerCase().trim())
)
: options;
}
Thank you in advance!
Created minimal working example with API calling please refer it. Start typing with minimum 3 chars and you will get filtered list with dropdown
html
<p-autoComplete
[suggestions]="options"
(completeMethod)="filterMethod($event)"
[dropdown]="true"
field="title"
[multiple]="true"
[forceSelection]="true"
[minLength]="3"></p-autoComplete>
ts
import { Component } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
options = [];
constructor(public http: HttpClient) {
}
filterMethod(event) {
this.http.get('https://jsonplaceholder.typicode.com/todos')
.subscribe(res => {
const result = (<any>res).filter(option => option.title.includes(event.query));
console.log(result);
this.options = result;
});
}
}
You can refer this example: http://keepnote.cc/code/p-auto-complete-with-api-calling-example
The Component, which held the autocomplete Component, it‘s ChangeDetectionStrategy was set on OnPush and this caused the problem. Because of that the PrimeNg autocomplete couldn‘t update the view properly.
I solved it by either removing the OnPush strategy and leave it on Default or calling the ChangeDetectorRefs markForCheck() in Observables subscribe.
I have an angular2 application and i have implemented the Registration and Login Modules. User role and other details are received when login in. Have no idea on how to properly manage access, based on the role of the user.
At the moment i'm hoping to use a Angular2 service to share the user role and other details through out the application and use "if" conditions to manage access, based on the Role.
Please provide me any information on how to properly do this.
I would approach this by building out an object to read from when the user is successfully logged in.
// when user logs in build out permissions object
permissions = {
dashboardOne: true,
dashboardTwo: true
}
then within your auth service, have a function that returns a boolean based on the user's permissions
userHasAccess = (() =>{
return {
toDashboardOne: () => {
return this.permissions.hasOwnProperty('dashboardOne');
},
toDashboardTwo: () => {
return this.permissions.hasOwnProperty('dashboardTwo');
}
}
})();
now throughout the app you can call the above function
if(this._authService.userHasAccess.toDashboardOne()){
// do something
}
I hope this helps get you started. cheers
You can try to use ngx-permissions library for controlling of permissions and roles in your angular application. The benefits it will remove elements from DOM, lazy loading and isolated modules supported(then, else syntax is supported).
Example of loading roles
import { Component, OnInit } from '#angular/core';
import { NgxPermissionsService } from 'ngx-permissions';
import { HttpClient } from '#angular/common/http';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
title = 'app';
constructor(private permissionsService: NgxPermissionsService,
private http: HttpClient) {}
ngOnInit(): void {
NgxRolesService
.addRole('ROLE_NAME', ['permissionNameA', 'permissionNameB'])
NgxRolesService.addRole('Guest', () => {
return this.sessionService.checkSession().toPromise();
});
NgxRolesService.addRole('Guest', () => {
return true;
});
}
}
Usage in templates
<ng-template [ngxPermissionsOnly]="['ADMIN']" (permissionsAuthorized)="yourCustomAuthorizedFunction()" (permissionsUnauthorized)="yourCustomAuthorizedFunction()">
<div>You can see this text congrats</div>
</ng-template>
<div *ngxPermissionsOnly="['ADMIN', 'GUEST']">
<div>You can see this text congrats</div>
</div>
<div *ngxPermissionsExcept="['ADMIN', 'JOHNY']">
<div>All will see it except admin and Johny</div>
</div>
for more information see wiki page
I'm got a couple of (beginner?) problems with my Angular2 app. Firstly a DI works for one component, but not another, and I cant see any problem.
I've got a cocktail component that includes a starring functionality, and a list of ingredients. All code below is stripped down, and it all runs fine (no console errors) - I'm just not getting the desired output
Heres the cocktail.component.ts:
import { Component } from '#angular/core'
import { CocktailService } from './cocktail.service'
import { HttpModule } from '#angular/http';
import { Observable } from 'rxjs/Rx';
#Component({
selector: 'cocktails',
templateUrl: 'app/cocktail.template.html',
providers: [CocktailService, HttpModule]
})
export class CocktailsComponent {
title: string = "Sunday Brunch Specials";
cocktails;
isStarred = false;
numLikes = 10;
ingredient_json = "Bob"; // for testing
constructor(private _cocktailService: CocktailService) {
this.cocktails = _cocktailService.getCocktails();
}
}
And the cocktail.template.html....
<h2>{{title}}</h2>
<input type="text" autoGrow />
<ul>
<li *ngFor="let cocktail of cocktails | async">
<h3>{{cocktail.name}}</h3>
<star [is-starred]="isStarred" [num-likes]="numLikes" (change)="onStarredChange($event)"></star>
<ingredients [ingredient-json]="ingredient_json"></ingredients>
<li>
The star component is getting passed isStarred and numLikes properly - all good.
Now in the ingredient component:
import {Component, Input} from '#angular/core';
import {IngredientService} from './ingredient.service';
#Component({
selector: 'ingredients',
template: '
<h4>Ingredients</h4>
<ul>
<li *ngFor="let ingredient of ingredients">{{ingredient}}</li>
</ul>'
)}
export class IngredientsComponent {
#Input('ingredient-json') ingredient_json = "Hello";
title: 'Ingredients';
ingredients;
constructor() {
// Why isn't ingredient_json outputting anything but hello? Ie nothing is going into input
console.log("Ingredient JSON = " + this.ingredient_json);
}
}
The problem I've stated in comments. The ingredient_json variable just isn't instantiated from the #Input. I'm not getting any errors, the console just always prints out 'Hello' - ie the default. The #Input isn't grabbing anything from its parent (cocktail.component.ts).
I havent included all the app, as I feel as though something is amiss in these 3 files. Like I said, the DI works on the component, so I know that the DI works, but I can't see whats wrong in my code below.
Thanks a lot
Constructor is invoked before the #input() params are passed to a component.
Implement the method ngOnChanges() in your IngredientsComponent and move your console.log() there.
Details here: https://angular.io/docs/ts/latest/api/core/index/OnChanges-class.html
I have angular 2 application written on javascript. I want to migrate it to typescript.
JS code is:
(function (app) {
app.SomeService = ng.core
.Class({
constructor: [app.AnotherService, function SomeService(s) {
this._anotherService = s;
}],
someFunction: function(){
...
}
.....
});
})
(window.app || (window.app = {}));
I want to inject this service into my typescript component. How can I do that?
I tried to use it like this:
#Component({...})
export class SomeComponent {
constructor(public someService: window.app.SomeService) {
}
}
But it does not work.
The way I've managed to mix JS and TS is to have a file with the JS, in your case let's say it's src/app.js , with the code you posted above.
At this point you can do one of two things:
You create a component that is going to use said JS code, something like:
import {Component} from "angular2/core";
#Component({
selector: 'app',
template: ` <a> <onclick='app()'>When the function is clicked, use app() code</a>
,
directives: []
})
export class App {
constructor(){
}
}
The template is going to depend on what your code is supposed to do. I often use onClick, but here you have an example of what it might look like:
template: `<input value="Select Date" type="text" class="datepicker" onclick ="myCalendar()" >
`
Another option is to call the JS code from the constructor
import {Component} from 'angular2/core';
#Component({
selector: 'app',
template: `
<div>
</div>
`,
directives: []
})
export class MyApp {
name:string;
constructor() {
this.name='Angular 2';
app();
}
}
So it depends on what you want to do, and when, as far as I can tell. There are people with more experience but I tried to not say anything wrong, and provide code similar to what I have working right now.