1

I am using the Vue Tribute component https://github.com/syropian/vue-tribute

When initially loading the page when the "show" data property is set to true I get "No Match!". However if I set the "show" data property to false on page load then set it to true manually I will get the two results as expected. I have tried to wrap the function call to getTributeOptions() inside of "mounted, created and updated" but I receive the same results. I am using the setTimeout() to mimic the AJAX call I am using to load the remote data.

var app = new Vue({
  el: '#myApp',
  data: function() {
    return {
      show: true,
      tributeOptions: {
        values: []
      }
    };
  },
  mounted: function() {
    this.getTributeOptions();
  },
  methods: {
    getTributeOptions: function(resource) {
      var vm = this;
      setTimeout(function() {
         vm.tributeOptions.values = [
            { key: 'Phil Heartman', value: 'pheartman' },
            { key: 'Gordon Ramsey', value: 'gramsey' }
          ];
      }, 500)
    }
  }
})

<div id="myApp">
  <div v-if="show">
    <vue-tribute :options="tributeOptions">
      <input type="text" placeholder="@" />
    </vue-tribute>
  </div>
</div>

https://codepen.io/anon/pen/QBQaNB?editors=1111

3 Answers 3

1

I found the answer on this question: Vuejs mount the child components only after data has been loaded

Updated Code:

var app = new Vue({
  el: '#myApp',
  data: function() {
    return {
      userDataLoaded: false,
      tributeOptions: {
        values: []
      }
    };
  },
  mounted: function() {
    this.getTributeOptions();
  },
  methods: {
    getTributeOptions: function(resource) {
      var vm = this;
      setTimeout(function() {
         vm.tributeOptions.values = [
            { key: 'Phil Heartman', value: 'pheartman' },
            { key: 'Gordon Ramsey', value: 'gramsey' }
          ];
        vm.dataLoaded = true;
      }, 500)
    }
  }
})

<div id="myApp">
  <template>
    <template v-if="dataLoaded">
      <vue-tribute :options="tributeOptions">
        <input type="text" placeholder="@" />
      </vue-tribute>
    </template>
  </template>
</div>
Sign up to request clarification or add additional context in comments.

1 Comment

actually what you do is rebuild(remount) the components inside v-if. The best way should be add one watcher to vue-tribute, then watch options, if change, delete old instance then create new instance instead. Then parent component don't need to care force-remount etc.
1

While your workaround above would probably work, the problem lays in the library you use In https://github.com/syropian/vue-tribute/blob/master/src/index.js#L19

mounted() {
  const $el = this.$slots.default[0].elm;

  this.tribute = new Tribute(this.options);
...
}

The options value is only used once in mounted(), and there is no handler for updating the values when the options are changed.

A better way to do it would be to watch for changes in this.options, and update the value inside the component respectively.

Comments

1

Check Vue Tribute source code at Github, you will see it will only create one new Tribute instance in mounted(). That means even you change the value of props=options once mounted, it will not affect anything.

So one solution is make sure tributeOptions is ready before mount, so update the value in created() will be an idea.

var app = new Vue({
  el: '#myApp',
  data: function() {
    return {
      tributeOptions: {
        values: []
      }
    };
  },
  created: function () {
   this.tributeOptions.values = [
      { key: 'Phil Heartman', value: 'pheartman' },
      { key: 'Gordon Ramsey', value: 'gramsey' }
    ]
  },
  mounted: function() {
    //this.getTributeOptions();
  },
  methods: {
    getTributeOptions: function(resource) {
      var vm = this;
      setTimeout(function() {
         vm.tributeOptions.values = [
            { key: 'Phil Heartman', value: 'pheartman' },
            { key: 'Gordon Ramsey', value: 'gramsey' }
          ];
      }, 500)
    }
  }
})
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<script src="https://unpkg.com/vue-tribute"></script>
<div id="myApp">
    <vue-tribute :options="tributeOptions">
      <input type="text" placeholder="@" />
    </vue-tribute>
</div>

another solution is download the source codes for Vue Tribute in Github, then implement update Tribute instance by yourself.

Update: create one pull request which implement update Tribute options.

the third solution will be force re-mount by bind different key every time once tributeOptions is updated:

like below demo.

var app = new Vue({
  el: '#myApp',
  data: function() {
    return {
      tributeOptions: {
        values: []
      },
      tributeKey: 0
    };
  },
  mounted: function() {
    this.getTributeOptions();
  },
  methods: {
    getTributeOptions: function(resource) {
      var vm = this;
      setTimeout(function() {
         vm.tributeOptions.values = [
            { key: 'Phil Heartman', value: 'pheartman' },
            { key: 'Gordon Ramsey', value: 'gramsey' }
          ];
          vm.tributeKey+=1
      }, 500)
    }
  }
})
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<script src="https://unpkg.com/vue-tribute"></script>
<div id="myApp">
    <vue-tribute :options="tributeOptions" :key="tributeKey">
      <input type="text" placeholder="@" />
    </vue-tribute>
</div>

1 Comment

@Yamaha32088 I just created one pull request which implement 'update Tribute options'. You can take that one to try it.

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.