import pdfjslib into vuejs component - vue.js

I would like to create a viewer PDF files into electron/vuejs application.
I need to use the pdfjs librarie.
For that I installed this package : "pdfjs-dist": "2.6.347"
and in my component vuejs I try to used this by doing this :
import pdfjsLib from "pdfjs-dist/webpack";
This import instruction seeems to be running good. But If a start used this like this :
created()
{
pdfjsLib.getDocument()
}
I throw this error :
Cannot read property 'getDocument' of undefined"
I try lot of tricks but I don't find any solution for use this library in my component.
Anyone have a vuejs project with pdfjslib for viewing pdf ?

This seems to work:
import("pdfjs-dist").then((pdfjsLib) => {
pdfjsLib.getDocument();
});
It can be used inside either created() or mounted(). I'd personally use it in mounted.
Working demo here.
Also note calling getDocument() with no arguments seems to trigger some lib error (but that's outside the scope of current question):
Invalid parameter in getDocument, need either Uint8Array, string or a parameter object

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

Vue/Nuxt: How to make a component be truly dynamic?

In order to use a dynamically-defined single page component, we use the component tag, thusly:
<component v-bind:is="componentName" :prop="someProperty"/>
...
import DynamicComponent from '#/components/DynamicComponent.vue';
...
components: {
DynamicComponent
},
props: {
componentName: String,
someProperty: null,
}
The problem is, this isn't really very dynamic at all, since every component we could ever possibly want to use here needs to be not only imported statically, but also registered in components.
We tried doing this, in order at least to avoid the need to import everything:
created() {
import(`#/components/${this.componentName}.vue`);
},
but of course this fails, as it seems that DynamicComponent must be defined before reaching created().
How can we use a component that is truly dynamic, i.e. imported and registered at runtime, given only its name?
From the documentation: Emphasis mine
<!-- Component changes when currentTabComponent changes -->
<component v-bind:is="currentTabComponent"></component>
In the example above, currentTabComponent can contain either:
the name of a registered component,
or a component’s options object
If currentTabComponent is a data property of your component you can simply import the component definition and directly pass it to the component tag without having to define it on the current template.
Here is an example where the component content will change if you click on the Vue logo.
Like this:
<component :is="dynamic" />
...
setComponentName() {
this.dynamic = () => import(`#/components/${this.componentName}.vue`);
},
Solution for Nuxt only
As of now its possible to auto-import components in Nuxt (nuxt/components). If you do so, you have a bunch of components ready to be registered whenever you use them in your vue template e.g.:
<MyComponent some-property="some-value" />
If you want to have truly dynamic components combined with nuxt/components you can make use of the way Nuxt prepares the components automagically. I created a package which enables dynamic components for auto-imported components (you can check it out here: #blokwise/dynamic).
Long story short: with the package you are able to dynamically import your components like this:
<NuxtDynamic :name="componentName" some-property="some-value" />
Where componentName might be 'MyComponent'. The name can either be statically stored in a variable or even be dynamically created through some API call to your backend / CMS.
If you are interested in how the underlying magic works you can checkout this article: Crank up auto import for dynamic Nuxt.js components
According to the official Documentation: Starting from v2.13, Nuxt can auto import your components when used in your templates, to activate this feature, set components: true in your configuration
you are talking about async components. You simply need to use the following syntax to return the component definition with a promise.
Vue.component('componentName', function (resolve, reject) {
requestTemplate().then(function (response) {
// Pass the component definition to the resolve callback
resolve({
template: response
})
});
})

vue.js register webcomponent

I am using vue.js and created a webcomponent with stencil.js. I don't want to publish the webcomponent to npm, which is why I simply include it in the src/assets directory in my vue project.
However I get the error
[Vue warn]: Unknown custom element: <my-component> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
found in --->
<App> at src/app.vue
<Root>
It works without problems with another component I already have in the assets directory.
It also doesn't help to use
Vue.config.ignoredElements = ['my-component'];
since the component is still empty when I run it locally.
Thanks for your help!
If you're including the web component locally, you can use #vue/web-component-wrapper:
import Vue from 'vue'
import wrap from '#vue/web-component-wrapper'
const Component = {
// any component options
}
const CustomElement = wrap(Vue, Component)
window.customElements.define('my-element', CustomElement)
just in case, for me that was a version issue:
my components were defined like that:
export default class Foo extends ScopedElementsMixin(LitElement) {
...
}
And in the vue I did
customElements.define('foo', Foo);
I started received that error when I updated scoped-elements 1.x.x -> 2.x.x.
So when I put everything back to 1.x.x the error just gone.

Custom js library(scrollMonitor) inside main Vue instance to be shared with inner components

This is Vue.js question, generally I'm trying to use 'scrollMonitor' function inside of my .vue instance(imported via main.js) but it gives me a typical 'this.scrollMonitor is not a function' error
mounted () {
let watcher = this.$scrollMonitor(this.$refs.nicer)
}
In main.js ScrollMonitor library seems to be properly imported(console shows what's expected):
import scrollMonitor from 'scrollmonitor'
Vue.use(scrollMonitor)
console.log(scrollMonitor)
Again main goal is using scrollMonitor functionality inside of .vue file(in vue component instance). Sorry if I'm missing something silly here - I'm already using some other libraries like Vue-Resource in that file so issue is not in 'filepath' but rather in the way I'm using scrollMonitor functionality, any help is much appreciated, thank you !
For those who are still looking: there is a way of adding plain js libraries to the main.js and then using them with ease globally in inner components(this is not about mixins):
import scrollmonitor from 'scrollmonitor'
Object.defineProperty(Vue.prototype, '$scrollmonitor', {
get() {return this.$root.scrollmonitor}
})
also it should be added to main Vue data object:
data () {
return { scrollmonitor }
},
And then it can be used within mounted() callback (not created() one) inside of the component itself, with scrollmonitor it may look like this(in my specific case the template had a div with ref="nicer" attribute, 'create' is a method specific to the library api):
mounted () {
this.$scrollmonitor.create(this.$refs.nicer)
}
Hooray, I hope someone may find this useful as I did!
Are you using a plain javascript library and trying to Vue.use it? That won't really work. Vue.use will only work with plugins designed to work with Vue. Import the library into the component that needs and and just use it there.
scrollMonitor(this.$refs.nicer)

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.