Importing an aurelia plugin: Unable to find module with ID - aurelia

I have tried to import 3 different Aurelia plugins unsuccessfully. Each are loaded, but it seems like exported resources within the plugin are not.
For example, when importing aurelia-simple-tabs like this:
aurelia.use
.standardConfiguration()
.plugin(PLATFORM.moduleName('aurelia-simple-tabs'));
The project builds but at runtime I get the error:
Unable to find module with ID: aurelia-simple-tabs/simple-tabs
So then I try loading this explicitly like this:
aurelia.use
.standardConfiguration()
.plugin(PLATFORM.moduleName('aurelia-simple-tabs'))
.plugin(PLATFORM.moduleName('aurelia-simple-tabs/simple-tabs'));
and I get a new error:
Unable to find module with ID: aurelia-simple-tabs/simple-tab.html
I see the same behavior with every other plugin so I do not believe this is a plugin problem. Is there some Aurelia CLI configuration I'm missing?

In aurelia.json, bundles/dependencies for vendor-bundle.js you need entry:
{
"name": "aurelia-simple-tabs",
"path": "../node_modules/aurelia-simple-tabs/dist/amd",
"main": "index",
"resources": [
"simple-tabs.html",
"simple-tab.html",
"simple-tabs.css"
]
}
And just use it later in any template:
<simple-tabs>
<simple-tab name="Tab 1">tab 1</simple-tab>
<simple-tab name="Tab 2">tab 2</simple-tab>
<simple-tab name="Tab 3">tab 3</simple-tab>
</simple-tabs>

Related

Loader is required to be configured to import images using Vite?

I have a vue project which uses Vite in place of Webpack, and when I try to use import x from './src/assets/my/path/to/image.png' to resolve an image to compile-time URL, I am greeted by the following error message:
✘ [ERROR] No loader is configured for ".png" files: src/assets/my/path/to/image.png
The entire project is pretty close to the scaffold project given by npm init vue#latest (using vue3) so my vite.config.js is pretty basic:
export default defineConfig({
plugins: [vue(), VitePWA({})],
resolve: {
alias: {
"#": fileURLToPath(new URL("./src", import.meta.url)),
},
},
build: {
manifest: true,
polyfillModulePreload: true,
}
});
What am I missing? How can I configure this? I can't find anything in Vite documentation about loaders.
I had a quite similar issue with my project that I couldn't really solve. The issue seemed that only initially loaded png files were added. Because I am new to Vite, my efforts with the vite.config.js were fruitless.
Instead, I found a different solution to import the assets (import img from '/path/to/img.png' ) in respective js files directly instead of vite.config.js. Since I used these assets for replacement images for toggling buttons, it was a quick fix. Maybe it helps you, too.

Failed to mount component: template or render function not defined - Laravel Spark Upgrade

I have a Laravel 5.3 project based on Laravel Spark 2.0. I'm trying to upgrade Spark to 3.0 and Vue.js to 2.0 following the upgrade guide.
I've added "laravel/spark": "~3.0" to my composer.json and it updated correctly. After that I added the following packages to package.json and they were installed without problem:
"laravel-elixir": "^6.0.0-11",
"laravel-elixir-vue-2": "^0.2.0",
"vue": "~2.0.1"
Also modified my gulpfile.js to add laravel-elixir-vue-2
Then I compiled my assets with Gulp and no errors were thrown, but when I go to the app, a blank page is shown and the console shows the following error:
[Vue warn]: Failed to mount component: template or render function not defined.
(found in root instance)
InvalidStateError
vue-migration-helper
My Vue files are located in resources/assets/js/ having an structure like this:
resources/assets/js/
--components/ **here I have custom components.
--spark/
--spark-components/
I ran the vue migration helper over those folders and fixed most of the warns. Only those related to global events were left.
This is how my gulpfile.js looks like:
var elixir = require('laravel-elixir');
require('laravel-elixir-vue-2');
require('laravel-elixir-livereload');
elixir(function(mix) {
mix.sass('app.scss')
.browserify('app.js', null, null, { paths: 'vendor/laravel/spark/resources/assets/js' })
.copy('node_modules/sweetalert/dist/sweetalert.css', 'public/css/sweetalert.css')
.copy('bower_components/iCheck/skins/minimal/_all.css', 'public/css/iCheck.css')
.copy('bower_components/iCheck/icheck.min.js', 'public/js/icheck.min.js');
mix.styles([
'resources/assets/vendor/bootstrap/css/bootstrap.css',
'resources/assets/vendor/animate/animate.css',
'resources/assets/vendor/font-awesome/css/font-awesome.css',
], 'public/css/vendor.css', './');
mix.scripts([
'resources/assets/vendor/metisMenu/jquery.metisMenu.js',
// 'resources/assets/vendor/slimscroll/jquery.slimscroll.min.js',
'resources/assets/vendor/pace/pace.min.js'
], 'public/js/vendor.js', './');
mix.version(['css/app.css', 'js/app.js']);
mix.livereload();
});

How to add aurelia-animator-velocity plugin to CLI based project?

Standard fade works if an element has "au-animate" class with the way I configured the plugin. But if app.ts injects VelocityAnimator and a new build is made after that, then there is failed HTTP GET request for "http://localhost:9000/src/velocity.js", JS error "Unhandled rejection Error: Script error for "velocity", needed by: velocity-animate/velocity.ui".
Message repeated twice in the build output:
------- File not found or not accessible ------
| Location: <project folder>/src/velocity.js
| Requested by: <project folder>/src/app.js
| Is this a package? Make sure that it is configured in aurelia.json and that it is not a Node.js package
Project is configured to use Typescript.
I have installed npm packages "aurelia-animator-velocity" and "velocity-animate". I try to include velocity.ui but I'm only guessing how to do it below.
aurelia.json
{
"name": "velocity-animate",
"path": "../node_modules/velocity-animate",
"main": "velocity"
},
{
"name": "velocity-animate-ui",
"path": "../node_modules/velocity-animate",
"main": "velocity.ui"
},
"aurelia-animator-velocity"
main.ts
aurelia.use
.standardConfiguration()
.plugin('aurelia-animator-velocity')
.feature('resources');
app.ts
import { autoinject } from "aurelia-framework";
import { VelocityAnimator } from "aurelia-animator-velocity";
#autoinject
export class App {
constructor(private animator: VelocityAnimator) {
console.log(this.animator);
}
}
I found the workaround. Also, extra characters.

Unable to use Aurelia plugin

I'm trying to move one of my custom elements into a plug-in so that I can re-use it across projects.
I had a look at the skeleton plugin and noticed that it has a src/index.js that returns a config with all custom elements defined as globalResources.
So I tried the same thing and I basically have:
src/index.js
export function configure (config) {
config.globalResources([
'./google-map',
'./google-map-location-picker',
'./google-map-autocomplete'
]);
}
And then I have each one of my custom elements next to index.js, for example:
google-map.js
import {inject, bindable, bindingMode, inlineView} from 'aurelia-framework';
#inlineView(`
<template>
<div class="google-map"></div>
</template>
`)
#inject(Element)
export class GoogleMapCustomElement {
// All the Custom Element code here
}
I've also set up a basic npm script that runs babel on the code and sticks it in dist/:
"main": "dist/index.js",
"babel": {
"sourceMap": true,
"moduleIds": false,
"comments": false,
"compact": false,
"code": true,
"presets": [ "es2015-loose", "stage-1"],
"plugins": [
"syntax-flow",
"transform-decorators-legacy",
"transform-flow-strip-types"
]
},
"scripts": {
"build": "babel src -d dist"
},
Tbh I'm not entirely sure this is all correct but I took some of it from the skeleton plugin and it seems to run fine.
Anyway, the problem I'm having is that after I install the plugin (npm install --save-dev powerbuoy/AureliaGoogleMaps), add it to my aurelia.json in build.bundles[vendor-bundle.js].dependencies and tell aurelia to use it in main.js (.use.plugin('aurelia-google-maps')) I get:
GET http://localhost:9000/node_modules/aurelia-google-maps/dist/index/google-map.js (404)
So my question is, where does it get the dist/index/ part from?? I'm configuring my globalResources in index.js but nowhere does it say that I have an index folder.
What am I doing wrong?
Bonus question: What is the bare minimum required to transpile my ES6 plug-in code so that others can use it? Does my babel configuration look correct?
What about referencing your plugin within aurelia.json, like this:
{
"name": "aurelia-google-maps",
"path": "../node_modules/aurelia-google-maps/dist",
"main": "index"
}
I have absolutely no idea why, but in order to solve this problem I actually had to move my custom elements inside an index/ folder.
So now I have this:
- index.js
- index/
- custom-element-one.js
- custom-element-two.js
And my index.js still looks like this:
export function configure (config) {
config.globalResources([
'./custom-element-one',
'./custom-element-two'
]);
}
Where it gets index/ from I guess I will never know, but this works at least.
I did need the babel plug-in Marton mentioned too, but that alone did not solve the mystery of the made up path.
Edit: To elaborate a bit further, if I name my main entry point something other than index.js the folder too needs that name. For example, if I were to rename index.js main.js I would need to put my globalResources inside a folder called main/.
Update:
Edit: thanks for clarifying why you don't want to use the whole skeleton-plugin package.
Focusing on your original question: aurelia-cli uses RequireJS (AMD format) to load dependencies. Probably, your current output has a different format.
Add transform-es2015-modules-amd to babel.plugins to ensure AMD-style output, so it will be compatible with RequireJS and therefore with aurelia-cli.
"babel": {
"sourceMap": true,
"moduleIds": false,
"comments": false,
"compact": false,
"code": true,
"presets": [ "es2015-loose", "stage-1"],
"plugins": [
"syntax-flow",
"transform-decorators-legacy",
"transform-flow-strip-types",
"transform-es2015-modules-amd"
]
}
Original:
There are several blog post about plugin creation, I started with this: http://patrickwalters.net/making-out-first-plugin/ .
Of course, there have been many changes since then, but it's a useful piece of information and most of it still applies.
I'd recommend using plugin-skeleton as project structure. It provides you with a working set of gulp, babel, multiple output formats out-of-the-box.
With this approach, your plugin's availability wouldn't be limited to JSPM or CLI only but everyone would have the possibility to install it regardless of their build systems.
Migration is fairly easy in your case:
Download skeleton-plugin
Copy your classes + index.js into src/
npm install
...wait for it...
gulp build
check dist/ folder
most of your pain should now be gone :)
Here are some details based on my observations/experience.
1. Main index.js/plugin-name.js:
In general, a main/entry point is required, where the plugin's configure() method is placed. It serves as a starting point when using it within an Aurelia application. This file could have any name, usually it's index.js or plugin-name.js (e.g. aurelia-google-maps.js) to make it clear for other developers what should be included for bundling. Set that same entry point in package.json as well.
In addition to globalResources, you can implement a callback function to allow configuration overrides. That can be called in the application, which will use the plugin. Example solution
Plugin's index.js
export * from './some-element';
export function configure(config, callback) {
// default apiKey
let pluginConfig = Container.instance.get(CustomConfigClass);
pluginConfig.apiKey = '01010101';
// here comes an override
if (callback) {
callback(pluginConfig);
}
...
config.globalResources(
'./some-element'
);
}
Your app's main.js
export function configure(aurelia) {
aurelia.use
.standardConfiguration()
.developmentLogging()
.plugin('aurelia-google-maps', (pluginConfig) => {
// custom apiKey
pluginConfig.apiKey = '12345678';
});
aurelia.start().then(a => a.setRoot());
}
2. HTML and CSS resources:
If you have html only custom elements, you can make them available using globalResources.
Custom css styling is going to require a bit of additional configuration in bundling configuration (see below).
3. Using the plugin with aurelia-cli: Documentation
One of the first new features you'll see soon is a command to help you with 3rd party module configuration. The command will inspect a previously npm-installed package, and make a configuration recommendation to you, automating the process if you desire.
While we are looking forward to that above moment, let's edit aurelia.json:
Configure plugin dependencies. If there are any external libraries (e.g. Bootstrap), then those should be included before your plugin.
Include your plugin:
...
{
"name": "plugin-name",
"path": "../node_modules/plugin-name/dist/amd",
"main": "plugin-name",
"resources": ["**/*.html", "**/*.css"] // if there is any
},
...
Now, your plugin is ready to include it in main.js as showed in Section 1..
I hope you didn't get sick of reading the word 'plugin' so many (21!) times. :D

Aurelia and Semantic UI - custom theme

I am building an Aurelia app with TypeScript and decided to try out Semantic UI. I followed this question (Aurelia Semantic dropdown) and it helped me install Semantic into Aurelia. It seems that it got installed already built with default theme. Is there a way I can install semantic into Aurelia TypeScript app, then add some custom gulp tasks to build according to my own theme.config? I would like also to override some variables like colors, font sizes etc. After it is built I'd like to use the built version in Aurelia view models (TypeScript) and in my views. How can I achieve that?
Here is how I solved this:
Installed semantic to some local folder with npm
Copied over the semantic folder and semantic.json to web app root folder (so semantic folder is on the level where I have node_modules and jspm_packages)
Inside semantic.json I specified the list of components I want to include in my app
Inside semantic.json I modified "output" and "clean" paths to match the folders where I serve files from.
The semantic.json:
{
"base": "semantic",
"paths": {
"source": {
"config": "src/theme.config",
"definitions": "src/definitions/",
"site": "src/site/",
"themes": "src/themes/"
},
"output": {
"packaged": "../dist/semantic",
"uncompressed": "../dist/semantic/components/",
"compressed": "../dist/semantic/components/",
"themes": "../dist/semantic/themes/"
},
"clean": "../dist/semantic"
},
"permission": false,
"autoInstall": false,
"rtl": false,
"version": "2.2.4",
"components": [
"button",
...
"site"
]
}
Inside Aurelia's gulp definitions I added semantic build task
The build/tasks/build.js:
var buildSemantic = require('../../semantic/tasks/build');
gulp.task('build-semantic', buildSemantic);
...
gulp.task('build-layout', function (callback) {
return runSequence(
'build-html',
'build-semantic',
'build-less',
callback
);
});
When coding I go into semantic src (e.g. semantic\src\themes\default\globals\site.variables) and modify things in there
Run gulp build-layout
The output is added to my dist folder and I can use it in my views
As for the view models I created some helper components to be used as aurelia attributes e.g. the semantic tooltip:
import {customAttribute, inject} from 'aurelia-framework';
import * as $ from 'jquery';
import '../semantic/semantic.min.js';
#customAttribute('semantic-tooltip')
#inject(Element)
export class SemanticTooltip {
constructor(private element: HTMLElement) {
}
attached() {
$(this.element).popup();
}
}
Usage:
<i class="info circle icon" data-content="Sample tooltip" semantic-tooltip></i>