Navigation outside of component in react-router - react-router

Is this outdated? https://github.com/rackt/react-router/blob/95094769caca201b8e9afe68ff3d6cb4ff280fac/docs/advanced/NavigatingOutsideOfComponents.md
I can't seem to get it working.
I'm exporting the history object like this:
export const history = require('history/lib/createBrowserHistory')();
And then I'm using it like so:
history.push('/home');
But the page doesn't change, only the URL changes.

This functionality still works fine and the current docs still have it in master
Notice the extra () at the end of the require in your code. That's a function call which returns a new history object instance.
In that doc they do the function call once in history.js and export the instance. They then require history.js and used that instance for both the router and outside of the router.

Related

Forge Viewer property database userFunction not found due to Vue webpack mangling (terser)

I am using a userFunction to query the property database in a custom Forge Viewer extension. This works great while testing the site locally using npm run serve. However, when I deploy the website to the web (which uses npm run build), the function no longer executes. The error says: SyntaxError: Function statements require a function name. This is because, according to the documentation, the function executed through executeUserFunction has to be named userFunction.
Upon further inspection I discovered that this was because of Vue & Webpack's mangling feature (executed by terser-webpack-plugin), where it renames variables and removes function names to decrease file size.
I have tried many different things, from making the function part of the extension's class to moving it to the global JS scope, but nothing helped. I also tried to exclude objects.js (which is the name of the extension I wrote) from mangling, but this didn't work either.
How do I configure terser to stop mangling this one variable?
I eventually figured out a way to do this which worked:
Add the following to vue.config.js:
module.exports = {
...
chainWebpack: config => {
config.optimization.minimizer('terser').tap(args => {
// eslint-disable-next-line no-param-reassign
args[0].terserOptions.keep_fnames = true;
return args;
});
},
};
This will prevent terser from removing function names, and will make it so userFunction still works. Weird design choice by Autodesk to require a function name, but at least it works now :)

Subscribe to a service of a local library

I have created an Angular library, which gets build with ngpackagr when I build my main application. Everything works fine, however I now have following use-case:
In my library I have a service, which does something. I need to wait for it to finish, so what I though about was doing this in my LibraryService:
LibraryService
reload = new Subject<any>();
// Do something else and after some time:
this.reload.next()
and in my real application code, I have another service which should just listen to it:
this.libraryService.reload.subscribe(()=>{})
But the subscribe will never get called. The reload subject and my service don't seem to know about each other.
What do I need to do? I already imported the library module in my app.module.ts
This has to do with in which life cycle hook you place the subscription
if you run this in sequence you will notice the subscribe will ever get called
reload = new Subject<any>();
this.reload.next()
this.reload.subscribe(()=>{})
subscriptions has to be made before next()
consider put the subscribe in constructor see if it works and call next() when content are rendered or in ngAfterViewInit

Import a specific Javascript library in to Angular 4 (if library doesn't export a variable)

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.

Global function in Ionic 3

I would like to create a global function called "translate". As i know, i can define global variables and their values in the app.module.ts file. So i tried following code:
export function translate(string) {
// i am not sure if it would make a difference if i would use var
let ts = new TranslateService();
return ts.get(string).subscribe(res=>{
return res;
});
}
So maybe i try to use the wrong class, maybe the mistake is somewhere else. I use the ngx-translate Module (and it works great). Instead of always declaring to use the "TranslateService" (in every class where a translation is needed), i want to have a global function, where i can access the translations via only a function (i do not want to call another class...). You can see the code that i do like to use in the global function at the very end of the link (ngx-translate)
Thanks in advance.
global means for me, that something is accessible everywhere in the project.
I think thats a very bad idea, even if you get it to work somehow by some messy hack thats not the way this is intended to work.
TranslateService is already a service you can inject in every class you need it. And injecting a service using Angulars dependency injection is the intended way to use it. If you are afraid that there will be multiple translate services in the end - don't worry, Angulars dependency injection system takes care of that.
I guess you want to do this because you always have to write public translate: TranslateService in your constructor. But if you export a function in your app.module you have to import it again in your class, so you will have to write import { translate } from 'path/to/app.module/translate'; instead every time.

Vue/Vuex - Load state from JSON file

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 ;)