Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Render Component in iframe using vuejs without src attribute

<iframe id="frame" width="100%" height="100%">

</ifrme>

I want to render component in this iframe. Is there any option of creating html element or rendering component in iframe?

new Vue({
   el:'#frame',
   store:store,
   router:router,
   render: component
})
like image 482
Vishal Dodiya Avatar asked Mar 29 '17 08:03

Vishal Dodiya


People also ask

How do I render my Vue component?

The best way to force Vue to re-render a component is to set a :key on the component. When you need the component to be re-rendered, you just change the value of the key and Vue will re-render the component.

What is iframe Srcdoc?

The srcdoc attribute specifies the HTML content of the page to show in the inline frame. Tip: This attribute is expected to be used together with the sandbox and seamless attributes. If a browser supports the srcdoc attribute, it will override the content specified in the src attribute (if present).

How do I use iframe tags?

Definition and UsageThe <iframe> tag specifies an inline frame. An inline frame is used to embed another document within the current HTML document. Tip: Use CSS to style the <iframe> (see example below). Tip: It is a good practice to always include a title attribute for the <iframe> .

For what purpose is the render () function used in Vue?

A render function returns a virtual DOM node, commonly named VNode in the Vue ecosystem, which is an interface that allows Vue to write these objects in your browser DOM. They contain all the information necessary to work with Vue.


2 Answers

You can refer below link That helped me a lot. Here is the link and the code snippets.

Vue.component('i-frame', {
  render(h) {
    return  h('iframe', {
      on: { load: this.renderChildren }
    })
  },
  beforeUpdate() {
    //freezing to prevent unnessessary Reactifiation of vNodes
    this.iApp.children = Object.freeze(this.$slots.default)
  },  
  methods: {
    renderChildren() {
      const children = this.$slots.default
      const body = this.$el.contentDocument.body      
      const el = document.createElement('DIV') // we will mount or nested app to this element
      body.appendChild(el)
      
      const iApp = new Vue({
        name: 'iApp',
        //freezing to prevent unnessessary Reactifiation of vNodes
        data: { children: Object.freeze(children) }, 
        render(h) {
          return h('div', this.children)
        },
      })
      
      iApp.$mount(el) // mount into iframe
      
      this.iApp = iApp // cache instance for later updates
      
      
    }
  }
})

Vue.component('test-child', {
  template: `<div>
  <h3>{{ title }}</h3>
  <p>
  <slot/>
  </p>
  </div>`,
  props: ['title'],
  methods: {
    log:  _.debounce(function() {
      console.log('resize!')
    }, 200)
  },
  mounted() {
    this.$nextTick(() => {
      const doc = this.$el.ownerDocument
      const win = doc.defaultView
      win.addEventListener('resize', this.log)
    })
  },
  beforeDestroy() {
    const doc = this.$el.ownerDocument
    const win = doc.defaultView
    win.removeEventListener('resize', this.log)
  }  
})

new Vue({
  el: '#app',
  data: {
    dynamicPart: 'InputContent',
    show: false,
  }
})

https://jsfiddle.net/Linusborg/ohznser9/

like image 167
Vishal Dodiya Avatar answered Oct 20 '22 00:10

Vishal Dodiya


The easiest way for me is to use srcdoc attribute. It loads raw html overriding src attribute.

<template>
    <iframe :srcdoc="html"></iframe>
</template>

Update: More detail example: Consider a textarea for a user html input and want to display in an iframe.


<template>
  <div id="app">
    <textarea v-model="html"></textarea>
    <iframe :srcdoc="html"></iframe>
  </div>
</template>

<script>
export default {
  name: "App",
  data(){
    return {
      html:"<h1>Hello I am H1 block</h1>"
    }
  }
};
</script>
like image 44
Bedram Tamang Avatar answered Oct 20 '22 00:10

Bedram Tamang