In particular, can the typescript source of the ag-grid-vue component be compiled then included in a regular html file?
I found a way to do this without modifying the source. Near the top of ag-grid-vue.umd.js, you can see that the module does this:
root["ag-grid-vue"] = factory(root["Vue"], root["agGrid"]);
Here, "root" is the window, and the result of the factory call is what you'll want. But due to the dashes, you can't access it directly. But you can use the dictionary syntax (or whatever it's called):
let agVueObj = window["ag-grid-vue"];
//The component is a field on this object:
let AgGridVue = agVueObj.AgGridVue;
//Then register it as a component in your Vue instance:
//components: { AgGridVue }
And you should be able to use <ag-grid-vue> tags.
I figured it out:
Download the ag-grid source code, go into the packages/ag-grid-vue directory and do npm install and npm run build. That will put compiled javascript modules in the dist directory that can be used without a build system.
I did have to modify the built javascript slightly to get the AgGridVue object into the global namespace, since I'm not using a module loader.
EDIT:
To get the AgGridVue into the global namespace, add window.AgGridVue = AgGridVue; to the end of the function that returns AgGridVue in ag-grid-vue.umd.js
Related
I'm trying to use this logging package I found in my Vue Project. https://github.com/xpl/ololog
I want to be able to use the logger in my whole project and all my components. Do I have to import the package in every single component I want to use it in or is there a way to make it global?
How can I make an instance for it? Sorry, I am confused about this. Thank you.
You can either:
A. Import the logger on every component
B. Add an instance property to make the log function accessible to all components:
// When you initialize your Vue app
Vue.prototype.$log = myLogFunction
// Now $log is available on all Vue instances via `this`
this.$log("my log");
A is more explicit, B is more convenient.
When I make changes to any function .js file under ./src/fn hot reload is not working and triggers a page reload.
I have been trying to make configure vue.config.js to include the directory to HMR correctly. Also I tried using my custom helpers as a Vue.use(myPlugin).
/* functions.js (just a part of it) */
export const Functions = {
game: {
helper: helpers,
turn: turn,
ui: ui,
validate: validate,
card: cards
},
}
/* main.js */
import Functions from './functions.js';
Vue.prototype.$myFn = Functions;
Expected HMR to work but instead get a full page reload when making changes to functions.js (or any underlying js file imported in functions.js)
Adding your own objects and functions to the Vue prototype is a bit of an anti-pattern. In this case, Webpack can't determine the extent of the changes made so it falls back to a page reload. This is because ES modules can be statically analysed whereas global objects cannot be.
Here's some articles about static analysis:
Static Program Analysis
ES Modules in Depth
Remove the functions from the Vue protoype and always use ES modules to structure your functions. Then you can import them into other modules or components without using the legacy style global hack approach of yesteryear.
I have a vue.js application and in the main.js file I have configured the Vuei18n as per the documentation. This is working perfectly and in order to access this in other components, I have added this to new Vue() instance and this is now accessible (with this.$i18n).
Now I have created a validator.js file for validation rules and I need to use the this.$i18n there, but its not working. I have also tried Vue.prototype.$i18n but that too not working. Can someone help me to find out where I went wrong ?
exporting the i18n variable
I'll assume your app is a vue-cli app, or at least that you use webpack to build it
and therefore can use ES modules.
Working with vue-i18n you would do something like the following:
// step 1: define the i18n object via new Vue18n
const i18n = new VueI18n({
locale: DEFAULT_LANGUAGE,
messages,
});
// step 2: setup the Vue object to use this object:
new Vue({
i18n,
... store, router.... whatever
})
Where messages contain all the JSON's with the translations keys and values.
I guess you already are doing something like this.
And now, in your validator module you need the very same i18n object you plugged to Vue.
Instead of trying to get to Vue in your validator, you can just plain export the i18n varible from main.js:
export {i18n}
So, in your validator.js file, you can just import it:
import {i18n} from '#/main.js' // or whatever is the path
This is pretty much how I'm solving the validator internationalization problem in my own application.
Important note: circular dependencies
If you're already importing the validator.js in your main.js, you won't be able to import i18n from main in your validator module. To avoid such a problem, you would move the i18n initialization and exportation to another module, such as i18n.js, so the validator and the main file can import it independently.
Without es6 modules
In case you're not using webpack or another bundler to bundle your code, you can still just export the i18n object to the window object:
window.i18n = i18n
and then use it from whatever file. You just need to be careful to store the i18n object in window before any file will try to access it.
I think what you're looking for is Custom Events. According to this documentation, you should be able to emit your variable with something like below
this.$emit('send-i18n', this.$i18n)
Still according to the documentation, try to use v-on:send-i18n to retreive your value.
Hope it works.
I have some method to generate random hexademical color. It will be used in very few (3 or 5) parts of the project. So I want to separate it from main code into some kind of Helper or smth else, and include it when needed (not globally).
I have 2 working ways to do this:
Using mixins. What I don't like is that when you read the code, you can't separate your own methods from methods of mixin.
Using plugins. What I don't like with that is that you have to write import Vue from 'vue' + Vue.use(MyPlugin) every time in all files where you want to use it. After that, you can call it like this.$ColorHelper.getRandomHEX().
So, the question is about aesthetics visualization.
What is the best practices to do such things?
PS: project was created from template with webpack.
Our team decide use function import from files-helpers
For example:
import { getRandomColor, getBackgroundColor } from 'Global/helpers/colorHelper';
// .....
let color = getRandomColor();
What good:
Don't need use excess import + use as in plugins
Method visually stands out, what it not from this
What bad:
Cant see visually what the helper have method. But possible can fixed with aliases. We dont think yet
Vue plugins are global, you only have to call the Vue.use method once. Then they should work wherever you use that particular Vue instance.
In a default project setup you normally don't have multiple Vue instance so it should work globally.
From the docs:
Plugins usually add global-level functionality to Vue.
And:
Use plugins by calling the Vue.use() global method:
Vue.use(MyPlugin)
https://v2.vuejs.org/v2/guide/plugins.html
I want to intercept the module loading of Aurelia to redirect some calls.
To do such things the aurelia-loader has a addPlugin() interface. You add a suffix like !myplugin to a resource to mark that it should be loaded using that plugin.
Now when I do this with my own component, it loads the JS file but the name for the HTML template is messed up. Like from the resource name my-comp!myplugin it will load my-comp.js but tries to find my-comp!myplugin.html which does not match the plugin name anymore.
I have provided a gist with that issue here: https://gist.run/?id=c7ed477bc652540ed8b0702d843f1832
The loader plugin code in main.js is basically:
loader.addPlugin('gate', {
fetch(address) {
console.info('Intercepted:', address);
var tmpParts = address.split('.');
var extension = tmpParts[tmpParts.length - 1].toLowerCase();
if (extension == 'css') {
console.debug('Loading as styles', address);
return loader.loadText(address);
} else if(extension == 'html') {
console.debug('Loading as template:', address);
return loader.loadTemplate(address);
} else {
console.debug('Loading as module:', address);
return loader.loadModule(address);
}
}
});
Using it like this in a template (marked with Issue 1 in the gist):
<require from="./comp2!gate"></require>
After that is should be possible to load the component like this:
<comp2></comp2>
Or even like this:
<compose view-model="./comp2!gate"></compose>
Instead the name for the template is messed up, the browser console says:
Failed to load resource: the server responded with a status of 404 ()
https://gist.host/run/1485182959149/comp2!gate.html
The expected name of the template would be https://gist.host/run/1485182959149/comp2.html!gate (including the plugin)
How can I fix the loader plugin to work correctly?
The loader is aurelia-loader-default 1.0.0, JSPM is 0.16.39, Node is 6.5.0, NPM 3.10.5.
I have added a second gist.run: https://gist.run/?id=1ddd4233e3afc40d89eb64b751e1dd8f
It is a bit shorter. When I specify the view using #useView decorator in comp2.js (marked with issue 4), it works - but I cannot specify a loader plugin with #useView. I would expect it to load the view with the same loader plugin or be able to specify a loader plugin with #useView.
Okay, I found a solution which looks like it can work with less code and patching and it works between two gists.
This gist contains the external component comp3:
https://gist.run/?id=dc837978a514011e13c872dbad92ae3f
This gist is the basic Aurelia app with a plugin and a small patch to the applyPluginToUrl method of the loader:
https://gist.run/?id=39e6fdacefc9e5c69b42a5e8c9049384
If the gist URLs are fixed, it should work for everyone. The Aurelia app loads comp3 from the first gist and displays it (you see the purple border define in the comp3-view).
There is one caveat at the moment: No support for CSS as SystemJS adds the extension .js to them, looks like I have to take care of that.
I do not like the path to loader.applyPluginToUrl but SystemJS does not really support plugin chaining and so the order must be correct. Also this solution requires all external components to set #useView including the loader plugin.
Any better approaches?