Home > Back-end >  Vue.js 2 components data property bound to the first or to one only instance of component
Vue.js 2 components data property bound to the first or to one only instance of component

Time:12-31

Need help. I'm fairly new to Vue.js and need some help and advice.

Context:
I have a component with BS modal inside which is rendered in a for loop and obviously has many instances.


Issue:
The very first rendered component has its data received from parent via props, and the rest component have their own (like row.id and etc.)


Question: How to fix it? Maybe the problem in BS modal?

Component:


    let vSelect = Vue.component("v-select", VueSelect.VueSelect);

    var scoringButton = Vue.component("scoring-button", {
      props: ["loadId", "causeData"],
      template: "#scoring-template",
      components: {
        "v-select": vSelect,
      },
      data: function () {
        return {
          scoredLoadId: this.loadId,
          scoring: null,
          causeId: null,
          selectedCause: null,
          causeList: this.causeData,
        };
      },
      computed: {
        showCauseList() {
          if (this.scoring === "1" || this.scoring === null) {
            return true;
          }
          return false;
        },
      },
    });

Template:


    <template v-cloak id="scoring-template">
      <div  :id="scoredLoadId">
        <div >
          <button
            v-if="scoring === '1'"
            title="Scoring button"
            type="button"
            
            data-bs-toggle="modal"
            data-bs-target="#scoringModal"
          >
            <i ></i>
          </button>
          <button
            v-else-if="scoring === '2'"
            title="Scoring button"
            type="button"
            
            data-bs-toggle="modal"
            data-bs-target="#scoringModal"
          >
            <i ></i>
          </button>
          <button
            v-else
            title="Scoring button"
            type="button"
            
            data-bs-toggle="modal"
            data-bs-target="#scoringModal"
          >
            <i ></i>
            <i ></i>
          </button>
        </div>
        <div
          
          id="scoringModal"
          tabindex="-1"
          role="dialog"
          aria-hidden="true"
        >
          <div >
            <div  :key="loadId">
              <div >
                <h1 >Load Scoring</h1>
                <button
                  type="button"
                  
                  aria-label="Close"
                  data-bs-dismiss="modal"
                ></button>
              </div>

              <div >
                <div >
                  <input
                    type="radio"
                    
                    name="btnScore"
                    id="btnLike"
                    autocomplete="off"
                    checked="scoring === '1'"
                    value="1"
                    v-model="scoring"
                  />
                  <label
                    
                    for="btnLike"
                    @click="clearSelectedCause"
                  >
                    <i ></i> Like
                  </label>
                  <input
                    type="radio"
                    
                    name="btnScore"
                    id="btnDislike"
                    autocomplete="off"
                    :checked="scoring === '2'"
                    value="2"
                    v-model="scoring"
                  />
                  <label  for="btnDislike">
                    <i ></i> Dislike
                  </label>
                </div>
                <div >
                  <v-select
                    :disabled="showCauseList"
                    label="name"
                    :options="causeList"
                    v-model="selectedCause"
                    placeholder="Choose a cause option"
                  ></v-select>
                </div>
              </div>
              <div >
                <button
                  type="button"
                  
                  data-bs-dismiss="modal"
                >
                  Close
                </button>
                <button type="button" >
                  Save changes
                </button>
              </div>
            </div>
          </div>
        </div>
      </div>
    </template>

Parent:


        var mainTableApp = new Vue({
        el: "#main-table",
        data: {
            tableData: [],
            scoringCauseList: [
                 {
                   "id": 6,
                   "scoring_type": 0,
                   "name": "Late at loading",
                   "mark": "late_at_loading"
                 },
                 {
                   "id": 7,
                   "scoring_type": 0,
                   "name": "Special conditions were not respected",
                   "mark": "special_conditions_were_not_respected"
                 },
                 {
                   "id": 8,
                   "scoring_type": 0,
                    "name": "Bad/not enough information",
                   "mark": "bad_not_enough_information"
                  }
              ],
        },
        components:{
            'scoring-button': scoringButton,
        }
    });

Component in the main app block:


    <div 
   v-for="row in tableData"
   
   >
   ....
   <scoring-button 
      :id="row.LOAD_ID"
      :key="row.LOAD_ID"
      :load-id="row.LOAD_ID" 
      :cause-data="scoringCauseList"
   >
   </scoring-button>
   ....
</div>

I tried to resetting BS modal's data, but it didn't work. So, I went back to look for a solution in Vue part.

I know I may construct the whole thing not enough in a very right way, but this code below is the last version after many other solutions, have been tried with v-model, $emit, props etc.

CodePudding user response:

Update: found solution.

Added ":id" for all "input" fields I had in my component.

So, to have reusable components their own data properties you need to have dynamic ":id" properties. So, that each data flows into their own component.


    <input
        type="radio"
        
        name="btnScore"
        id="btnLike"    // <-- old line
        :id="`btnLike-${dynamicStr}`" // <-- new modified line
        autocomplete="off"
        checked="scoring === '1'"
        value="1"
        v-model="scoring"
      />
      <label
        
        for="btnLike" // <-- old line
       :for="'btnLike-${dynamicStr}'" // <-- new modified line
        @click="clearSelectedCause"
      >
   <i ></i> Like
   </label>

  • Related