2

Just to preface this whole thing-- I'm not even sure that the way I'm going about this is the most correct way to do it. Basically, I need to add an instance of a Vue component when the user clicks a button, expanding. I used this discussion in the vue.js forum to help. Unfortunately, triggering this insert function via a button click is not working. Console is showing an "addNewStop is not defined at HTMLButtonElement.onclick" error.

The HTML in my template:

<div id="newCont"></div>
            <button type="button" class="btn-primary" id="addStop" onclick="addNewStop()">Add Stop</button>

The script I'm calling:

  import Stops from '@/components/Stops'

  const ComponentCtor = Vue.extend(Stops)
  const componentInstance = new ComponentCtor({})
  function addNewStop() {
    componentInstance.$mount('#newCont')
  }

I will freely admit that I wasn't sure how to go about doing this in the first place, and have found surprisingly little information about how to insert new component instances. If there are other, better options I should be exploring beyond this, please let me know!

Edit:

Stops is actually a template containing form inputs, allowing the user to specify a delivery stop along a truck route. Here is its template:

<template>
  <div class="stops">
    <h4>Delivery</h4>
            <div class="form-group">
                  <label for="shipName">Shipper Name</label>
                <vue-simple-suggest
                    :list="simpleSuggestionList"
                    :filter-by-query="true" id="shipName" placeholder="Start typing a name" autocomplete="autofill-myself"></vue-simple-suggest>
                </div>
            <div class="form-group">
                  <label for="locationPickup">Location</label>
                <vue-simple-suggest
                    :list="simpleSuggestionList"
                    :filter-by-query="true" id="locationPickup" placeholder="Start typing an address" autocomplete="custom-addresses"></vue-simple-suggest>
                </div>
                <div class="form-group row">
              <label>Date</label>
              <flat-pickr
              :config="dateConfig"
                class="form-control" 
                placeholder="Select date"               
                name="date" id="date1"></flat-pickr>
            </div>

            <div class="row">
              <div class="form-group col left">
              <label>Time</label>
              <flat-pickr
                :config="timeConfig"
                class="form-control" 
                placeholder="Select time"               
                name="time1" id="time1"></flat-pickr>
              </div>

              <div class="form-group col right">
              <label v-show="pickupChecked">Time 2</label>
              <flat-pickr
                :config="timeConfig"
                class="form-control" 
                placeholder="Select time"               
                name="time2" v-show="pickupChecked" id="time2"></flat-pickr>
              </div>
            </div>
            <div class="form-check">
                <input class="form-check-input" type="checkbox" v-model="pickupChecked" id="apptCheck1" >
                <label class="form-check-label" for="apptCheck1">
                  Time range?
                </label>
            </div>
             <div class="form-group row">
              <label for="userAboutMe">Location notes:</label>
              <textarea class="form-control" id="userAboutMe" rows="3" placeholder="Is there any information about the location that the driver should know?"></textarea>
              <div class="form-check">
                <input class="form-check-input" type="checkbox" value="" id="defaultCheck1">
                <label class="form-check-label" for="defaultCheck1">
                  Save location notes for this place?
                </label>
              </div>
            </div>
  </div>

</template>
1
  • declare one data property=stops : [], inside <div id="newCont">, add template like <stops v-for="(item, index) in stops" :key="index"></stops> Commented Jun 27, 2018 at 20:29

1 Answer 1

5

In most cases, trying to manipulate the DOM directly (e.g. by adding a component) is a sign that you're not using Vue.js as it was intended. Vue is data-driven, which means that your code should simply update the data, leaving the DOM manipulation to Vue itself. Your question doesn't provide enough details for a specific solution, but there are a couple of general approaches that might work.

If you have a number of Stop components in the DOM, and clicking on the button simply adds another, then use v-for to render the stops from data, and have the button click handler simply add another entry in the data array.

<template>
    <form>
        <fieldset v-for="(stop, index) in stops" :key="index">
            <stop v-bind="whatever"/>
        </fieldset>
        <button @click="onClick">Add one</button>
    </form>
</template>

<script>
export default {
    data() {
        return {
            stops: []
        };
    },
    methods: {
        onClick() {
            this.stops.push(/* whatever */)'
        }
    },
    components {
        Stop
    }
};
</script>
Sign up to request clarification or add additional context in comments.

3 Comments

I had looked at v-for, but was under the impression that it was for list rendering; I'm trying to add sections to a form. I should have clarified in my question, that was my bad! I've updated the question with my Stop template.
v-for is appropriate any time you have an array of data that should be rendered, regardless of whether you're rendering it in an <ol>, <ul>, or something completely different. I revised my example to show how one might render multiple <fieldset> elements within a <form>
Thank you for that clarification, and for helping me adjust the way I was thinking about using Vue! Orienting my thinking around data instead of the DOM has been a struggle.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.