Angular: pass JSON data to child component - javascript

I have a paragraph and app component, and a JSON file:
app component:
//app.component.ts
import { Component, OnInit } from '#angular/core';
import * as data from 'JsonDataSample1.json'
#Component({
selector: 'app-root',
template: `<app-paragraph [value]='json.caseFileID'></app-paragraph>`,
})
export class AppComponent{
json = data
title = 'af-bifurcated';
}
paragraph component:
//paragraph.component.ts
import { Component, Input } from '#angular/core';
#Component({
selector: 'app-paragraph',
template: `{{ value }}`,
styleUrls: ['./paragraph.component.css']
})
export class ParagraphComponent {
#Input() value: string;
}
JSON:
{
"caseFileID": "1234567",
"pdaSubmitterEntity": "Submitter 1",
"propertyDataCollectorName": "Data Collector 1",
"propertyDataCollectorType": "APPRAISER",
"stateCredentialID": "007",
"licenseState": "CA",
"licenseExpiration": "09\/18\/2019"
}
When I try to pass the imported JSON object to the child component, nothing displays. But if instead of importing the JSON, I copy it and hardcode the value of json as equal to whatever I copy from the file, the code works. What am I doing wrong here? Why can't I pass the imported JSON?
UPDATE
I have found that in order to get the JSON file properly imported I had to add the following to my tsconfig.json:
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true,
...
}

To achieve expected result, use correct path jsondatasample1.json file
import * as data from './JsonDataSample1.json'
Sample working code for reference- https://stackblitz.com/edit/angular-f1hxf9?file=src/app/app.component.ts

I have found that in order to get the JSON file properly imported I had to add the following to my tsconfig.json:
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true,
...
}

Related

Ag-grid custom tool tip component doesn't work

My custom tooltip is pretty simple
custom.ts file
import { Component } from '#angular/core';
import {ITooltipAngularComp} from 'ag-grid-angular';
#Component({
selector: 'app-custom-columnheader-tooltip-component',
templateUrl: './custom-columnheader-tooltip-component.html',
styleUrls: ['./custom-columnheader-tooltip-component.css']
})
export class CustomColumnheaderTooltipComponent implements ITooltipAngularComp {
private params: any;
agInit(params): void {
console.log("test tooltip");
this.params = params;
}
}
custom.html file:
{{params.value}}
I imported the component in app.module.ts file and added it as part of declarations and withComponents
app.module.ts file:
import {CustomColumnheaderTooltipComponent} from '...';
declarations: [
CustomColumnheaderTooltipComponent],
imports: [AgGridModule.withComponents([CustomColumnheaderTooltipComponent])]
my main component which calls this custom tooltip is as follows:
main.ts
frameworkComponents = {
customTooltip: CustomColumnheaderTooltipComponent}
IN my default col Definitions:
defaultColDef: ColDef = {
enableRowGroup: true,
filter: true,
resizable: true,
sortable: true,
autoHeight: true,
valueFormatter: this.cellValueFormatter.bind(this), // numeric formatting
cellRenderer: this.cellRenderer,
headerTooltip: 'hi',
tooltipComponent:'customTooltip'
};
I was hoping the header tooltip string will be picked up by the tool tip component and it is displayed as a part of that component as 'header name: hi' but my application just displays 'hi' as the tool tip. I cant see the console logging within the agInit() , basically it doesn't connect to that component for the tool tip. Any suggestions are highly appreciated.
Looks like you have problem in registering your custom tooltip
In my app.module.ts
I would do something like below -
imports: [
BrowserModule,
FormsModule,
AgGridModule.withComponents(
[CustomColumnheaderTooltipComponent]
)
],
declarations: [
............,
CustomColumnheaderTooltipComponent,
...........
],
Check this github example from official ag grid doc

Angular 5 Service to read local .json file

I am using Angular 5 and I've created a service using the angular-cli
What I want to do is to create a service that reads a local json file for Angular 5.
This is what I have ... I'm a bit stuck...
import { Injectable } from '#angular/core';
import { HttpClientModule } from '#angular/common/http';
#Injectable()
export class AppSettingsService {
constructor(private http: HttpClientModule) {
var obj;
this.getJSON().subscribe(data => obj=data, error => console.log(error));
}
public getJSON(): Observable<any> {
return this.http.get("./assets/mydata.json")
.map((res:any) => res.json())
.catch((error:any) => console.log(error));
}
}
How can I get this finished?
First You have to inject HttpClient and Not HttpClientModule,
second thing you have to remove .map((res:any) => res.json()) you won't need it any more because the new HttpClient will give you the body of the response by default , finally make sure that you import HttpClientModule in your AppModule
:
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs';
#Injectable()
export class AppSettingsService {
constructor(private http: HttpClient) {
this.getJSON().subscribe(data => {
console.log(data);
});
}
public getJSON(): Observable<any> {
return this.http.get("./assets/mydata.json");
}
}
to add this to your Component:
#Component({
selector: 'mycmp',
templateUrl: 'my.component.html',
styleUrls: ['my.component.css']
})
export class MyComponent implements OnInit {
constructor(
private appSettingsService : AppSettingsService
) { }
ngOnInit(){
this.appSettingsService.getJSON().subscribe(data => {
console.log(data);
});
}
}
For Angular 7, I followed these steps to directly import json data:
In tsconfig.app.json:
add "resolveJsonModule": true in "compilerOptions"
In a service or component:
import * as exampleData from '../example.json';
And then
private example = exampleData;
You have an alternative solution, importing directly your json.
To compile, declare this module in your typings.d.ts file
declare module "*.json" {
const value: any;
export default value;
}
In your code
import { data_json } from '../../path_of_your.json';
console.log(data_json)
I found this question when looking for a way to really read a local file instead of reading a file from the web server, which I'd rather call a "remote file".
Just call require:
const content = require('../../path_of_your.json');
The Angular-CLI source code inspired me: I found out that they include component templates by replacing the templateUrl property by template and the value by a require call to the actual HTML resource.
If you use the AOT compiler you have to add the node type definitons by adjusting tsconfig.app.json:
"compilerOptions": {
"types": ["node"],
...
},
...
Assumes, you have a data.json file in the src/app folder of your project with the following values:
[
{
"id": 1,
"name": "Licensed Frozen Hat",
"description": "Incidunt et magni est ut.",
"price": "170.00",
"imageUrl": "https://source.unsplash.com/1600x900/?product",
"quantity": 56840
},
...
]
3 Methods for Reading Local JSON Files
Method 1: Reading Local JSON Files Using TypeScript 2.9+ import Statement
import { Component, OnInit } from '#angular/core';
import * as data from './data.json';
#Component({
selector: 'app-root',
template: `<ul>
<li *ngFor="let product of products">
</li>
</ul>`,
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
title = 'Angular Example';
products: any = (data as any).default;
constructor(){}
ngOnInit(){
console.log(data);
}
}
Method 2: Reading Local JSON Files Using Angular HttpClient
import { Component, OnInit } from '#angular/core';
import { HttpClient } from "#angular/common/http";
#Component({
selector: 'app-root',
template: `<ul>
<li *ngFor="let product of products">
</li>
</ul>`,
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
title = 'Angular Example';
products: any = [];
constructor(private httpClient: HttpClient){}
ngOnInit(){
this.httpClient.get("assets/data.json").subscribe(data =>{
console.log(data);
this.products = data;
})
}
}
Method 3: Reading Local JSON Files in Offline Angular Apps Using ES6+ import Statement
If your Angular application goes offline, reading the JSON file with HttpClient will fail. In this case, we have one more method to import local JSON files using the ES6+ import statement which supports importing JSON files.
But first we need to add a typing file as follows:
declare module "*.json" {
const value: any;
export default value;
}
Add this inside a new file json-typings.d.ts file in the src/app folder.
Now, you can import JSON files just like TypeScript 2.9+.
import * as data from "data.json";
import data from './data.json';
export class AppComponent {
json:any = data;
}
See this article for more details.
Try This
Write code in your service
import {Observable, of} from 'rxjs';
import json file
import Product from "./database/product.json";
getProduct(): Observable<any> {
return of(Product).pipe(delay(1000));
}
In component
get_products(){
this.sharedService.getProduct().subscribe(res=>{
console.log(res);
})
}
Using Typescript 3.6.3, and Angular 6, none of these solutions worked for me.
What did work was to follow the tutorial here which says you need to add a small file called njson-typings.d.ts to your project, containing this:
declare module "*.json" {
const value: any;
export default value;
}
Once this was done, I could simply import my hardcoded json data:
import employeeData from '../../assets/employees.json';
and use it in my component:
export class FetchDataComponent implements OnInit {
public employees: Employee[];
constructor() {
// Load the data from a hardcoded .json file
this.employees = employeeData;
. . . .
}
Let’s create a JSON file, we name it navbar.json you can name it whatever you want!
navbar.json
[
{
"href": "#",
"text": "Home",
"icon": ""
},
{
"href": "#",
"text": "Bundles",
"icon": "",
"children": [
{
"href": "#national",
"text": "National",
"icon": "assets/images/national.svg"
}
]
}
]
Now we’ve created a JSON file with some menu data. We’ll go to app component file and paste the below code.
app.component.ts
import { Component } from '#angular/core';
import menudata from './navbar.json';
#Component({
selector: 'lm-navbar',
templateUrl: './navbar.component.html'
})
export class NavbarComponent {
mainmenu:any = menudata;
}
Now your Angular 7 app is ready to serve the data from the local JSON file.
Go to app.component.html and paste the following code in it.
app.component.html
<ul class="navbar-nav ml-auto">
<li class="nav-item" *ngFor="let menu of mainmenu">
<a class="nav-link" href="{{menu.href}}">{{menu.icon}} {{menu.text}}</a>
<ul class="sub_menu" *ngIf="menu.children && menu.children.length > 0">
<li *ngFor="let sub_menu of menu.children"><a class="nav-link" href="{{sub_menu.href}}"><img src="{{sub_menu.icon}}" class="nav-img" /> {{sub_menu.text}}</a></li>
</ul>
</li>
</ul>
For me, it didn't work when I try to import the data file. instead, I have moved the data file to the assets folder and tried to access it through get request.
public getProjectTree()
{
return this.http.get("assets/data.json");
}

Injection Token in Angular for Cesium.js

I'm trying to use the cesium.js library the angular way so that I can still code in typescript, I have seen some 3rd party lib tutorials, and I'm trying to inject the dependency with a dependencty token. right now, my code is not compiling, and I'm getting the error:
ERROR in ....../node_modules/cesium/Build/Cesium/Cesium.js (557,23102): Unreachable code detected.
ERROR in ....../node_modules/cesium/Build/Cesium/Cesium.js (557,24518): Unreachable code detected.
ERROR in ....../node_modules/cesium/Build/Cesium/Cesium.js (559,26990): Unreachable code detected.
I have a stack blitz with all the necessary code, but stack blitz can't handle all the dependencies to run and get the above error, so feel free to copy the code into your own environment.
my stack blitz 'demo' and here is the tutorial I followed
here are the raw files for reference as well.
This project is build with angular-cli
I started by running npm install --save cesium
cesium.lib.ts
import { InjectionToken } from '#angular/core';
import * as cesiumLib from '../../../node_modules/cesium/Build/Cesium/Cesium.js';
export const cesiumToken = new InjectionToken('cesium');
export const cesium = cesiumLib;
export type Cesium = typeof cesiumLib;
export * from 'cesium';
gobe.module.ts
import { GlobeComponent } from './globe.component';
import { CommonModule } from '#angular/common';
import { NgModule } from '#angular/core';
import * as cesiumLib from './cesium.lib';
#NgModule({
declarations: [
GlobeComponent
],
imports: [
],
providers: [
{ provide: cesiumLib.cesiumToken, useValue: cesiumLib.cesium}
]
})
export class GlobeModule {}
globe.component.ts
import { cesium, cesiumToken } from './cesium.lib';
import { Component, Inject, OnInit, ViewEncapsulation, AfterViewInit, ViewChild, ElementRef } from '#angular/core';
#Component({
selector: 'app-globe',
templateUrl: './globe.component.html',
styleUrls: ['./globe.component.css'],
encapsulation: ViewEncapsulation.None
})
export class GlobeComponent implements OnInit, AfterViewInit {
constructor( #Inject(cesiumToken) private cesium: any) {
}
ngAfterViewInit() {
this.viewer = new Cesium.viewer('cesiumContainer')
}
}
globe.component.html
<div id="cesiumContainer"></div>
globe.component.css
#import url(../Build/Cesium/Widgets/widgets.css);
#cesiumContainer {
width: 100%;
height: 720px;
margin: 0; padding: 0;
overflow: hidden;
}
tsconfig.json
{
"compileOnSave": false,
"compilerOptions": {
"allowJs": true,
"outDir": "./dist/out-tsc",
"baseUrl": "src",
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es5",
"typeRoots": [
"node_modules/#types"
],
"lib": [
"es2016",
"dom"
]
}
}
.angular-cli.json snippet
"styles": [
"../node_modules/bootstrap/dist/css/bootstrap.min.css",
"../node_modules/bootstrap-switch/dist/css/bootstrap3/bootstrap-switch.min.css",
"styles.css",
"../node_modules/font-awesome/css/font-awesome.css",
"../node_modules/cesium/Build/Cesium/Widgets/widgets.css"
],
"scripts": [
"../node_modules/jquery/dist/jquery.min.js",
"../node_modules/bootstrap-switch/dist/js/bootstrap-switch.min.js",
"../node_modules/cesium/Build/Cesium/Cesium.js"
___UPDATE______
after making changes from #Justin Shwartzenberger
the compiler is successful but the page loads continuously until if fails... ideas? this occurs once I add the script and css to the .angular-cli.json file
In the .angular-cli.json file under the apps array first object add:
(to bring in the 3rd party css and js files needed)
"styles": [
"styles.css",
"../node_modules/cesium/Build/Cesium/Widgets/widgets.css"
],
"scripts": [
"../node_modules/cesium/Build/Cesium/Cesium.js"
],
In your cesium.lib.ts file just have:
(to create the InjectionToken only, everything else is global from that Cesium lib as it doesn't appear to be able to be imported)
import { InjectionToken } from '#angular/core';
export const cesiumToken = new InjectionToken('cesium');
In your typings.d.ts add:
(so TypeScript knows about the Cesium thing)
declare var Cesium: any;
In your app.module.ts set up:
(only need to bring in the token and then set its value to the Cesium global that the 3rd party lib creates)
import {cesiumToken} from './cesium.lib';
. . .
providers: [
{ provide: cesiumToken, useValue: Cesium }
],
. . .
And finally, in your app.component.ts:
(just need to get that token value injected into a class field and then use the API of it from there)
. . .
constructor( #Inject(cesiumToken) private cesium: any) {}
. . .
ngAfterViewInit() {
this.viewer = new this.cesium.Viewer('cesiumContainer');
}
. . .
You can go further with creating typings for the Cesium lib and encapsulating more from here, but this should get you up and working.

Call Angular Component method from an imported library

Here is my Angular component:
import { basketModule } from './wind'
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
constructor(){
}
ngOnInit(){
basketModule.init()
}
public dataMain(){
alert('hi')
}
}
Here is the wind.js file which is imported above.
export var basketModule = (function () {
return {
init: function(){
dataMain()
}
}
})();
When I run the above code, it returns an error that
core.es5.js:1020 ERROR ReferenceError: dataMain is not defined
How to access the Angular component method dataMain from the imported library ?
If you're using AngularCLI, you will need to add that file to the scripts section of the angular-cli.json file.
"scripts": [
// path to script here in quotes
],
And regardless of whether you're using angular cli, make sure the 'allowJs' flag in your tsconfig.json file is set to true.
{
"compilerOptions": {
"target": "es5",
"sourceMap": true,
"allowJS": true // this one
}
}
Then try importing the library in your component
import * as wind from './path/to/lib/wind.js'
Now you should be able to access that libraries functions using the 'wind' name
wind.dataMain();
If you want an A file methode in a B file so you should import A in B
But you should put your methode in a service and then import service in wind.js

Angular DI in a hybrid boostrapped application

I have a sizable AngularJS (aka Angular 1) application that is written in Typescript. I've decided that new features should be written in Angular (aka Angular 4) and have taken the steps to boostrap the app in "hybrid mode".
This seems to work (all the AngularJS bits work fine) and I've added a single Angular component and that renders fine.
The problem comes when I try to add an Angular service to my Angular (so all Angular 4 so far). Angular fails to work, spitting out the seemlying ubiquitous
Can't resolve all parameters for... error.
However, if I mark the type in the components constructor with #Inject then it works ok.
All the documentation points to the fact I should not need to use #Inject routinely, so why is this failing?
My medium term need to is inject AngularJS services into the Angular components and services, and this situation isn't filling me with confidence.
app.module.ts:
// All AngualarJS definitions appear before this section.
#NgModule({
imports: [
BrowserModule,
UpgradeModule,
],
declarations: [
AppComponent,
OrgSummaryComponent
],
providers: [
OrgDetailsService,
],
bootstrap: [
AppComponent,
],
})
export class AppModule {
ngDoBootstrap() {
// Does nothing by design.
// This is to facilitate "hybrid bootstrapping"
}
}
platformBrowserDynamic().bootstrapModule(AppModule).then(platformRef => {
const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
upgrade.bootstrap(document.body, [AppModuleName], {strictDi: true});
});
org-details.service.ts:
import {Injectable} from "#angular/core";
export class OrgDetails {
public orgName: string;
}
#Injectable()
export class OrgDetailsService {
getOrgDetails () : OrgDetails {
const od = new OrgDetails();
od.orgName = "Some Org Name from a REST service";
return od;
}
}
org-summary.component.ts:
import {Component, Inject, OnInit} from "#angular/core";
import {OrgDetailsService} from "./org-details.service";
#Component ({
selector: "orgsummary",
template: "<h2>{{OrgName}}</h2>",
})
export class OrgSummaryComponent implements OnInit {
constructor (
/*#Inject(OrgDetailsService)*/ private orgs: OrgDetailsService, // Only works if I uncomment the #Inject
) {
}
public OrgName: string;
ngOnInit(): void {
this.OrgName = `${this.orgs.getOrgDetails().orgName}`;
}
}
tsconfig.json:
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"sourceMap": true,
"noImplicitAny": true,
"declaration": true,
"experimentalDecorators": true
},
"exclude": [
"node_modules",
"**/*.spec.ts"
],
"include" : [
"app/**/*.ts"
]
}
Many thanks,
Jeff
Just add
"emitDecoratorMetadata": true
to your tsconfig.json

Categories