title: Can I Pass a Function To a Props on a VueJS Component
body: <p>I have a rather simple component.  Basically it is a dropdown <code>select</code> and I need to run some custom code that is in an external javascript function.  However, this prop is not required on every instance of the component.  So sometimes there may be nothing in the prop.  Other times it might do one thing, others might do something else.</p>
  
  <pre><code>&lt;template id="drop-list-template"&gt;
    &lt;select class="form-control"
            v-model="value"
            v-bind:class="{ required: isRequired, invalid: !isValid }"
            v-on:blur="validate"
            v-on:change="changed"&gt;  &lt;-- This is the Prop I want to use
      &lt;option v-if="showEmptyOption" value=""&gt;{{ emptyOption }}&lt;/option&gt;
      &lt;option v-for="i in items"
              v-bind:value="i.value"
              v-bind:selected="i.checked === value"
              v-bind:disabled="i.enabled === false"&gt;
        {{ i.text }}
      &lt;/option&gt;
    &lt;/select&gt;
  &lt;/template&gt;
  </code></pre>
  
  <p>So in the <code>on-change</code> event, it will call the <code>changed</code> method.  That was not working.  I then added a <code>special</code> prop to the code file:</p>
  
  <pre><code>Vue.component("drop-list", {
    template: "#drop-list-template",
    props: {
      dataset: { type: Array, required: true },
      isRequired: { type: Boolean, required: false, default: false },
      emptyOption: { type: String, required: false, default: "*Select an Option *" },
      showEmptyOption: { type: Boolean, required: false, default: true },
      special: { required: false }
    },
    data: function () {
      return {
        items: this.dataset,
        isValid: true,
        value: ""
      }
    },
    methods: {
      validate: function (event) {
        var Result = true;
  
        if ((this.isRequired === true) &amp;&amp; (this.value === ""))
          Result = false;
  
        this.isValid = Result;
  
        return Result;
      },
      changed: function (event) {
        if (this.special) {
          AbnormalitiesAndImpressions(); &lt;-- Obviously this works
          alert("After");
          this.special();  &lt;-- Would want this to run AbnormalitiesAndImpressions
        }
      }
    }
  });
  </code></pre>
  
  <p>And implement it via:</p>
  
  <pre><code>&lt;drop-list ref="lstAbnormalities"
             v-bind:dataset="Abnormalities"
             v-bind:is-required="true"
             special="AbnormalitiesAndImpressions"&gt;
  &lt;/drop-list&gt;
  </code></pre>
  
  <p>Where <code>AbnormalitiesAndImpressions</code> is just dumb right now:</p>
  
  <pre><code>function AbnormalitiesAndImpressions(lstAbs, lstImps) {
    alert("Got to here");
  }
  </code></pre>
  
  <p>When I run it, the "Got to here" alert pops up and so does the "After" alert.  It then fails because <code>this.special();</code> is not a function.</p>
  
  <p>Bottom line is I am trying to let the user (myself in this case) create as many of these lists as needed.  What will happen on some of them is they tweak what is available in other controls.  So a sort of validation is going on.  I just want this to be customizable per each use of the component.</p>
  
  <p>I would even be fine with an anonymous function like the following:</p>
  
  <pre><code>&lt;drop-list ref="lstAbnormalities"
             v-bind:dataset="Abnormalities"
             v-bind:is-required="true"
             special="function () { AbnormalitiesAndImpressions(); }"&gt;
  &lt;/drop-list&gt;
  </code></pre>
  
  <p><strong>Update</strong>
  I have updated my component slightly:</p>
  
  <pre><code>&lt;template id="drop-list-template"&gt;
    &lt;select class="form-control"
            v-model="value"
            v-bind:class="{ required: isRequired, invalid: !isValid }"
            v-on:blur="validate"
            v-on:change="change"&gt;
      &lt;option v-if="showEmptyOption" value=""&gt;{{ emptyOption }}&lt;/option&gt;
      &lt;option v-for="i in items"
              v-bind:value="i.value"
              v-bind:selected="i.checked === value"
              v-bind:disabled="i.enabled === false"&gt;
        {{ i.text }}
      &lt;/option&gt;
    &lt;/select&gt;
  &lt;/template&gt;
  </code></pre>
  
  <p>And the corresponding javascript:</p>
  
  <pre><code>Vue.component("drop-list", {
    template: "#drop-list-template",
    props: {
      dataset: { type: Array, required: true },
      isRequired: { type: Boolean, required: false, default: false },
      emptyOption: { type: String, required: false, default: "*Select an Option *" },
      showEmptyOption: { type: Boolean, required: false, default: true },
      special: { type: Function, required: false }
    },
    data: function () {
      return {
        items: this.dataset,
        isValid: true,
        value: ""
      }
    },
    methods: {
      change: function (event) {
        if (this.special)
          this.special();
      }
    }
  });
  </code></pre>
  
  <p>And the implementation:</p>
  
  <pre><code>&lt;drop-list ref="lstAbnormalities"
             v-bind:dataset="Abnormalities"
             v-bind:is-required="true"
             :special="AbnormalitiesAndImpressions"&gt;
  &lt;/drop-list&gt;
  </code></pre>
  
  <p>And here is the page's Vue code:</p>
  
  <pre><code>var vm = new Vue({
    el: "#app",
    data: {
      Result: {},
      Defaults: {},
      Errors: [],
      Abnormalities: [],
      Impressions: []
    },
    methods: {
      AbnormalitiesAndImpressions: function () {
        alert("Should get overridden");
      }
    }
  });
  
  vm.AbnormalitiesAndImpressions = function (lstAbs, lstImps) {
    alert("Got to here: " + lstAbs + "\n" + lstImps);
  }
  </code></pre>
  
  <p>I found that if I did not add the <code>methods</code> short version of <code>AbnormalitiesAndImpressions</code> that it would give me a Vue warning that the property did not exist.  However, the version of <code>AbnormalitiesAndImpressions</code> at the bottom of that file actually runs.  I like this as each implementation could change and they should be on the page and not on the component.</p>
  
  <p>When I change the dropdown item, I do get the <code>Got to here</code> message.  And of course it has two <code>undefined</code> as the <code>lstAbs</code> and <code>lspImps</code> were not passed in.</p>
  
  <p><strong>New Question</strong></p>
  
  <p>Is it possible then to pass values to my props function?  In this case, they can be <code>strings</code>.  But if I do the code below...</p>
  
  <pre><code>&lt;drop-list ref="lstAbnormalities"
             v-bind:dataset="Abnormalities"
             v-bind:is-required="true"
             :special="AbnormalitiesAndImpressions('test')"&gt;
  &lt;/drop-list&gt;
  </code></pre>
  
  <p>When the page loads, the <code>alert</code> is popped right away and Does have the <code>test</code> parameter.  And when I actually change the <code>select</code> the <code>alert</code> does not fire at all.</p>