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 ;)
Related
In React Native:
I would like to import a file using require at runtime.
e.g.
let mydata = require('../data/' + new Date().getFullYear().toString() + '.json');
Since I have more than a couple hundred json files it is not feasible to hard code all the files.
in angular you can just use the above code and it works, but I think RN requires a static path. I am hoping there is an alternative way to do it.
any help appreciated!!!
This is one of the problems i have encountered. As i have heard of, react's require()only uses static url not variables, that means that you have to do require('/path/file'). Here is my version of solution:
const images = {
profile: {
profile: require('./profile/profile.png'),
comments: require('./profile/comments.png'),
},
image1: require('./image1.jpg'),
image2: require('./image2.jpg'),
};
export default images;
not the best option, but you can get away with it sometimes.
I've got an Angular6 app that is being built as more of a framework for internal apps. The header / footer / major navigation will be shared, but each app (feature module) should have internal flows separate from each other. For example one feature might be purchasing, another might be onboarding, another might be a sales dashboard. They're very different from each other.
What I'm trying to do is come up with a declarative way to define known configurations for each feature. For example, the minor navigation (page to page within a feature), top level header title, and various other context related data points. My initial thought was to have them defined as JSON within each feature, which works great except I now have to import every feature's config regardless of whether a user navigates, or even has access to, that feature.
I've already got the context service set up that is checking the URL on navigation and setting some items, but again, it has to import all possible configs using this at the top of that service.
import { fooConfig } from '#foo\foo.config';
import { barConfig } from '#bar\bar.config';
import { bazConfig } from '#baz\baz.config';
So the question is: Is there a way for me to check the URL on navigation, and within that subscription, pick up the config from the correct file without pre-maturely importing them? Or maybe I can use the module to express / declare those options?
Using Typescript's Dynamic Import Expressions might be a viable option in your case..
let config;
switch (val) {
case 'foo': config = await import('#foo\foo.config'); break;
case 'bar': config = await import('#bar\bar.config'); break;
case 'baz': config = await import('#baz\baz.config'); break;
}
Though, as far as I know, there's now way at the time of writing to use variables for the import string (e.g. await import(path)).
updateConfig(feature: string) {
import(`../configs/${feature}.config.json`).then(cfg => {
this._currentConfig$.next(cfg);
});
}
The above snippet shows what I came up with. It turns out WebPack can't digest the # paths you normally use on imports and you also can't use fully variable paths. All possible options for the module package must have some common part of the path. I ended up moving my configs from #foo\foo.config.ts to #core\configs\foo.config.json. Which makes them less modular because now core is holding their config, but it makes the module lazy.
I'm trying to diagnose a problem thats recently arisen for us, after upgrading our suppported browser (~40 -> ~60)
We have this effective code in an external (now unsupported) library, that sits in an iffe:
(function(window, undefined){
# external library
if(!window.terribleIdea){
window.terribleIdea = {}
}
<some code>
if(!window.terribleIdea.config.url){
window.terribleIdea.config.url = 'the wrong url'
}
localStorage.set('somethingImportant', getStuff(window.terribleIdea.config.url))
})( window );
Now we did have a bootstap type file that looked like this:
# appBootstrapper.js
import applyConfig from './app/configApplier';
import ALL_ANGULAR_MODULES from './app'; # contains angular.module set up for
# app and every dependency
fetchConfig()
.then(applyConfig)
.then () => angular.bootstrap(document, [ALL_ANGULAR_MODULES])
.catch( error => {
alert(`It borked: ${error.message}`)
});
Amongst other things applyConfig does:
window.terribleIdea = {
config: {
url: 'not terrible'
}
}
What now happens, is that the import statement of ALL_ANGULAR_MODULES ends up running the code in the external library, and setting local storage. What we think used to happen is that it was only called on angular.bootstrap running.
Now what I need to find out is, has the functionality of the import statement changed in a later version of chrome, or has it always been running this code and gone unnoticed?
All I can find is references to Dynamic Imports, and the order of scripts running, in <script></script> tags.
It is hard to debug without access to the project (see discussion in comments above). Here are some possibilities worth exploring while encountering such issues. It is of course possible that it was like this all along.
Change in the bundler configuration. Webpack accepts entries as arrays, and order matters in them.
Change in the way the bundler/dependency manager reacts to dynamic imports
Change in the way your application loads its dependency during the its bootstrap phase. It is not (imo) angular specific, as many app use some kind of "componentization" which translates in files executed in a different order they are imported (as they may only export constructors or whatnot).
I am trying to show a diff for two JSON objects in Angular 4 view, I am using this library (angular-object-diff) originally built for AngularJS.
Demo of that library: Link
I tried to import this JS library the following way:
JS file I am trying to import: angular-object-diff.js, doesnt have a exported variable
In my typings.d.ts ( I added the following):
declare var ObjectDiff: any;
In my angular-cli.json, I added
"scripts": [
"../node_modules/angular-object-diff/dist/angular-object-diff.js"
],
In my component file:
const json1 = {
name: 'John'
};
const json2 = {
name: 'Johnny'
};
const diff = ObjectDiff.diffOwnProperties(json1, json2);
this.jsonViewData = ObjectDiff.toJsonDiffView(diff);
In my view:
<pre ng-bind-html="jsonViewData"></pre>
<pre> {{jsonViewData}}</pre>
Nothing seems to be working, I get the error that "ObjectDiff" is not defined in the console"
Can someone please let me know if I am doing in thing wrong ?
Suggestions for displaying the JSON diff are also welcomed :)
** Thank you
The library doesn't export anything. It uses IIFE to not pollute global scope with local variables. It's impossible to reach local variables from the outside, this makes Module pattern so effective (and annoying).
The library uses AngularJS angular global and expects that it will exist. This creates a problem, because Angular 4 application should mock angular global in this case. Moreover, the code itself relies on AngularJS-specific units ($sce service).
The library should be forked and modified to suit the expectations. The mentions of angular should be removed. Considering that script will be executed in module scope, IIFE should be removed and appropriate exports should be added.
I am trying to learn building a React + Redux application architecture using Web Pack 3 for bundling. I am trying to work with temporary JSON files for data sets and importing them into Service files which want to use the data returned from the imported JSON.
I try to use the imported JSON in Promise.resolve(JSON) and somehow the value seems to be undefined.
Note: This block is inside in IIFE block.
Find the service code below.
import jsonVal from './josnFile.json';
export default (function() {
return {
method1: methodName1,
method2: methodName2,
...
}
function methodName1(){
return new Promise((resolve, reject) => {
resolve(jsonVal);
// ...usual then, catch blocks for returning rejects
});
}
}());
After all this flow, I have set up the reducers and actions to appropriately update the Redux state. But no update happens because the JSON data is always undefined and when I try to pass this down to the presentational React components via Redux connect (mapStateToProps), its undefined too.
I want to know what should I do to include this JSON for mocking APIs.
Whether I have to use a JSON loader in webpack or any other solution?
Note: I am using babel-node to transpile ES6 code