How can we integrate Cordova plugins into Vue-Cordova framework?

Looking to integrate Vue-Cordova with Cordova-plugin-file-opener2 to open PDF files within iOS/Android applications.

In the Vue-Cordova setup, plugins related to the device are defined on the data property of the App vue instance:

  data: function () {
    return {
      cordova: Vue.cordova,
      plugins: {
        'cordova-plugin-camera': function () {
          if (!Vue.cordova.camera) {
            window.alert('Vue.cordova.camera not found !')
            return
          }
          Vue.cordova.camera.getPicture((imageURI) => {
            window.alert('Photo URI : ' + imageURI)
          }, (message) => {
            window.alert('FAILED : ' + message)
          }, {
            quality: 50,
            destinationType: Vue.cordova.camera.DestinationType.FILE_URI
          })
        },
         ....

While I can access these properties on my iOS simulator, I'm facing difficulty in accessing externally installed plugins via Cordova CLI. The Cordova object that should enable calling file-opener2 commands like:

cordova.plugins.fileOpener2.open(
    filePath, 
    fileMIMEType, 
    {
        error : function(){ }, 
        success : function(){ } 
    } 
);

has additional properties not present on the Vue.cordova instance. Trying to access them via: Vue.cordova.plugins.fileOpener2 results in undefined.

Seeking guidance on how to incorporate external plugins into Vue-Cordova, or potentially find a workaround?

EDIT:

Despite my efforts, I haven't succeeded, but progress seems near.

The steps taken include:

  1. cloning https://github.com/pwlin/cordova-plugin-file-opener2 into the plugins folder of the Cordova project
  2. modifying

    node_modules/vue-cordova/index.js
    :

    function(module, exports, webpack_require) {

            'use strict';
    
    // list here all supported plugins
    var pluginsList = ['cordova-plugin-camera', 'cordova-plugin-device', 'cordova-plugin-geolocation', 'cordova-plugin-contacts', 'cordova-plugin-file-opener2'];
    
    exports.install = function (Vue, options) {
    
      // declare global Vue.cordova object
      Vue.cordova = Vue.cordova || {
        deviceready: false,
        plugins: []
      };
    
      // Cordova events wrapper
      Vue.cordova.on = function (eventName, cb) {
        document.addEventListener(eventName, cb, false);
      };
    
      // let Vue know that deviceready has been triggered
      document.addEventListener('deviceready', function () {
        Vue.cordova.deviceready = true;
      }, false);
    
      // load supported plugins
      pluginsList.forEach(function (pluginName) {
        var plugin = __webpack_require__(1)("./" + pluginName);
        plugin.install(Vue, options, function (pluginLoaded) {
          if (pluginLoaded) {
            Vue.cordova.plugins.push(pluginName);
          }
          if (Vue.config.debug) {
            console.log('[VueCordova]', pluginName, '→', pluginLoaded ? 'loaded' : 'not loaded');
          }
        });
      });
    };
    

    // }, / 1 / // function(module, exports, webpack_require) {

    var map = {
        "./cordova-plugin-camera": 2,
        "./cordova-plugin-camera.js": 2,
        "./cordova-plugin-contacts": 3,
        "./cordova-plugin-contacts.js": 3,
        "./cordova-plugin-device": 4,
        "./cordova-plugin-device.js": 4,
        "./cordova-plugin-geolocation": 5,
        "./cordova-plugin-geolocation.js": 5,
        "./cordova-plugin-file-opener2": 6
    };
    function webpackContext(req) {
        return __webpack_require__(webpackContextResolve(req));
    };
    function webpackContextResolve(req) {
        return map[req] || (function() { throw new Error("Cannot find module '" + req + "'.") }());
    };
    webpackContext.keys = function webpackContextKeys() {
        return Object.keys(map);
    };
    webpackContext.resolve = webpackContextResolve;
    module.exports = webpackContext;
    webpackContext.id = 1;
    

    /***/ },

    ...

    /***/ function(module, exports) {

    'use strict';
    
    exports.install = function (Vue, options, cb) {
      document.addEventListener('deviceready', function () {
    
          if (typeof cordova.plugins.fileOpener2 === 'undefined'){
          return cb(false);
          }
    
    
        // pass through the geolocation object
          Vue.cordova.fileOpener2 = cordova.plugins.fileOpener2;
    
        return cb(true);
      }, false);
    };
    
    /***/ },
    
  3. included the following addition to plugins in the data object in app.vue: (Unsure about further additions needed for this definition. Any recommendations?)

    'cordova-plugin-file-opener2': function () { if (!Vue.cordova.fileOpener2){ window.alert('Vue.cordova.fileOpener2 not found !') return } }

Following these steps, anticipation is high for {{ fileOpener2 }} availability in the template as an object, yet it remains elusive. What am I overlooking?

Answer №1

Have you made sure to wait for the deviceready event before accessing your plugin?

If not, try using this code snippet after the event is triggered:

Vue.cordova.on('deviceready', () => {
  // Check for your variable here
})

It's possible that you didn't follow the contribution guide properly to support this plugin, as mentioned by Gandhi. Avoid editing webpack generated files and instead generate your own:

  • Clone the vue-cordova repository
  • Replace node_modules/vue-cordova in your project with a symlink to the cloned repository
  • Add the plugins and run npm run build (or npm run dev)

After completing these steps, try building your Cordova app again.

Answer №2

If you're struggling to incorporate Cordova plugins into Vue-Cordova, the issue at hand involves transpiling files with Webpack.

  1. Start by cloning the repository

  2. Create a file in the plugins/ directory named after the plugin

  3. Add your plugin to the list in src/index.js

  4. Include ".babelrc" in the root folder

    Insert the following code:

    {
      "presets": [
        [
          "env",  { "modules": false }
        ]
      ]
    }
    
  5. Execute

    npm install --save-dev babel-preset-env

  6. Run the command npm install

You will discover the transpiled file generated in the index.js file within the root folder.

Answer №3

If you're looking for an alternative solution, one way to ensure that plugins load correctly is by modifying this function within cordova.js...

  function determineCordovaPath() {
    let platform = cordova.platformId.toUpperCase();
    if (platform === 'ANDROID') {
      return `file:///android_asset/www/`;
    }
    else if (platform === 'IOS') {
      return `cdvfile://localhost/bundle/www/`;
    }
    else if (platform === 'OSX') {
      return `cdvfile://localhost/bundle/Contents/Resources/www/`;
    }
    else if (platform === 'WINDOWS') {
      return `/www/`;
    }
    return null;
  } 

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Achieving a smooth transition from a blur-out effect to a blur-in effect on a background Div

I created a blur in/out effect for my landing page, but it's not functioning as expected and I'm not sure why. It blurs out correctly, but the issue arises when I want the underlying Div to fade in. Currently, it just appears abruptly after the ...

Retrieving Vue data from parent components in a nested getter/setter context

<template> <div id="app"> {{ foo.bar }} <button @click="meaning++">click</button> <!--not reactive--> <button @click="foo.bar++">click2</button> </div> </templ ...

Is there a solution for the continuous automatic incrementing of the jQuery UI spinner that occurs when I right-click on it?

Only Linux and Mac OS users are facing this particular issue, indicating a potential bug with the jQuery spinner. The bug also affects the spinner located at the following link: https://jqueryui.com/spinner/ <input class="spinner"/> $(".spinner"). ...

Why isn't this setState function activating?

I am working on creating a versatile notification React component for my application that can be accessed from any part of the code. I have written the following code, where I am attempting to find a workaround for exporting the showNotif function: func ...

I encountered an Angular error that is preventing me from updating and uploading images to my Firebase Storage because it is unable to locate the storage bucket

Hey there fellow developers! I'm currently working on a simple Angular app that allows users to upload images to a gallery. However, I've encountered an issue while trying to upload the images to Firebase Storage. I keep getting an error mentioni ...

Encountering a "Element is not defined" error in Nuxt when trying to render Editor.js and receiving

I've been working on creating an editor using Editor.js within my Nuxt project, but it seems like the editor isn't initializing properly when I render the page. import EditorJS from '@editorjs/editorjs'; interface IEditor { editor: E ...

Delete particular user inputs following a $.ajax request

I have created a search feature with inputs that allow users to search the database using ajax requests. Unfortunately, I am facing an issue where the response from the server includes the search inputs themselves. This is not what I want. Here's a ...

What steps should I follow to utilize a JavaScript dependency following an NPM installation?

After successfully installing Fuse.js using npm, I am having trouble using the dependency in my JavaScript code. The website instructions suggest adding the following code to make it work: var books = [{ 'ISBN': 'A', 'title&ap ...

As soon as I closed the modal, I noticed that the checked inputs reverted back to

I am using checkboxes within a modal to narrow down my search results. However, I have encountered an issue where when I check multiple checkboxes and then close the modal, the checked inputs become unchecked. Every time I open the modal, I want the check ...

ng-show and ng-hide toggling for the active row

I have a single table where I am implementing row hide and show functionality using Angular for editing and saving purposes. So far, everything works as expected. $scope.init=function(){ $scope.editable=true; } Now, when I click on the edit button ...

The specified timeout elapsed without the jasmine async callback being invoked

Having recently ventured into Protractor and javascript, I've encountered a persistent error that none of the existing solutions seem to shed light on. The issue revolves around understanding async callbacks within my Page Object model implementation. ...

Showcase Pictures from a Document

Is there a way to upload an image via an input field and display it? I want to showcase a profile picture that can be saved in a database. The process should be simple for the user, with the ability to easily upload and view the image. function Save() { ...

Dealing with issues escaping unicode characters in JavaScript

Whenever I need to load data from an external file based on a specific event, I make use of the following jQuery code: $("#container").load("/include/data.php?name=" + escape(name)); An issue arises when the JavaScript variable "name" contains Unicode ch ...

Struggling to dynamically fill the table with Ajax Json data

After retrieving data from my webservice call, I am sending this JSON response: [ [ { "id": 123, "vendorName": "PoppyCounter", "item": "Chocolate" }, { "id": 1234, "ve ...

Tips for preparing HTML content with Jquery's "ON" method?

My jQuery Accordion is functioning properly, but I'm encountering issues when trying to load the accordion content dynamically from a database or JSON onto the page. The problem arises because the DOM doesn't have information about the newly inje ...

Sharing data between view and controller in Laravel: a guide

Currently, I am developing a product cart feature that includes subtotal and grand total values displayed within <span> tags. My goal is to pass the grand total value to the controller for further processing. However, I encountered an issue where the ...

Adjust the displayed HTML Tag within a Vue Component to add variety

Is it possible to allow a user to choose which HTML tag will be rendered in a VueJS Component? For example, consider <my-component>Some Text</my-component>. I would like to create a property called "tag" that determines the HTML tag to render ...

Inquiring about the Model component within the MVC architecture in a web application created with NodeJs and integrated with

As a beginner in NodeJs, I am venturing into creating web applications using the express framework and MySQL. Understanding that in MVC architecture, views are represented by *.ejs files, controllers handle logic, and models interact with the database. Ho ...

The JQuery datepicker fails to display the current date

I am experiencing an issue with the datepicker on my webpage. While it is working correctly, the default date being displayed is '01/01/2001' instead of '11/23/2012', as I intended. Here is the jquery code I am using: $(":inpu ...

Solution: The issue where the children's onChange event was not updating the parent in Ant Design was discovered to be due to the Select and Table components nested inside a Tab not changing according to the pageSize

I'm facing an issue with updating a parent element when the children's onChange event is triggered. Specifically, I have an Ant Design Select and Table inside a Tab that are not reflecting changes in the pageSize value. Although setPageSize func ...