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

Retrieving every single .json file present in a specific folder

I'm working on developing an Android app that utilizes JSON data. Is there a method to establish a directory structure similar to this: http://......./jsons/*.json Or is there another way to append additional data into a JSON file (such as a.json) a ...

How to sort objects by keys in AngularJS

Currently, I am working on building a sorting list using AngularJS. The goal is to have the data updated in the DOM dynamically when a user clicks on the name of a value. I am attempting to order the values by categories such as Bracelets, Charms, Earrings ...

Managing Form Data with Vuex

Within my Vuex implementation, I have two computed properties used to display state data: computed:{ dataTab:function(){ return this.$store.state.form; }, ...Vuex.mapState({ mapA: state=>state.form.a }), }, Afte ...

Retrieve, establish cookies, and guard against CSRF attacks

Having some difficulty with CSRF in my application while using Isomorphic fetch. The backend sends a CSRF-TOKEN in the set-cookies property: There is advice against directly accessing these cookies in code, so I attempted utilizing the credentials proper ...

Numerous comparisons between ngIf and ngShow are made when dealing with intricate user interfaces and form structures

After searching, I couldn't find a satisfactory answer to my question about when to use ngShow versus ngIf. Alternative to ng-show/-hide or how to load only relevant section of DOM What is the difference between ng-if and ng-show/ng-hide When to fav ...

Is there a way to repurpose a JavaScript object that gets sent back to the client upon page loading?

Upon initial page load, an AJAX request fetches a list of JavaScript objects which display only one value each. The page includes buttons to expand each item and reveal the remaining values. Originally, I used another AJAX call to retrieve individual objec ...

Expanding form fields dynamically with AngularJS

I am currently working on a form that allows users to click a '+' sign in order to add new lines. I've set up a function to be called when the button is clicked, which should push a new line into the array. However, for some reason the new l ...

Issue with Mat-AutoComplete arising while utilizing a formArray

After adding a form array to account for multiple rows, I had to modify my definition from: shoppingCartList Observable<any[]>; to shoppingCartList: Observable<any[]>[] = [];. However, this change resulted in an error in my filter function whic ...

Maintain the visibility of the jQuery dropdown menu even when navigating to a different page within the

I am experiencing an issue with my dropdown menu. Whenever I click on a "dropdown link", it opens another page on my website, but the menu closes in the process. I want to ensure that the menu stays open and highlights the clicked "dropdown link" in bold. ...

Event with no refresh required

When using chat scripts, new lines can be added without reloading the page. The user's availability status can change without a postback. Similar to Facebook, a new comment can be added without reloading the page. How can an event be triggered in ASP. ...

Preventing Javascript array elements from being overwritten: Best practices

My challenge lies with the addToClients() function, which is designed to add a new value to the clients array whenever a button is pressed. The issue I am facing is that each time I press submit, the previous element in the array gets replaced by the new o ...

Issues with hover functionality in React Material Design Icons have been identified

I'm facing an issue with the mdi-react icons where the hovering behavior is inconsistent. It seems to work sometimes and other times it doesn't. import MagnifyPlusOutline from "mdi-react/MagnifyPlusOutlineIcon"; import MagnifyMinusOutli ...

When running "npx create-nuxt-app" followed by "npm run dev", an error occurs stating that there

Recently, I started using Nuxt and initiated my app with npx create-nuxt-app my-app, setting the parameters as follows: Project name: client Programming language: JavaScript Package manager: Npm UI framework: Tailwind CSS Nuxt.js modules: Axios - Prom ...

What is the best way to apply a specific style based on the book ID or card ID when a click event occurs on a specific card in vue.js

My latest project involves creating a page that displays a variety of books, with the data being fetched from a backend API and presented as cards. Each book card features two button sections: the first section includes "ADD TO BAG" and "WISHLIST" buttons ...

Animation of disappearing blocks covering the entire screen

I am currently working on creating a slider with fading blocks animation similar to the one shown here. The challenge I am facing is making it fullscreen, where the height and width will be variable. This makes using the background-position trick ineffecti ...

Tips on removing either the date or time when input type date and input type time share the same ng-model

In my Ionic app built with AngularJS, I have a form where the date and time are displayed separately but share the same data-ng-model: <input type="date" id ="actualVisitDate" data-ng-model="actualVisitDate" required> <input type="time" id ="actu ...

Soundex and Metaphone implementation for Phonegap application development on the Android platform

I am trying to perform SQL searches on Android through PhoneGap using functions like soundex or metaphone. However, both soundex and metaphone are not functioning properly. For example: SELECT * FROM customers WHERE soundex(surname) = soundex('M ...

Using JavaScript to invoke Applescript commands

Is it feasible to execute Applescript from JavaScript? I would be grateful if someone could offer a sample code or useful reference link. ...

Sudden slowdown due to Jquery error

I am encountering an issue with the Jquery registration validation. I am struggling to display the error message if a name is not filled in. jQuery(document).ready(function () { $('#register').submit(function () { var action = $(thi ...

Executing a function when a user chooses to exit a webpage using the @HostListener('window:beforeunload') method

Utilizing @HostListener('window:beforeunload') allows me to detect when a user navigates away from the page, prompting a dialog window to open. I wish for an event to be triggered or a method to be executed if the user chooses to leave the page. ...