I have strange problem possibly bug with importing JSON file as object into my application. I do have:
"compilerOptions": {
"resolveJsonModule": true,
"esModuleInterop": true,
}
Looking at the s̶o̶u̶r̶c̶e̶ ̶a̶n̶d̶ source maps JSON is being imported and even when I look at debugger:
But as you see debugger is able to see contents of this var/JSON while app claims it's undefined. Can it be building cache problem?
I import JSON file like:
import * as eventsDB from './events.json';
and for debugging purpose I export it like this:
export const jsonDB = eventsDB;
EDIT: After checking carefuly build whole reducer where I import and export JSON was ommited but for some reason everything was in Source-Maps, I'm currently searching for possible reason.
Guys I've located the problem. I think this might be helpful, so I want to share the solution. As I said in reducer named events (file name events.ts) I've imported the JSON:
import * as eventsDB from './events.json';
And some of you might already noticed the problem. Even when I included the extension, for some reason there was name conflict so under events reducer
import events from '../reducers/events';
I actually had the JSON. And under JSON I had undefined. Still the mistery is why debugger saw the contents of the variable correctly.
Related
In my Angular application, I'd like to display the version from the package.json file.
I know that to import it I need to allow importing json and for this tsconfig.json file needs to get a few extra lines:
{
"compilerOptions": {
"module": "commonjs",
"resolveJsonModule": true,
"esModuleInterop": true,
"moduleResolution": "node"
}
}
I did this, but after that when I import json file in my component class:
import { myPackage } from '../../../package.json';
I still get an error:
Cannot find module '../../../package.json'. Consider using '--resolveJsonModule' to import module with '.json' extension.ts(2732)
And problem is not with path as I put another simple json file to the same folder but getting the same error.
I've googled and seen many examples that speak about '--resolveJsonModule', but it seems like I do all what's needed... but it still does not work.
I also restarted VScode and angular service - it did not help.
I use Angular 10.0.11 and TS 3.9.7
Please advise! Thanks!
In order to access the package.json information in angular, you need to do 3 things
In your tsconfig.json, you need to enable resolveJsonModule option that is present in the compilerOptions like
compilerOptions": {
......
"resolveJsonModule": true
......
}
After that, you can rerun npm start in your terminal.
Once you have rerun npm start, you will be able to access all the package.json variables inside the component as
import * as packageJson from 'package.json';
......
export class AppComponent {
......
version = packageJson.version;
......
}
Deepak posted an almost proper answer, but for some reasons it did not work to me. Though, referenced answer (https://stackoverflow.com/a/48869478/6904274) has comments that actually helped.
In my case, the Angular application had more than just tsconfig.json, and to be able to import JSON files I had to modify other 'flavours': base, spec, and app. And each is responsible for their own thing. Obviously, to have that import work in components under tests, I need to add it to 'spec'. But, better to just 'base'.
I created a React App using the create-react-app npm package. Everything works fine, however I'm not sure how to handle external files.
I created a POC that holds a json object of the entries for a select field. I can import the object and it works properly. However, I'm used to having files like this available on the server so that they can be edited without having to re-build the program.
I converted the file to a .json and I'm able to import it without a problem. However, if I try to move it to the "public" folder, I'm no longer able to import it. If it remains within the src folder it gets included within the bundle and I'm not able to edit it directly.
Is including the file within the bundle the standard way of handling data that can change (whether by requiring update or i18n)??? If not, how do I go about configuring the app to allow me to import it from the public folder once it's deployed?
This should work:
Add data.json to public directory and use fetch in componentDidMount
componentDidMount() {
fetch('data.json').then(data => {
data.json().then(response => {
console.log(response)
this.setState({ data }); // you can set data to state
});
})
}
content of data.json
{
"data": "some data"
}
If you are trying to use some external data e.g. from server, you should not import it like any other files (i.e. import a.js from './a') you should make HTTP request in order to retrieve these data
You will find instructions to reproduce on your own device at the bottom.
I have a basic Angular project I created using Angular CLI, running on TypeScript 3.1.3, with nothing much added aside a class and a json file.
I created a class ResourcesService with the following command with Angular CLI:
ng generate service Resources
I'm basically using it to load json files, as a mean of localising (instead of using Angular unfinished builtin internationalisation features).
The following is my class, as well as the json file:
ResourcesBundle.json
{
"label.changeLanguage": "Change language",
"label.education": "Education",
"label.experience": "Experiences",
"label.skills": "Skills",
"label.summary": "Summary",
"label.language.english": "English",
"label.language.french": "French"
}
resources.service.ts
import * as resources from '../assets/resources/ResourcesBundle.json';
#Injectable({
providedIn: 'root'
})
export class ResourcesService {
constructor() {}
public getString(label: string): string {
let resource: string = resources[label];
return resource;
}
}
Of course, in order to be able to import the json file that way, I've set "resolveJsonModule": true in tsconfig.json.
The service by itself is working properly. I can inject it and call the getString method, and it's running without any error.
However, no matter what value I pass to the getString method, the returned value is always undefined. I've even tried to hard code the value for label = 'label.summary', but it's still returning undefined. The only time it's working properly is when I write the string directly between the brackets:
let resource: string;
label = 'label.summary';
resource = resources[label]; // resource == undefined
resource = resources['label.summary']; // resource == 'Summary'
Within the TS on VSCode, the content of resources is as following:
label.changeLanguage
label.education
label.experience
label.language.english
label.language.french
label.skills
label.summary
When using console.log(resources), the console was displaying something like this on Firefox:
Object {
label.changeLanguage: "Change language"
label.education: "Education"
label.experience: "Experience"
label.language.english: "English"
label.language.french: "French"
label.skills: "Skills"
label.summary: "Summary"
}
So the json is properly loaded, but it can only be used with hard coded string.
The only other solution I found was to give up the json file and initialise an indexed type directly in the code:
private resources: { [key: string]: string } = {
'label.changeLanguage': 'Change language',
'label.education': 'Education',
'label.experience': 'Experiences',
'label.skills': 'Skills',
'label.summary': 'Summary',
'label.language.english': 'English',
'label.language.french': 'French'
};
However, I don't think that's a good approach, at all...
In the case of the imported json file, why does it always return undefined when I use a variable? Or otherwise, why does it work only with a hard coded string between the brackets?
Edit:
You will find below a stackblitz link to a demo project:
https://stackblitz.com/edit/angular-h2aspf?file=tsconfig.json
If you run it on the browser, it will work properly (the console will properly display Change language).
However, if you download it and run it locally, you will notice that the console will display undefined instead.
To run it locally:
You must have npm and Angular CLI
Download and unzip the stackblitz demo in a folder
Run npm i in the project folder
Run ng serve --open
Open the console on your browser, it should be displaying undefined, instead of the expected value (Change language on stackblitz)
Edit:
According to a comment on the Angular CLI issue, a workaround is to set "esModuleInterop": true in tsconfig.json, and to change the import statement from:
import * as resources from '../assets/resources/ResourcesBundle.json';
To this:
import resources from '../assets/resources/ResourcesBundle.json';
Original answer:
After checking multiple times on different devices, I think this is a bug directly related to Angular (current version: 7.0.2).
To take the example I gave in the question again:
https://stackblitz.com/edit/angular-h2aspf?file=tsconfig.json
On the browser, this demo is outputting Change language on the console.
On locale device:
Download and unzip the stackblitz demo in a folder
Run npm i in the project folder
If you run with ng serve, you will notice undefined in the web browser console
Stop Angular, then run again with ng serve --prod. The web browser console is now properly outputting Change language
I've opened the following issues for Angular and Angular CLI projects on GitHub for this problem:
Angular: Issue #26785: Imported json file as indexed type always giving undefined when Angular is not running in production mode
Angular CLI: Issue #12781: Imported json file as indexed type always giving undefined, but not when running ng serve --prod
I am trying to bulid a simple app using Vue / Vuex starting from vue-cli webpack template.
The app works fine but I would like to add the possibility to load and save the state in a JSON file.
Is there a best practice in order to do that ?
My first idea was to read the data into the file store.js
import Vue from 'vue'
import Vuex from 'vuex'
import fs from 'fs'
// Read file
let loaded = null
fs.readFile('./data.json', 'utf8', (err, data) => {
if (err) throw err;
loaded = data;
})
Vue.use(Vuex)
const state = {
notes: loaded,
activeNote: {}
}
...
...
But I am getting error when I try to import fs module.
There are great plugins available for exactly what you're trying to do.
Basically, having Vuex and defining a state is he way to go, however, you should do it a little different.
Take a look at this plugin:
https://github.com/robinvdvleuten/vuex-persistedstate
Since you're using Webpack it is pretty easy to install, use yarn add vuex-persistedstate for example..
Then, you import the plugin using import createPersistedState from 'vuex-persistedState'.
Now you change up your store a little bit, doing something like this:
export const store = new Vuex.Store({
state: {
yourVar: 0
},
mutations: {
changeValue (state, number) {
state.yourVar += number
}
},
plugins: [createPersistedState()]
})
That's basically it. All you need to do is add the plugin line to your Vuex store and all variable data inside your state will be saved in the browsers localStorage by default. Of course, you can read through the GitHub repository to see how you can use sessions, cookies etc, but that should work just fine.
The important part here are your mutations, since everything you want to do with your store variables HAVE to be declared by a mutation function.
If you try to modify your stored variables using ordinary functions, you'll get some warnings. The reason behind this is to ensure that no unexpected mutation of your data will take place, so you have to explicitly define what you want your program to accept in order to change your variables.
Also, using the export const store before your new Vuex.Store allows you to import that state in any of your Vue components and call the mutation functions out of there as well, using store.commit('changeValue', number).
I hope this answer helps you out a little bit, I was struggling with the exact same problem about 2 days ago and this is working like a charm ;)
Would you kindly explain how the import marked in red can work? For me, it simply does not. (they are using it in react-boilerplate template)
Please excuse me, I am not an experienced JS developer.
The export is done as a default array of functions (as below).
// Bootstrap sagas
export default [
githubData,
];
The import is done in standard way in a test file as below.
import { githubData } from '../sagas';
My point is, if the githubData was exported as "export function* githubData" I think there would be no problem. However I am not sure how importing member of default array of functions can work in this way. Maybe I have incompatible version of babel, node?
if the githubData was exported as export function* githubData i think there would be no problem
Well, there is no problem because that's exactly how it is exported. Being also a part of the default-exported value doesn't stop it from working.