JSON pipe in Angular 2 is not working - json

When I try to pipe my data by JSON pipe I get the following error in the console:
Unhandled Promise rejection: Template parse errors:
The pipe 'json' could not be found (...
What am I doing wrong?

Most likely you forgot about importing CommonModule:
import { CommonModule } from '#angular/common';
#NgModule({
...
imports: [ CommonModule ]
...
})
As noted in the comments, do this in the module where you're using the json pipe.

In my case CommonModule was added, but the component was not part of declaration of any module
(I was creating component dynamically by using ContainerRef)

Your parent Module of the component should be like this.
import {NgModule} from '#angular/core';
import {AuditTrailFilterComponent} from './components/audit-trail-filter/audit-trail-filter.component';
import {CommonModule} from '#angular/common'; <-- This is important !!!!
#NgModule({
imports: [
CommonModule, <-- This is important !!!!
],
declarations: [AuditTrailFilterComponent],
exports: [
AuditTrailFilterComponent
]
})
export class AuditTrailModule {
}

This can also occur if you declare your component in a Lazy module and try to add the component to a route that hasn't caused that module to be loaded.
eg. I just had this error with:
children: [
{
path: 'editor',
loadChildren: () => from(import(/* webpackChunkName: "editor" */ '../editor/editor.module').then(m => m.EditorModule))
},
{
path: 'multi-preview',
component: MultiPreviewerComponent // declared in Editor.module (lazy loaded)
}
]

For me,
I had to add it on the under the providers in the app.module.ts
#NgModule({
providers: [
{ provide: JsonPipe }, <-- This is important !!!!

Related

Cypress not picking up html elements

I'm trying to get a handle on a simple html <p> tag using the data-cy attribute:
<p data-cy="register">Register</p>
First I mount the component:
it('mounts', () => {
cy.mount(AccountDialogComponent, {
imports: [
HttpClientTestingModule,
ReactiveFormsModule,
AngularMaterialModule,
BrowserAnimationsModule
],
declarations: [ AccountDialogComponent ],
providers: [{provide: AccountService, useValue: accountService}]
})
});
The test I am running for this as follows:
it("text should be 'Register' when user is registering", () => {
cy.get('[data-cy="register"]').should('have.text', 'Register');
});
The test keeps returning a failure:
assertexpected [data-cy="register"] to have text Register, but the
text was ''
After another few seconds, it then returns an Assertion Error:
Timed out retrying after 4000ms: Expected to find element: [data-cy="register"], but never found it.
I can't understand why this isn't working?
I am new to Cypress and this is the first test I am dong since installing Cypress in my Angular app.
I had same problem, this Angular - adding Cypress data-cy attribute sorted it out.
The gist is the Angular framework would not pass on data-cy without it's particular binding,
<p [attr.data-cy]="register">Register</p>
Now, test code will find your element.
BTW Component testing is ok if mount() ok, then it's same syntax for test assertions.
Ok so it seems I was just forgetting that I need to mount the component before each test:
beforeEach(async () => {
cy.mount(AccountDialogComponent, {
imports: [
HttpClientTestingModule,
ReactiveFormsModule,
AngularMaterialModule,
BrowserAnimationsModule
],
declarations: [ AccountDialogComponent ],
providers: [{provide: AccountService, useValue: accountService}]
})
});

StaticInjectorError when importing a custom-made Angular library

I've built my own Angular library (called ProcessorModule) and want to use it in other applications. Whenever I import the library however, I get the following error:
StaticInjectorError(AppModule)[StatusComponent -> MainProcessComponent].
NullInjectorError: No provider for MainProcessComponent!
This occurs within the html of MainProcessComponent which has a nested StatusComponent (specifically when I use the 'status' selector:
/* MainProcessComponent.html */
<h2>This is the MainProcessComponent view</h2>
<div>
<status></status>
</div>
This is my processor.module.ts file:
import { NgModule } from '#angular/core';
import { CommonModule } from "#angular/common";
import { FormsModule } from "#angular/forms";
import { HttpClientModule } from "#angular/common/http";
import { MainProcessComponent } from "./components/process.component";
import { StatusComponent } from "./components/status.component";
#NgModule({
imports: [
routing,
CommonModule,
FormsModule,
HttpClientModule
],
exports: [
MainProcessComponent,
ProcessComponent,
StatusComponent
],
declarations: [
MainProcessComponent,
ProcessComponent,
StatusComponent
],
bootstrap: [
]
})
export class ProcessorModule { }
I build/pack a .tgz file for ProcessorModule and import it into my outside application using
import { ProcessorModule} from "processor-module";
Within the imports section of #NgModule I add:
#NgModule({
imports: [
...,
ProcessorModule,
...
]
})
export class OutsideAppModule { }
Keep in mind the above code has been simplified to help illustrate my issue. I thought adding both components to the exports section of processor.module.ts would have solved my problem. Can anyone see what exactly I'm doing wrong?
EDIT: I've added MainProcessComponent to both the 'exports' and 'declarations' section of processor.module.ts but I still get the same error.
MainProcessComponent is not exported in processor.module.ts's exports array.
processor.module.ts
#NgModule({
imports: [..],
exports: [
ProcessComponent,
StatusComponent,
MainProcessComponent // added
],
declarations: [...],
bootstrap: [... ]
})
export class ProcessorModule { }
Figured out my problem - I had some components declared in the constructor of another component (not shown above) that were unused. After removing them everything worked fine.

Show chart at angular 6

I'm following this tutorial to show a chaart from fusionchart at angular 6
But it only is showing this message:
Cannot read property 'moduleObj' of undefined
I've done imported in app.module.ts
import { FusionChartsModule } from 'angular-fusioncharts';
// Import fusioncharts core in the root
import FusionCharts from 'fusioncharts/core';
// Import chart type
import Column2D from 'fusioncharts/viz/column2d'; // Column2D chart
// Import the fusion theme
import FusionTheme from 'fusioncharts/themes/es/fusioncharts.theme.fusion';
import { ChartComponent } from './chart/chart.component'
// Pass the fusioncharts library and chart modules
FusionChartsModule.fcRoot(FusionCharts, Column2D, FusionTheme);
#NgModule({
imports: [ BrowserModule, FormsModule, FusionChartsModule ],
declarations: [ AppComponent, HelloComponent, ChartComponent ],
bootstrap: [ AppComponent ]
})
This is my html:
Meu html está assim:
<fusioncharts
width="700"
height="400"
type="Column2d"
[dataSource]="dataSource">
</fusioncharts>
Here is my stackblitz
I was having the same problem, but later found it out that stackblitz internally tries to compile the code into ES5, however in FusionCharts recent modular build, they are internally using all ES6 module syntax, hence, stackblitz is not able to run the charts, however, if you check the sample locally using Angular CLI it will work fine. Let me know if you need any assistance, I can share a sample if needed.

how to add social share button in angular 4

I have run the command "npm install --save ng2-social-share".
and then add into app.module.ts :-
import { CeiboShare } from 'ng2-social-share';
#NgModule({
imports: [
CeiboShare
]
});
and then i add into my home.component.ts :-
import { CeiboShare } from 'ng2-social-share';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css'],
directives: [CeiboShare]
})
webpack: Compiling...
ERROR in src/app/home/home.component.ts(16,3): error TS2345: Argument of type '{ selector: string; templateUrl: string; styleUrls: string[]; directives: typeof CeiboShare[]; }' is not assignable to parameter of type 'Component'.
Object literal may only specify known properties, and 'directives' does not exist in type 'Component'.
Date: 2018-02-27T09:02:42.288Z - Hash: bedb972b22f9a72ebb59 - Time: 2832ms
5 unchanged chunks
chunk {main} main.bundle.js (main) 367 kB [initial] [rendered]
webpack: Compiled successfully.
The simple way for you is to import in your app.modules.ts like this
1) import {CeiboShare} from 'ng2-social-share';
#NgModule({
declarations: [
AppComponent,
CeiboShare
]
})
2) and then in your home.component.ts
you need to just only define the url sharing link and image url sharing if you want like this:
//vars used only for example, put anything you want :)
public repoUrl = 'https://www.egozola.com';
public imageUrl = 'https://avatars2.githubusercontent.com/u/10674541?v=3&s=200';
the in your home.component.html the you can call sharing easily like this
button ceiboShare [facebook]="{u: repoUrl}">Facebook
Linkedin
Google Plus
Twitter
Pinterest
good all thing is working well
What you could do is to use these functions on your typescript file and call it from the template.
Providing here 5 Social Media Share - Facebook, Pinterest, Twitter, GooglePlus, LinkedIn
// Facebook share won't work if your shareUrl is localhost:port/abc, it should be genuine deployed url
shareOnFacebook(shareUrl: string) {
shareUrl = encodeURIComponent(shareUrl);
window.open(`https://www.facebook.com/sharer/sharer.php?u=${shareUrl}`, 'sharer');
}
shareOnPinterest(shareUrl: string, img: string, desc: string) {
shareUrl = encodeURIComponent(shareUrl);
img = encodeURIComponent(img);
desc = encodeURIComponent(desc);
window.open(`https://www.pinterest.com/pin/create/button?url=${shareUrl}&media=${img}&description=${desc}`, 'sharer');
}
shareOnTwitter(shareUrl: string, desc: string) {
shareUrl = encodeURIComponent(shareUrl);
desc = encodeURIComponent(desc);
window.open(`https://twitter.com/intent/tweet?url=${shareUrl}&text=${desc}`, 'sharer');
}
shareOnGooglePlus(shareUrl: string) {
shareUrl = encodeURIComponent(shareUrl);
window.open(`https://plus.google.com/share?url=${shareUrl}`, 'sharer');
}
// LinkedIn share won't work if your shareUrl is localhost:port/abc, it should be genuine deployed url
shareOnLinkedIn(shareUrl: string, title: string, summary: string) {
shareUrl = encodeURIComponent(shareUrl);
window.open(`https://www.linkedin.com/shareArticle?url=${shareUrl}&title=${title}&summary=${summary}`, 'sharer');
}
Hope this will help you or somebody else.
Thanks!
remove that directives : [CeiboShare] from #component decorator. It is not supported in angular 4 and you don't even need to import it into your component. Just Import into Ngmodule as below,
import { CeiboShare } from 'ng2-social-share';
#NgModule({
imports: [
CeiboShare.forRoot()
]
});
This would suffice to get it working in any component as attribute directives.

Can't set up routing to a named outlet in Angular

I have three named router outlets as shown below.
...
<router-outlet name="menus"><router-outlet>
<router-outlet><router-outlet>
<router-outlet name="footer"><router-outlet>
...
In the markup I want to route the first one, menus, to a component with certain submenu junk in it as shown in the docs.
<ul *ngFor="let main of menus;"
routerLink="[{outlets:{menus:[{{main.link}}]}}]"
class="nav-items">{{main.header}}
The error I'm getting says that:
Error: Cannot match any routes. URL Segment: '%5B%7Boutlets:%7Bmenus:%5Bsubmenu1%5D%7D%7D%5D'
Am at a loss what's wrong with the syntax. Googling my fingernails off but haven't found a simple and crude example of a routerLink version showing how to point a route in a named outlet.
Edit: Based on the comments and samples, I need to reformulate the code being used, still with the same error. In the markup:
<ul *ngFor="let main of menus;"
(click)="pullMenu(main.link)"
class="nav-items">{{main.header}}
Then, in TS:
constructor(private router: Router, private route: ActivatedRoute) { }
pullSubmenu(input) {
console.log(input);
this.router.navigate(
[{ outlets: { menus: [input] } }],
{ relativeTo: this.route });
}
Now, I'm getting the following error (submenu1 is the name of configured path).
Error: Cannot match any routes. URL Segment: 'submenu1'
My routing is set up in the module like this.
const routes: Routes = [
{ path: "submenu1", component: Submenu1Component },
{ path: "submenu2", component: Submenu2Component }
];
#NgModule({
declarations: [
AppComponent,
NavbarComponent,
MainAreaComponent,
Submenu1Component,
Submenu2Component
],
imports: [
BrowserModule,
RouterModule.forRoot(routes)
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
You need to use the evaluated version [routerLink]:
<ul *ngFor="let main of menus;"
[routerLink]="[{outlets:{menus:[{{main.link}}]}}]"
class="nav-items">{{main.header}}
As an alternative you can emulate the routerLink. Here is the gist of what it does:
#HostListener('click')
onClick(): boolean {
const extras = {
skipLocationChange: attrBoolValue(this.skipLocationChange),
replaceUrl: attrBoolValue(this.replaceUrl),
};
this.router.navigateByUrl(this.urlTree, extras);
return true;
}
So, here is the setup using navigate instead of navigateByUrl:
#Component({
template: `
<ul *ngFor="let main of menus;" (click)="[{outlets:{menus:[{{main.link}}]}}])"
class="nav-items">{{main.header}}
`
...
class MyComponent {
constructor(router: Router, route: ActivatedRoute) {}
navigate(commands) {
this.router.navigate(commands, {relativeTo: this.route})
You can't use unevaluated version of routerLink because it reads commands as a string and if you have outletsin the commands strings don't work. See Navigation to secondary route URL for routerLink attribute to understand why.