Vue

by Md. Atiquzzaman Soikat

HTML

<div id="app">
    <div>
      <div class="page" v-for="(block, pageIndex) in blocks" :key="pageIndex">
          <section ref="page" :key="pageIndex">
            <template v-if="block.schools">
              <h2>School</h2>
              <div ref="inputBlock" class="input-block" v-for="(school, index) in block.schools" :key="index" :data-block="parseObject({pageIndex, index, type: 'schools'})">
                <div>
                  <label for="">Name</label>
                  <input v-model="school.name" type="text">
                  <label for="">Description</label>
                  <textarea v-model="school.description" name="" id="" cols="30" rows="6"></textarea>
                </div>
              </div>
              <button @click.prevent="addSchool(pageIndex)">add school</button>
              <button @click.prevent="remove(pageIndex, index, 'schools')">remove</button>
            </template>
            <template v-if="block.universities">
              <h3>University</h3>
              <div :data-block="parseObject({pageIndex, index, type: 'universities'})" ref="inputBlock" class="input-block" v-for="(university, index) in block.universities" :key="university.name">
                <div>
                  <label for="">Name</label>
                  <input v-model="university.name" type="text">
                  <label for="">Description</label>
                  <textarea v-model="university.description" name="" id="" cols="30" rows="6"></textarea>
                </div>
              </div>
              <button @click.prevent="addUniversity(pageIndex)">add university</button>
              <button @click.prevent="remove(pageIndex, index, 'universities')">remove</button>
            </template>  
            <template v-if="block.work">
              <h3>Work</h3>
              <div :data-block="parseObject({pageIndex, index, type: 'work'})" ref="inputBlock" class="input-block" v-for="(work, index) in block.work" :key="index">
               ...

SCSS

body {
  background: #FFF;
  padding: 20px;
  font-family: Helvetica;
}

.page {
  width: 750px;
  height: 800px;
  margin: 0 auto;
  border: 2px solid #ccc;
  padding: 20px;
  overflow: hidden;
}

.input-block div {
  display: flex;
  flex-direction: column;
  text-align: left;
  background-color: #d3d3d3;
  padding: 0.5rem;

  input {
    margin-bottom: 1rem;
    max-width: 80%;
  }
}

Vue

new Vue({
  el: "#app",
  data: () => ({
    blocks: [{
      schools: [{name: '', description: ''}],
      universities: [{name: '', description: ''}],
      work: [{name: '', duration: ''}],
    }],
    pageHeight: 800,
  }),
  created() {
    //
  },
  methods: {
    addSchool(index) {
      this.blocks[index].schools.push({name: '', description: ''})
      this.$nextTick().then(() => {
        this.checkContentOverflow();
      })
    },
    addUniversity(index) {
      this.blocks[index].schools.push({name: '', description: ''})
      this.$nextTick().then(() => {
        this.checkContentOverflow();
      })
    },
    addWork(index) {
      this.blocks[index].works.push({name: '', duration: ''})
      this.$nextTick().then(() => {
        this.checkContentOverflow();
      })
    },
    addBlock(){
      this.blocks.push({});
    },
    remove(pageIndex, index, type) {
      const activeBlock = this.blocks[pageIndex];
      activeBlock[type].splice(index, 1)
    },
    getCurrentPage(index){
      const pages = this.$refs.page;
      return pages[index]
    },
    getContentType(type) {
      const content = {
        schools: {name: '', description: ''},
        universities: {name: '', description: ''},
        work: {name: '', duration: ''}
      }
      return content[type]
    },
    checkContentOverflow() {
      const blocks = this.$refs.inputBlock;
      const overflowBlock = blocks.filter((block) => {
          return block.offsetTop > this.pageHeight;
      })
      const elementToMove = overflowBlock[0];
      if(elementToMove) {
        const blockAttr = elementToMove.getAttribute('data-block');
        const blockObj = JSON.parse(blockAttr)
        const {pageIndex, index, type} = blockObj;
        if(typeof this.blocks[pageIndex + 1] === 'undefined'){
          this.addBlock();
        }
        const presentBlock = this.blocks[pageIndex][type].splice(index, 1);
        const block = this.blocks[pageIndex + 1];
        console.log(block);
   ...