Why does Vue.js lose formatting when adding dynamic items? Is it possible to correct this?

1

I have a form where the phone fields is dynamic so the user can add as many numbers as he wants.

But when I click the button to add new item, this created item appears unformatted. Not to mention that a bug still descends the entire screen.

See what happens in the gif below:

Itriedtoinsertthedirectcodehere,buttheBoostrapformattingwasnotappearing,soIputitinthecodepen:

link

I know this can happen because vue.js tries to add an item after the screen has already been rendered, I remember that jquery had this same problem, until they launched the live method that kept the formatting with dynamic items. / p>

Can I fix this problem in vue?

    
asked by anonymous 19.10.2018 / 18:53

2 answers

2

The problem is not VueJS , the problem is that Bootstrap can not "see" the new element, so it is necessary to (re) start Bootstrap Material Design every time you add a new element.

One way to do this is by creating a custom directive , so every time there is a change in the element, the policy will be responsible for restarting Bootstrap.

JavaScript:

Vue.directive('update-material-design', {
  inserted(el) {
    $(el).bootstrapMaterialDesign();
  }
})

HTML:

<div class="row clearfix" v-for="(row, index) in rows" v-update-material-design>
Ready! Now every time a field is added inside the div above, the update-material-design directive will be executed.

Full Example:

$(document).ready(function() {
  $('body').bootstrapMaterialDesign();
});

var telsadd = new Vue({
  el: "#telsadicionais",
  data: {
    rows: [{
      teltipo: "celtim",
      telddd: "15",
      telnumber: "3429-2410"
    }, {
      teltipo: "whatsapp",
      telddd: "34",
      telnumber: "46536546"
    }]
  },
  methods: {
    addRow: function() {
      this.rows.push({
        teltipo: "",
        telddd: "13",
        telnumber: ""
      });
    },
    removeElement: function(index) {
      this.rows.splice(index, 1);
    }
  }
});

Vue.directive('update-material-design', {
  inserted(el) {
    $(el).bootstrapMaterialDesign();
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script><scriptsrc="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script><scriptsrc="https://unpkg.com/[email protected]/dist/umd/popper.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script><scriptsrc="https://unpkg.com/[email protected]/dist/js/bootstrap-material-design.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.13.2/js/bootstrap-select.min.js"></script><linkhref="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://unpkg.com/[email protected]/dist/css/bootstrap-material-design.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.13.2/css/bootstrap-select.min.css" rel="stylesheet"/>


<div id="telsadicionais">
  <div class="row clearfix" v-for="(row, index) in rows" v-update-material-design>
    <div class="col-sm-4">     
      <div class="form-group">
        <div class="form-line">
          <select name="teltipo[]" class="form-control show-tick" title="Tipo" v-model="row.teltipo">
            <option value="fixo">Fixo</option>
            <option value="celvivo">Celular - Vivo</option>
            <option value="celclaro">Celular - Claro</option>
            <option value="celtim">Celular - Tim</option>
            <option value="celoi">Celular - Oi</option>
            <option value="celnextel">Celular - Nextel</option>
            <option value="celoutros">Celular - Outro</option>
            <option value="whatsapp">Whatsapp</option>
          </select>
        </div>
      </div>
    </div>
    <div class="col-sm-1">
<div class="form-group">
    <label for="ddd" class="bmd-label-floating">DDD</label>
    <input type="text" name="telddd[]" class="form-control" maxlength="2" id="ddd" v-model="row.telddd">
  </div>
    </div>
    <div class="col-sm-5">
<div class="form-group">
    <label for="telnumber" class="bmd-label-floating">Numero</label>
    <input type="text" name="telnumber[]" class="form-control" maxlength="12" id="telnumber" v-model="row.telnumber">
  </div>
    </div>
    <div class="col-sm-2">
      <a class="btn btn-primary" v-on:click="removeElement(index);" style="cursor: pointer">Remove</a>
    </div>
  </div>
  <button class="btn btn-primary" @click="addRow">Adicionar</button>
</div>
    
19.10.2018 / 23:17
1

Vue does not lose the formatting of dynamically added items, but there are some important considerations you need to make about your code:

  

1 -

for N reasons.

     

2 - For the link you are using Bootstrap4 with jQuery, there is the Vue which is what I'm using in the reply.

     

3 - This put you just put a label for the select tag as I did in the example, or give a margin-top no select with CSS as I did in the example with the remove buttons.

var telsadd = new Vue({
  el: "#telsadicionais",
  data: {
    rows: [{
      teltipo: "celtim",
      telddd: "15",
      telnumber: "3429-2410"
    }, {
      teltipo: "whatsapp",
      telddd: "34",
      telnumber: "46536546"
    }]
  },
  methods: {
    addRow: function() {
      this.rows.push({
        teltipo: "",
        telddd: "13",
        telnumber: "992300312"
      });
    },
    removeElement: function(index) {
      this.rows.splice(index, 1);
    }
  }
});
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css"/>
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.css"/>
<script src="https://cdn.jsdelivr.net/npm/vue"></script><divid="telsadicionais">
  <div class="row clearfix" v-for="(row, index) in rows">
    <div class="col-sm-4">     
      <div class="form-group">
        <div class="form-line">
          <label>Selecione a operadora</label>
          <select name="teltipo" class="form-control show-tick" title="Tipo" v-model="row.teltipo">
            <option value="fixo">Fixo</option>
            <option value="celvivo">Celular - Vivo</option>
            <option value="celclaro">Celular - Claro</option>
            <option value="celtim">Celular - Tim</option>
            <option value="celoi">Celular - Oi</option>
            <option value="celnextel">Celular - Nextel</option>
            <option value="celoutros">Celular - Outro</option>
            <option value="whatsapp">Whatsapp</option>
          </select>
        </div>
      </div>
    </div>
    <div class="col-sm-1">
<div class="form-group">
    <label for="ddd" class="bmd-label-floating">DDD</label>
    <input type="text" name="telddd[]" class="form-control" maxlength="2" id="ddd" v-model="row.telddd">
  </div>
    </div>
    <div class="col-sm-5">
<div class="form-group">
    <label for="telnumber" class="bmd-label-floating">Numero</label>
    <input type="text" name="telnumber[]" class="form-control" maxlength="12" id="telnumber" v-model="row.telnumber">
  </div>
    </div>
    <div class="col-sm-2">
      <a class="btn btn-danger" v-on:click="removeElement(index);" style="cursor: pointer;margin-top:30px;">Remove</a>
    </div>
  </div>
  <button class="btn btn-primary" @click="addRow">Adicionar</button>
</div>
  

Follow some CSS framework links for use with Vue.js

19.10.2018 / 22:58