iframe-resizer icon indicating copy to clipboard operation
iframe-resizer copied to clipboard

Vue

Open SmarterPhoneLabs opened this issue 7 years ago • 29 comments

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>

SmarterPhoneLabs avatar Aug 21 '17 17:08 SmarterPhoneLabs

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 avatar Sep 26 '17 17:09 davidjbradshaw

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

itafras avatar Nov 10 '17 14:11 itafras

I did, but I ended up having to do some witchcraft on my asp.net application to make it work

On Fri, Nov 10, 2017 at 8:07 AM, itafras [email protected] wrote:

Did you find a solution @SmarterPhoneLabs https://github.com/smarterphonelabs ? I am trying to do implement iframeResizer with my vue app as well.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/davidjbradshaw/iframe-resizer/issues/513#issuecomment-343482378, or mute the thread https://github.com/notifications/unsubscribe-auth/ABIq5ScfHNYsfgAwjMrS3Hv0d2zomrHqks5s1FipgaJpZM4O9m4I .

SmarterPhoneLabs avatar Nov 10 '17 14:11 SmarterPhoneLabs

Care to share?

davidjbradshaw avatar Nov 10 '17 17:11 davidjbradshaw

It was highly specific to our app, so I doubt it would be useful to you.

On Fri, Nov 10, 2017 at 11:41 AM, David J. Bradshaw < [email protected]> wrote:

Care to share?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/davidjbradshaw/iframe-resizer/issues/513#issuecomment-343538782, or mute the thread https://github.com/notifications/unsubscribe-auth/ABIq5bIaj2lLPzR0sztX7hqOR0zE4hHYks5s1IrGgaJpZM4O9m4I .

SmarterPhoneLabs avatar Nov 10 '17 17:11 SmarterPhoneLabs

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

geriiat avatar Feb 28 '18 09:02 geriiat

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.

Dreimus avatar Aug 08 '18 09:08 Dreimus

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!

catskull avatar Nov 20 '18 22:11 catskull

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

adesombergh avatar Sep 30 '19 14:09 adesombergh

That looks nice and simple, would be great to be able to pass options to iframe-resizer via the directive

davidjbradshaw avatar Sep 30 '19 15:09 davidjbradshaw

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>

adesombergh avatar Oct 04 '19 09:10 adesombergh

Why does my use in vue not work?

shiyabin avatar Mar 24 '20 09:03 shiyabin

Thanks for sharing your experience with this!

The v-resize directive in https://github.com/davidjbradshaw/iframe-resizer/issues/513#issuecomment-538333854 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>

JCFerrerG avatar Apr 14 '20 15:04 JCFerrerG

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.

victornpb avatar May 08 '20 14:05 victornpb

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>

ayalon avatar May 20 '20 10:05 ayalon

Creating plugin in Nuxt, it doesnt work!:(

gaglage avatar Sep 19 '20 08:09 gaglage

@gaglage you might look at https://github.com/davidjbradshaw/iframe-resizer/issues/831 for experience with Nuxt.js

JCFerrerG avatar Sep 19 '20 16:09 JCFerrerG

thanks! I'll check it

gaglage avatar Sep 19 '20 17:09 gaglage

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 avatar Jan 30 '21 22:01 MeStrak

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/[email protected]/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: https://github.com/vuetifyjs/vuetify/issues/11452, so the iFrame resizes to fit the whole screen height everytime.

MeStrak avatar Jan 30 '21 22:01 MeStrak

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 avatar Nov 25 '21 09:11 picks44

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>

picks44 avatar Nov 25 '21 10:11 picks44

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();
  },
};

drewm avatar May 19 '22 10:05 drewm

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

yangxinSamsara avatar Jul 06 '22 12:07 yangxinSamsara

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

rotimidokun avatar Aug 27 '22 14:08 rotimidokun

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))
      },
    },
  },

drewzb avatar May 25 '23 15:05 drewzb

Hi @catskull the solution (https://github.com/davidjbradshaw/iframe-resizer/issues/513#issuecomment-979048597) returns the following warning.

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

sachinkumar121 avatar Dec 20 '23 13:12 sachinkumar121

@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 avatar Apr 14 '24 10:04 davidjbradshaw

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 avatar Apr 14 '24 16:04 davidjbradshaw