How do I make a custom element available globally in Aurelia? - aurelia

I am trying to update an app based in pluralsight course "Building Applications with Aurelia" with methods to make a custom component globally available to DOM.
The course still has globalizeResources because it was written before 0.15 or whatnot and hasn't been updated.
Note that <require> does work to display the custom component contained in resources...
none of these methods seem to:
in main.js:
aurelia.use
.standardConfiguration()
.developmentLogging()
.globalResources("./resources/nav-menu");
or
aurelia.use
.standardConfiguration()
.developmentLogging()
.feature("resources");
with ./resources/index.js containing
export function configure(aurelia) {
aurelia.globalResources("./nav-menu");
}
or
aurelia.use
.standardConfiguration()
.developmentLogging()
.plugin("./resources/nav-menu");
Has this changed again, or ...?

Not sure which chapter of the course you use, but this is taken from the 5th chapter. Didn't follow the course, but it shows Movies and then the nav :-)
See this gistrun for a working example:
https://gist.run/?id=ef855f42433dd22c533e1f52e48dfc45
(run it in chrome, for best gistrun support)

Related

How to acced to google object in vue 2?

I'm trying to use the google maps API at my vue2 project and I have tried some ways that have failed. After using the vue2googlemaps module and the node module from google I have decided to use the CDN directly and add it to the index page. My problem now is that to acced to the google object, for example, to create a Marker or something like that, I need to use this.marker = new window.google.maps.Marker() for example, but in the tutorials I have seen, everyone uses directly the google object and never uses that window. I can`t understand why it happens. It would be appreciated if someone shows me the correct way to import or use this library on google.
It's because your template's code is compiled and executed in your component instance (a.k.a vm) 's scope, not in the global (a.k.a. window) scope.
To use google directly in your template you could add the following computed:
computed: {
google: () => window.google
}
If your problem is not having google defined in the component's <script>, a simple solution is to add it as a const at the top:
import Vue from 'vue';
const google = window.google;
export default Vue.extend({
computed: {
google: () => google // also make it available in template, as `google`
}
})
An even more elegant solution is to teach webpack to get google from the window object whenever it's imported in any of your components:
vue.config.js:
module.exports = {
configureWebpack: {
externals: {
google: 'window.google'
}
}
}
This creates a google namespace in your webpack configuration so you can import from it in any of your components:
import google from 'google';
//...
computed: {
google: () => google // provide it to template, as `google`
}
Why do I say it's more elegant?
Because it decouples the component from the context and now you don't need to modify the component when used in different contexts (i.e: in a testing environment, which might not even use a browser, so it might not have a window object, but a global instead; all you'd have to do in this case is to define a google namespace in that environment and that's where your component will get its google object from; but you wouldn't have to tweak or mock any of the component's methods/properties).

"aurelia-polyfills" doesn't work (or we cannot import it correctly)

We are using Aurelia JS in our project.
On IE11 we get error conntected to missing "includes" method:
Object doesn't support property or method 'includes'
We've installed aurelia-polyfills plugin but it doens't work (or we use it in wrong way).
In main-webpack.js:
...
import 'aurelia-polyfills';
...
bootstrap(function (aurelia) {
aurelia.use
.standardConfiguration()
.defaultResources()
.developmentLogging()
...
.plugin(PLATFORM.moduleName('aurelia-polyfills'));
aurelia.start().then(() => aurelia.setRoot(PLATFORM.moduleName('app-webpack'), document.body));
});
Our import statement is correct?
Should we do it in the same file?
SOLVED:
aurelia-polyfills handles only includes for Array object, not String.
My error concerned on String, so I needed to create separate JS file with polyfill and use this code snippet: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes

Unknown html tag warning of Bootstrap-Vue.js support in WebStorm

I'm using WebStorm 2017.2.4 and webpack Vue.js project. I have added bootstrap-vue.js to my project and would like to see hints for it and components support.
But instead of that I have got "Unknown html tag" warning.
BTW: bootstrap-vue works as expected when running project.
Do you have any suggestions how to make it work?
UPDATED on 2019/07/30
PHPShtorm(WebStorm) was updated to 2019.2 and now they added better support for vuejs libraries:
https://blog.jetbrains.com/webstorm/2019/07/webstorm-2019-2/#development_with_vue
I've just tested and it works.
OLD answer
I solved this issue by adding components manually.
According to: https://bootstrap-vue.js.org/docs/#individual-components-and-directives
I created new file, e.g. bootstrap.js then register globally components which required
import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap-vue/dist/bootstrap-vue.css';
import Vue from 'vue';
import navbar from 'bootstrap-vue/es/components/navbar/navbar';
import container from 'bootstrap-vue/es/components/layout/container';
// ...
Vue.component('b-navbar', navbar);
Vue.component('b-container', container);
// ...
It work for me in phpstorm 2018.1
Bootstrap vue uses very dynamic way of defining components. I am using PyCharm with vuejs extension which is unable to resolve the components when registered using
import { Layout } from 'bootstrap-vue/es/components'
Vue.use(Layout)
What I use to do is make a new file bootstrap.js in components directory, and register all bootstrap components I would use like
import Vue from 'vue'
import bContainer from 'bootstrap-vue/es/components/layout/container'
import bRow from 'bootstrap-vue/es/components/layout/row'
import bCol from 'bootstrap-vue/es/components/layout/col'
Vue.component('b-container', bContainer);
Vue.component('b-col', bCol);
Vue.component('b-row', bRow);
and then import this file in main.js
import './components/bootstrap'
Just a little cleaner solution.
#Updated: There're two ways to fix "Unknown html tag" warning: (Global and Local Registration)
Global Registration :
You should have to register your component globally Vue.component(tagName, options) before creating the new Vue instance. For example:
Vue.component('my-component', {
// options
})
Once registered, a component can be used in an instance’s template as a custom element, <my-component></my-component>. Make sure the component is registered before you instantiate the root Vue instance. Here’s the full example:
HTML:
<div id="example">
<my-component></my-component>
</div>
JS:
// global register
Vue.component('my-component', {
template: '<div>A custom component!</div>'
})
// create a root instance
new Vue({
el: '#example'
})
Which will render HTML::
<div id="example">
<div>A custom component!</div>
</div>
Local Registration :
You don’t have to register every component globally. You can make a component available only in the scope of another instance/component by registering it with the components instance option:
var Child = {
template: '<div>A custom component!</div>'
}
new Vue({
// ...
components: {
// <my-component> will only be available in parent's template
'my-component': Child
}
})
The same encapsulation applies for other registerable Vue features, such as directives.
Read more at https://v2.vuejs.org/v2/guide/components.html#Using-Components
#Before Updated:
In WebStorm, a library is a file or a set of files whose functions and methods are added to WebStorm's internal knowledge in addition to the functions and methods that WebStorm retrieves from the project code that you edit. In the scope of a project, its libraries by default are write-protected.
WebStorm uses libraries only to enhance coding assistance (that is, code completion, syntax highlighting, navigation, and documentation lookup). Please note that a library is not a way to manage your project dependencies.
Source: https://www.jetbrains.com/help/webstorm/configuring-javascript-libraries.html
Simply, upgrade WebStorm from version 2017.2.4 to 2017.3 which fixed this issue. It is tested.

Aurelia Webpack loader unable to find a module I add as a feature

I have a small Aurelia app built with Webpack. Under my src folder I have util folder with index.ts inside. In main.ts I turn the feature on like this:
import { Aurelia, PLATFORM } from "aurelia-framework";
export function configure(aurelia: Aurelia) {
aurelia.use
.standardConfiguration()
.developmentLogging()
.feature(PLATFORM.moduleName("util"));
aurelia.start().then(() => aurelia.setRoot(PLATFORM.moduleName("app")));
}
util/index.ts:
import { FrameworkConfiguration } from 'aurelia-framework';
export function configure(config: FrameworkConfiguration): void {
config.globalResources([
"./converters",
"./rest"
]);
}
converters and rest are Typescript modules under util.
I'm following the instructions from Aurelia Hub.
When I open the app in the browser I see the following error:
Uncaught (in promise) Error: Unable to find module with ID: util/index
at WebpackLoader.<anonymous> (aurelia-loader-webpack.js:187)
at step (aurelia-loader-webpack.js:36)
at Object.next (aurelia-loader-webpack.js:17)
at aurelia-loader-webpack.js:11
at Promise (<anonymous>)
at webpackJsonp.64.__awaiter (aurelia-loader-webpack.js:7)
at WebpackLoader.webpackJsonp.64.WebpackLoader._import (aurelia-loader-webpack.js:152)
at WebpackLoader.<anonymous> (aurelia-loader-webpack.js:252)
at step (aurelia-loader-webpack.js:36)
at Object.next (aurelia-loader-webpack.js:17)
If I reference the modules directly instead of the feature e.g.
import { Rest } from '../util/rest';
Then I get no errors and the app loads successfully. But I want to have these modules globally available.
Using aurelia-webpack-plugin version 2.0.0-rc.2
Would appreciate your advice.
Take a look at this:
https://github.com/aurelia/templating-resources/blob/master/src/aurelia-templating-resources.js
Edit:
I have gotten it working. The key is that you need to explicitly call PLATFORM.moduleName('./relative/path/to/file') on each path specifically and that the call needs to be made from the file (actually technically the same directory but still...) that calls config.globalResources().
In other words you can't shortcut the following code:
config.globalResources(
PLATFORM.moduleName('./resource1'),
PLATFORM.moduleName('./resource2')
);
Don't try to map the resources to PLATFORM.moduleName or to dynamically construct file names.
You should change your path PLATFORM.moduleName("util") into PLATFORM.moduleName("./util"). Then you can be able to use path relative to your util folder to register your globalResources. Also you can look into here for sample project structure. Also see this line of code, aurelia added /index to moduleName if it not included as it was based on convention.
If you already try using aurelia CLI, the created project under src/resources is registered as a feature.

What is the difference between Aurelia Plugin and Feature?

I am trying to register a couple of plugins for my app however I am not sure how this should be done.
The plugins that I have, include two ValueConverters and the gooy/aurelia-animator-tinyanimate which I have installed via JSPM.
Here is my current implementation:
resources\index.ts/js
export function configure(aurelia) {
aurelia.globalResources('../from-now', '../date-format');
}
main.ts/js (this is the entry point of the app)
import {Aurelia} from 'aurelia-framework';
export function configure(aurelia: Aurelia): void {
aurelia.use
.standardConfiguration()
.developmentLogging()
.plugin('resources/index', 'gooy/aurelia-animator-tinyanimate');
aurelia.start().then(function () { return aurelia.setRoot('views/app'); });
}
The converters are working however I do not see the tinyanimate to be loaded.
Based on the above, I have the following questions:
how would I move the gooy/aurelia-animator-tinyanimate over to the index.js file?
what is the difference between plugin() and feature()?
Features are basically the same as a plugin, except that they live in your own source tree. Based on your index.js file, you would need to load your feature like this:
aurelia.use.feature('resources`);
Assuming that the feature's index.js file is located in the resources folder. You may want to change your index.js file to
export function configure(config) {
config.globalResources('./from-now', './date-format');
}
and update your directory structure to put from-now.js and date-format.js in the resources directory. You don't need to do this, but from an organizational standpoint, it would make sense. Changing the parameter name is simply to better describe what the parameter is (a FrameworkConfiguration instance).
To load gooy/aurelia-animator-tinyanimate in your main.js file, you will need to remove the 'resources/index' parameter from the call to plugin. Aurelia will then load the plugin properly for you. Your main.js file should end up looking like this:
export function configure(aurelia: Aurelia): void {
aurelia.use
.standardConfiguration()
.developmentLogging()
.feature('resources')
.plugin('gooy/aurelia-animator-tinyanimate');
aurelia.start().then(function () { return aurelia.setRoot('views/app'); });
}
Also, note that there is no need for the import {Aurelia} from 'aurelia-framework'; line in your main.ts.