Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vue #513

Closed
SmarterPhoneLabs opened this issue Aug 21, 2017 · 30 comments
Closed

Vue #513

SmarterPhoneLabs opened this issue Aug 21, 2017 · 30 comments

Comments

@SmarterPhoneLabs
Copy link

SmarterPhoneLabs commented Aug 21, 2017

Hi there,

I am trying to get your component to work inside of Vue 2
I was able to get the npm installed and my host page running.
I have the client script installed in the child iframe as well, but am getting this warning/error:

[iFrameSizer][Host page: oauth2relay737909339] IFrame has not responded within 10 seconds. Check iFrameResizer.contentWindow.js has been loaded in iFrame. This message can be ingored if everything is working, or you can set the warningTimeout option to a higher value or zero to suppress this warning.

I also setup the callbacks, but the messages that come back on resize and message are 'undefined'.

<template>
	<div class="row">
		<div class="col-lg-12">
			<div class="panel panel-flat">
				<!-- <iframe id="myIframe" :src="getTarget()" scrolling="no" ref="myIFrame" />  -->
				<iframe id="myIframe" src="https://www.trueatlas.com/vanilla.html" scrolling="no" ref="myIFrame">
				</iframe>


			</div>
		</div>
	</div>
</template>
<script lang="ts">
	import * as Vue from 'vue'
	import { NavigationService } from '../../shared/Utilities/Navigation';
	import * as resizer from 'iframe-resizer';
	import { Bus } from '../../main';
	export default {
		name: 'iFrameHolder',
		data() {
			return {
				NS: NavigationService,
				ifr: resizer,
			}
		},
		components: { resizer },
		methods:
		{
			msgCB: function () {
				console.log('got ready');
			},
			gotMessage: function (messageData) {
				console.log(messageData)
			},
			resizeIframe: function (height) {
				console.log(height);
				//document.getElementById('frame_name_here').height = parseInt(height)+60;
			},
			getiFrameWidth: function () {
				return this.$store.state.iframeWidth;
			},
			getiFrameHeight: function () {
				return this.$store.state.iframeHeight;
			},
			getTarget: function () {

				return this.$store.state.iframeTarget;
			}
		},

		updated: function () {
			this.ifr.iframeResizer({ log: true, warningTimeout: 10, checkOrigin: false, autoResize: true, resizeFrom: 'child', messageCallback: function (messageData) { console.log() }, readyCallback: this.msgCB() }, this.$refs.myIFrame);
		},
		created: function () {
			this.NS = new NavigationService();
			this.NS.router = this.$router;
			this.$store.state.Crumb = "";

			this.ifr.iframeResizer({ log: true, warningTimeout: 10000, checkOrigin: false, autoResize: true, resizeFrom: 'child', resizedCallback: this.gotMessage(), messageCallback: this.gotMessage(), readyCallback: this.msgCB() }, this.$refs.myIFrame);


		}
	}

</script>
<style>
	iframe {
		width: 100%
	}
</style>
@davidjbradshaw
Copy link
Owner

Never used Vue, so not sure what is going on. If you put a simple test case online somewhere I'll take a quick look.

@davidjbradshaw davidjbradshaw changed the title [iFrameSizer][Host page: xxx] IFrame has not responded within 10 seconds. Check iFrameResizer.contentWindow.js has been loaded in iFrame. This message can be ingored if everything is working, or you can set the warningTimeout option to a higher value or zero to suppress this warning. Vue Sep 27, 2017
@itafras
Copy link

itafras commented Nov 10, 2017

Did you find a solution @SmarterPhoneLabs ? I am trying to do implement iframeResizer with my vue app as well.

@SmarterPhoneLabs
Copy link
Author

SmarterPhoneLabs commented Nov 10, 2017 via email

@davidjbradshaw
Copy link
Owner

Care to share?

@SmarterPhoneLabs
Copy link
Author

SmarterPhoneLabs commented Nov 10, 2017 via email

@geriiat
Copy link

geriiat commented Feb 28, 2018

Hi!
Try to move it into the mounted, maybe this solves your problem.

@Dreimus
Copy link

Dreimus commented Aug 8, 2018

Hey there,

We got a fix in vuejs. You have to create a directive :
We installed the package from npm
TWIG :

<iframe src="{{ src }}" id="iframe" v-resize></iframe>

JS :


import Vue from 'vue';
import iFrameResize from 'iframe-resizer/js/iframeResizer'

Vue.directive('resize', {
    inserted: function (el) {

        iFrameResize({log:true}, '#'+el.id);
    }
});

Hope it helps.

@catskull
Copy link

While the directive approach works, I didn't want to have to include the iframeResizer JS in my entire application since I lazy load the components and only one component shows an iFrame. You actually don't have to use a directive to use this in vue. Here's how I did it:

Template:

<iframe
  id="iframe"
  :src="source"
  style="min-width: 100%; border: none;"
  scrolling="no"
  @load="iframeLoaded"
/>

Script:

<script>
import iFrameResize from 'iframe-resizer/js/iframeResizer'

export default {
  name: 'component name',

  data () {
    return {
      source: ''
    }
  },

  methods: {
    iframeLoaded () {
      iFrameResize({log: true}, '#iframe')
    }
  }
}
</script>

That works fine for me and is a bit cleaner for my application! If you're doing this in multiple places then I'd still recommend @Dreimus solution above!

@adesombergh
Copy link

Hey,

Here is a different approach based on @Dreimus 's code:

import Vue from 'vue'
import iFrameResize from 'iframe-resizer/js/iframeResizer'

Vue.directive('resize', {
  bind: function (el) {
    el.addEventListener('load', () => iFrameResize({}, el))
  },
})

This way:

  • You don't need an id attribute
  • Only run iFrameResize when the iframe has loaded which will prevent an error

@davidjbradshaw
Copy link
Owner

davidjbradshaw commented Sep 30, 2019 via email

@adesombergh
Copy link

adesombergh commented Oct 4, 2019

Good idea,
this should work:

import Vue from 'vue'
import iFrameResize from 'iframe-resizer/js/iframeResizer'

Vue.directive('resize', {
  bind: function (el, {value = {}}) {
    el.addEventListener('load', () => iFrameResize(value, el))
  },
})

Now we can pass options like this:

<iframe v-resize="{ log: true }" width="100%" src="myiframe.html" frameborder="0"></iframe>

@shiyabin
Copy link

Why does my use in vue not work?

@JCFerrerG
Copy link

Thanks for sharing your experience with this!

The v-resize directive in #513 (comment) fails with Vuetify because Vuetify handles the value as a callback. To disable this behavior, Vuetify has a quiet modifier (see the Vuetify docs for details).

So, the following directive works with Vuetify:

<iframe v-resize.quiet="{ log: true }" width="100%" src="myiframe.html" frameborder="0"></iframe>

@victornpb
Copy link

victornpb commented May 8, 2020

While the directive approach works, I didn't want to have to include the iframeResizer JS in my entire application since I lazy load the components and only one component shows an iFrame.

You don't need to register a directive globally you can declare it just like any other component:

component.vue

<template>
     ...
     <iframe v-iframe-resize="{log:true}"></iframe>
     ...
</template>
<script>
import iframeResize from './v-iframe-resize.js';
export default {
    directive: {
        'iframe-resize': iframeResize,
    },
    // component impl.
}
</script>

Directive:
v-iframe-resize.js

import iFrameResize from 'iframe-resizer/js/iframeResizer'

export default {
  bind(el, binding) {
     iFrameResize(binding.value, el);
  },
};

its also good idea to handle properties changing, and unbinding.

@ayalon
Copy link

ayalon commented May 20, 2020

The above code is wrong. "directives" instead of "directive". Name without "v-"

<template>
     ...
     <iframe v-iframe-resize="{log:true}"></iframe>
     ...
</template>
<script>
export default {
  directives: {
    'iframe-resize': {
      bind(el, binding) {
        iFrameResize(binding.value, el)
      }
    }
  }
 }
</script>

@gaglage
Copy link

gaglage commented Sep 19, 2020

Creating plugin in Nuxt, it doesnt work!:(

@JCFerrerG
Copy link

@gaglage you might look at #831 for experience with Nuxt.js

@gaglage
Copy link

gaglage commented Sep 19, 2020

thanks! I'll check it

@MeStrak
Copy link

MeStrak commented Jan 30, 2021

I have the same error message as @SmarterPhoneLabs, I think it might be an issue installing the script on the child page. Does anyone have an example of installing the contentWindow script on a VueJS child page?

@MeStrak
Copy link

MeStrak commented Jan 30, 2021

Added this into my child page, and it seems to be working:

mounted() {
    const resizerScript = document.createElement('script')
    resizerScript.setAttribute('src', 'https://cdn.jsdelivr.net/npm/iframe-resizer@4.3.1/js/iframeResizer.contentWindow.min.js')
    document.head.appendChild(resizerScript)
    }

However I'm using Vuetify and have an issue specific to that framework which forces pages to be full-screen height, even if there are only a few lines of text: vuetifyjs/vuetify#11452, so the iFrame resizes to fit the whole screen height everytime.

@picks44
Copy link

picks44 commented Nov 25, 2021

Anyone succeeded to use this with Vue3?

I've tried doing this but my frame isn't resized...

<template>
  <div>
    <iframe
      v-iframe-resize="{ log: true }"
      src="myURL"
    ></iframe>
  </div>
</template>

<script>
import iFrameResize from 'iframe-resizer/js/iframeResizer'

export default {
  name: 'Selector',
  directives: {
    'iframe-resize': {
      bind(el, binding) {
        iFrameResize(binding.value, el)
      }
    }
  }
}
</script>

<style scoped lang="scss">
iframe {
  width: 1px;
  min-width: 100%;
}
</style>

@picks44
Copy link

picks44 commented Nov 25, 2021

OK, solved it:

<script>
import iFrameResize from 'iframe-resizer/js/iframeResizer'

export default {
  name: 'Selector',
  directives: {
    'iframe-resize': {
      beforeMount(el, binding) {
        iFrameResize(binding.value, el)
      }
    }
  }
}
</script>

@drewm
Copy link

drewm commented May 19, 2022

A Vue 3 example using script setup:

<script lang="ts" setup>
import iframeResize from 'iframe-resizer/js/iframeResizer';

const vResize = {
  mounted: (el, { value = {} }) => {
    el.addEventListener('load', () => iframeResize(value, el));
  },
  unmounted: (el) => {
    el.iFrameResizer.removeListeners();
  },
};

@yangxinSamsara
Copy link

如果你用的是vue+vuetify,指令不要用v-resize,vuetify自身有这个指令

@rotimidokun
Copy link

rotimidokun commented Aug 27, 2022

can I also see your template region of the iframe? @drewm

@drewzb
Copy link

drewzb commented May 25, 2023

For anyone struggling with this who is using Vuetify, I finally solved it. Vuetify already has it's own v-resize directive which causes a conflict. So you need to choose a different name.

<iframe
 v-resizer="{ log: false }"
  width="100%"
  style="width: 1px; min-width: 100%; height: 2000px"
  src="https://"
  frameborder="0"
></iframe>
directives: {
    resizer: {
      bind(el, { value = {} }) {
        el.addEventListener('load', () => iframeResize(value, el))
      },
    },
  },

@sachinkumar121
Copy link

Hi @catskull the solution (#513 (comment)) returns the following warning.

[iFrameSizer][Host page: iframe] Ignored iFrame, already setup.

@davidjbradshaw
Copy link
Owner

@drewm, @picks44, @JCFerrerG, @MeStrak, @victornpb

I'm currently working on a large v5 update (#1212) to iframe-resizer and I would like to includes an @iframe-resizer/vue component that ideally works with Vue, Vueify and Nuxt. Having never used any of these platforms before, I'm after a bit of help with this. The new version splits the NPM module into @iframe-resizer/parent and @iframe-resizer/child.

I have just published an alpha build of version 5 on NPM and have create a draft documentation site
https://iframe-resizer.github.io/docs/

This includes an upgrade guide
https://iframe-resizer.github.io/docs/upgrade/

and a guide for creating Framework components
https://iframe-resizer.github.io/docs/frameworks/api/

Would any of you be able to help create a small Vue wrapper component?

@davidjbradshaw
Copy link
Owner

As a starting point, this is roughly how I think the Vue3 example would need to be updated,

Vue Directive

import { Directive, DirectiveBinding } from "vue";
import connectResizer from "@iframe-resizer/core";

interface ResizableHTMLElement extends HTMLElement {
  iframeResizer?: {
    close: () => void;
    disconnect: () => void;
    moveToAnchor: (string) => void;
    resize: () => void;
    sendMessage: () => void;
  };
}

const iframeResizer: Directive = {
  mounted(el: HTMLElement, binding: DirectiveBinding) {
    const options = binding.value || {};
    const connectWithOptions = connectResizer(options);
    el.addEventListener("load", () => connectWithOptions(el));
  },
  unmounted(el: HTMLElement) {
    const resizableEl = el as ResizableHTMLElement;
    resizableEl?.iframeResizer.disconnect();
  },
};

export default resize;

Register the directive

const app = createApp(App)
...
app.directive('iframeResizer', connectResizer)
...
app.mount('#app')

Page

<iframe
  v-iframeResizer
  width="100%"
  src="myiframe.html"
  frameborder="0"
></iframe>

@davidjbradshaw
Copy link
Owner

We now have a Vue package

https://iframe-resizer.com/vue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests