Access Framework7-Api in Vue-Project from inside custom class or object literal?


#1

Hi,

i wonder how i would call Api-Methods from inside a custom class or object literal, because this is then referring to the Class Instance / Object.

I searched the window object, but couldn’t find anything.

My use case is the following:

Object Literal or Class:

var Test = {
    test: function () {
        // access the Framework7 API eg. request.json(...
        // Neither app.request nor Framework7.request works,
        // and the scope of this is the class or object here        
    }
}
export default Test;

in main.js:

import test from './common/test.js';
Vue.prototype.$test = test;

const app = new Vue({
...

And then in a component:

...
methods: {
    onTest() {
        this.$test.test();
    }
}
...

As said before, inside the Class or Object, this refers to the Class or Object Instance and in the window object i couldn’t find any hint to the api.

I’m still using Framework7 v2.

Thanks in advance.


#2

Hi, you can expose vue with
window.app = new Vue()
Or just send the instance of vue/f7/both as a param to the method you are calling;
eg:

methods: {
    onTest() {
        const params = {vm: this, param1: 'some-value'}
        this.$test.test(params);
    }
}
test: params {      
  params.vm.$f7 
  params.param1
  ..some logic here
}

#3

Hi pvtallulah,

thanks for your reply.

Regarding the param solution, that’s something i would like to avoid, because if i call multiple methods of multiple classes i would always have to passthru the instance, which would quickly become really cumbersome.

Putting the Vue instance into the global scope seems also not like a best practice, but i would go with it until i find something “cleaner”. (Is there no other, favored way of accessing Framework7s Api?)
But with this, another problem occurs:

If i try to access window.myApp inside either the onF7Ready or Vues mounted callback, it’s still undefined. When i access it later e.g. on a user interaction, it’s available.

As far as i understand the Vue instance life-cycle, it should be defined after the created callback is called. Mounted and onF7Ready are called even later, but the instance is still not created?!

Best wishes


#4

Ok, here is another solution i can think about, i dont know. maybe it fits your needs;

// However you import F7
import F7 from 'framework7/dist/framework7.esm.bundle.js';
const F7API = new F7()
var Test = {
    test: function () {
        F7API.dialog.alert('Testing my f7 api')
        // access the Framework7 API eg. request.json(...
        // Neither app.request nor Framework7.request works,
        // and the scope of this is the class or object here        
    }
  }

#5

I am using another solution. I have created file My.js

export default {
  app: null,
};

In the main.js, where we are initing Vue, I have assigned to My.app

import My from './My.js';
...
My.app = new Vue({...})
...

After that, I call from any place where necessary.

AnotherFileWhereNoVueOrFramework7Access.js

import My from './My.js';
...
My.app.$f7.panel.left.open(); //example, opening left panel
...

#6

Hi almazk,

thanks for your reply, but this solution has the same problem as noted above.
Meanwhile i migrated my app to Framework7v3, but the problem stays the same.

When i access the window.myApp or My.app object inside the $f7ready((f7) => { … callback, it is undefined. It seems like the Vue-instance is not ready, when this callback is called.

So starting initial tasks from this callback, when access to the F7-Api is needed, seems not possible…

Currently i guess there is no other way, than passing thru the f7 object from function to function, which is pretty ugly :frowning:

If i am missing something here, please enlighten me…


#7

Ok, my current solution is the following.

In App.vue:

mounted: function() {
    this.$f7ready((f7) => {
        window.$f7 = f7;
        // start initialization...

So the F7 Object is exposed to the global scope and can be accessed from “everywhere”. Not pretty, but due to the lack of alternatives, i’ll go with it.

Any thoughts?


#8

I migrated to v3 too. In my way, when we are requesting $f7.api in App.vue, my option is not usable, there is only f7. Before Vue mounted, there no global variable be assigned to $f7.


#9

That is pretty correct way of exposing f7 instance to global :+1:


#10

My 2 cents:

Make it a vue plugin!!!

export default
{
    install(Vue, options)
    {
        alert(Vue, options); // the imported function below
        // ... your other plugins here
    }
}

---

export default function(Vue)
{
    Object.defineProperty(Vue.prototype, "$dialogs",
    {
        get()
        {
            const self = this;

            return {
                alert()
                {
			return alert.apply(self, arguments);
		},
}

function alert(message, title)
{
    this.$f7.dialog.create(...); // this this is the same as Vue this
}

----

In your vue object:

methods:
{
    someMethod(message)
    {
        this.$dialogs.alert("Yay!");
    }
}

#11

BTW, you can use your this.$dialog also in non vue classes (as stores), if you make a Vue EventBus and import it on your classes:

import Vue from "vue";

const eventBus = new Vue({
	created()
	{
		setTimeout(() =>
		{
			this.$log.blue("EventBus", "Created");
		}, 100);
	},
});

export default eventBus;

On store:

import EventBus from "@/eventBus";

export default async function({ dispatch, commit }, payload)
{
	const auth = EventBus.$cache.get("auth"); // <-- EventBus is the this of Vue

(the this.$log is a colored log created with the method above, so is this.$cache)