I'm trying to import a local file to use the data in it.
I have tried the require method and the import method. Neither seems to work.
I'm using Angular 5 and Typescript 2.9.2. I am locked to angular 5.
I'm building for aot and when I look at the fesm5 file that gets exported the json file does not seem to resolve.
(I DO NOT WANT TO PULL IT IN WITH HTTP...)
import * as data from '../../assets/file.json';
When I try to set tsconfig value to:
"resolveJsonModule": true,
I get an error on build:
Cannot read property 'slice' of undefined
TypeError: Cannot read property 'slice' of undefined
at addReferencesToSourceFile (/Users/ME/Projects/PROJECT/node_modules/#angular/compiler-cli/src/transformers/compiler_host.js:520:54)
at TsCompilerAotCompilerTypeCheckHostAdapter.getSourceFile (/Users/ME/Projects/PROJECT/node_modules/#angular/compiler-cli/src/transformers/compiler_host.js:348:13)
I have also tried the:
declare module '*.json' {
const value: any;
export default value;
}
This doesn't seem to help at all.
Also tried:
declare function require(url: string);
var data = require('../../assets/file.json');
This does not seem to resolve the json in the final file either.
You can put your file under assets folder and get it using HTTP GET from HttpClient module, this will return the whole json file, use your file path in your GET request URL; something like this:
this.http.get('../assets/file.json')
.subscribe(jsonFormat => {
//Your code
});
You can create a service for all the GET, POST, PUT& DELETE implementations. Then in your GET method of HttpClient that is imported from ‘#angular/common/http’, call the JSON with the link to your local JSON file.
public getAbout(): Observable<any> {
return this.http.get("./assets/json/about.json");
}
Related
I have a Vue.js 2 project with Typescript. In the main.ts file, I've declared 2 variables, that I've wanted to access globally in my project:
// ...
Vue.prototype.$http = http; // this is the library imported from another file, contains various methods such as `get`, `post` etc.
Vue.prototype.$urls = urls; // this is JSON object, also imported from another file
new Vue({
store,
render: (h) => h(App),
}).$mount('#app');
In one of my components, let's call it User I have following mounted code block:
mounted(): void {
this.$http.get(`${this.$urls.getUser}/${this.userId}`);
}
Everything works fine when I'm running a local server (via npm run serve command), but when I create an app build (via npm run build command) and enter the app on the server (or the index.html file on my hdd) I receive following error:
TypeError: Cannot read property 'get' of undefined
at VueComponent.value (user.ts:62) // <-- this line is the one with $http.get from `mounted` hook
I'm not sure how to proceed with this, I've blindly tried to add those global values to various places e.g. in http.d.ts file I have the following:
import { KeyableInterface } from '#/interfaces/HelperInterfaces';
import Vue from 'vue';
declare module 'vue/types/vue' {
interface VueConstructor {
$http: KeyableInterface;
}
}
declare module 'vue/types/vue' {
interface Vue {
$http: KeyableInterface;
}
}
declare module 'vue/types/options' {
interface ComponentOptions<V extends Vue> {
http?: KeyableInterface
}
}
(I've also created urls.d.ts with similar code)
UPDATE #1:
I've tried also following approach - in my main.ts file:
const helperModules = {
/* eslint-disable-next-line #typescript-eslint/no-explicit-any */
install: (vueInstance: any) => {
vueInstance.prototype.$http = http;
vueInstance.prototype.$urls = urls;
},
};
Vue.use(helperModules);
But it still doesn't work (same error).
UPDATE #2:
I've also imported http utility into my user component, and added following console.log to existing mounted callback:
console.log(http, this.$http)
And while working on my localhost, it returns me twice the same value, but when I create a build it returns me:
Module {__esModule: true, Symbol(Symbol.toStringTag): "Module"}, undefined
Similar thing happens, when I add console.log(urls, this.$urls) - imported module is being logged, while prototyped one returns undefined.
Any thoughts? Will appreciate any help.
Finally I've overcome the problem by moving the prototyping parts from main.ts to App.ts file.
I'm not 100% sure if it's a valid "the Vue.js way" of solving this, as I've always declared that in main.js file - but I was using then JavaScript & it was "just working" as expected.
I am using a json file to load/write some data. This specific JSON file gets changed quite often.
So with this, how can I import this JSON file from inside a Vue.JS method?
Currently I do this:
<script>
import * as settings from '../config/settings.json'
// some other things
</script>
But this only gets the json file once and I am not able to get the updates on the json file anymore.
I tried doing something like this:
methods: {
loadJsonFile () {
import * as settings from '../config/settings.json'
}
}
But it gives an error:
error Parsing error: 'import' and 'export' may only appear at the top level
How can I dynamically get the updates on this json file based on some trigger (e.g. calling of a method)? Only on code level - not allowed to get modules for this.
Thanks
I am attempting to load valid json but I am getting the error:
stackblitz
Http failure during parsing for ... .json
recipe.component.ts
url = '../../files/recipes.json';
recipes;
constructor(private fileService: FileLoaderService) {}
ngOnInit() {
this.fileService.getData(this.url).subscribe(res => console.log(res));
}
file-loader.service.ts
constructor(private http: HttpClient) { }
getData(url: string): Observable<any> {
return this.http.get(url);
}
What you have is not a valid JSON file. epascarello's answer tells you how to convert it to valid JSON, but another option is to just import the data directly.
Change the .json file extension to .ts
In your component, add import {recipes} from '../../files/recipes'
You've got your data! No need to mess around with http requests.
Having the export
export const recipes = [
{...}
]
makes it not a valid json document. Do not use export, remove it
JSON file should just be the json.
[
{...}
]
Couple this wrong and missing here:
This is not a valid JSON file (in the stackblitz). This is a constant which you can just import using a normal typescript import. If you want to load it using http, you should remove the export const recipes from the file
You should move the files folder to the assets folder of the project, this way the file can be loaded from the http server.
I spent a while ripping my hair out today (new to writing in StackBlitz). and even tried what was marked as answer on this thread, with no luck. Anyhow, the key seemed to be adding the .json file to the assets folder. Here's the link that finally got me immediate success. Hope that helps someone else keep their hair in tact. :-)
I've been asked to add code snippet, but not really too much to add, so I created a StackBlitz example that can be viewed, if desired. However, basically it all boils down to this: in StackBlitz when you're loading a local .json file, you do the same thing you normally would...except you ABSOLUTELY put that .json file in the "assets" folder (if you don't have one, create one)
this.http.get('/assets/user.json')
I added a StackBlitz example here
I have the following problem, I get:
"Unable to resolve module nik/env from /some/path/constant.js : Module does not exist in the module map or in these directories /path/to/project/root"
In my constant.js I do try to do the following:
import {
API_URL,
} from 'nik/env'
so I am basically just trying to get a variable (API_URL) out of my env.
However, when I tested this and I replaced the above with a hardcoded variable like so: const API_URL = 'http://my-api.myserver.com';, I still get the same error. Namely, that it cannot resolve nik/env - but there is no reference to nik/env in that file anymore.
Why could this be? Thanks a lot in advance!!
So the code is simple:
calls.json
{"SERVER":{
"requests":{
"one":"1"
}
} }
file.ts
import json = require('../static/calls.json');
console.log(json.SERVER);
the generated javascript is correct and when running the node js server, the console log json.SERVER prints '{ requests: { one: '1' } }', as it should.
The typescript compiler (commonjs) however, somehow does not particularly like this situation and throws: "Cannot find module '../static/calls.json'".
Ofcourse I tried writing a .d.ts file, like this:
declare module '../static/calls.json'{
var exp:any;
export = exp;
}
this then obviously throws: "Ambient module declaration cannot specify relative module name".
I also tried different variants, like:
declare module 'calls.json' {
import * as json from '/private/static/calls.json';
export = json;
}
and then requiring:
import json = require('calls.json');
None work properly and have their own little compiler errors :)
I want to use an external .json file because I use commonjs serverside and amd clientside and I want a single file for loading constants.
Use var instead of import.
var json = require('./calls.json');
You're loading a JSON file, not a module, so import shouldn't be used is this case. When var is used, require() is treated like a normal function again.
If you're using a Node.js definition, everything should just work, otherwise require will need to be defined.
TS 2.9 added support for well typed json imports. Just add:
{
"compilerOptions": {
"resolveJsonModule": true
}
}
in your tsconfig.json or jsconfig.json. Now imports such as:
import json = require('../static/calls.json');
and
import * as json from '../static/calls.json';
should be resolved and have proper typings too!
Another solution is to change data.json to data.ts and export like this
export default {
"key" : {
...
}
}
and import as you would expect:
import { default as data } from './data'
This can also be done by using import statement if using webpack v2 which is already packed with json-loader.
Note that this is not async
import data from './data.json';//Note that this is not async
Also, in your typings.d.ts file add the following wildcard module to avoid typescript error saying: Cannot find module
declare module "*.json" {
const value: any;
export default value;
}
For anyone interested in async imports, check this article by 2uality
As of Typescript 2.9 you can import JSON file natively without any additional hack/loader needed.
The following excerpt is copied from said link above.
...TypeScript is now able to import JSON files as input files when using the node strategy for moduleResolution. This means you can use json files as part of their project, and they’ll be well-typed!
./src/settings.json
{
"dry": false,
"debug":
./src/foo.ts
import settings from "./settings.json";
settings.debug === true; // Okay
settings.dry === 2; // Error! Can't compare a `boolean` and `number`
For Angular 6 it can work with simple HTTP get call as below
Service
//interface, could be Array , object
export interface ResultJSON{
}
//Read JSON file for 3DWide
getJSON() {
return this.http.get(this.filepathUrl);
}
Component :import both service and interface and use as below
resultJSON :ResultJSON;
this
.testService
.getJSON()
.subscribe((data: ResultJSON) => {
this.resultJSON= data;
console.log(this.resultJSON);
});