I have a filter to convert content with id into user name. For instance, it converts Thank you @id-3124324 ! into Thank you @Jack !.

var filter = function (content) {
    var re = /\s@(id\-\d+)\s/g;
    var matches = [];
    var lastMatch = re.exec(content);
    while (lastMatch !== null) {
        matches.push(lastMatch[1]); // uid being mentioned
        lastMatch = re.exec(content);
    }

    // TODO: query user name from matched id

    // replace id with user name
    // fake usernames here
    var usernames = ['Random Name'];
    for (var i = 0; i < usernames.length; ++i) {
        content = content.replace(new RegExp(matches[i], 'g'), usernames[i]);
    }

    return content;
};

Vue.filter('username', filter);

But in my case, usernames should be achieved with AJAX of a query with id. How should I do it?

share|improve this question
    
Just make an ajax call to your API or whatever and when you get result return the content from your ajax response – Primoz Rome Sep 22 '16 at 7:31
    
@PrimozRome Then how to update the content? – Ovilia Sep 22 '16 at 7:37
    
Not sure how your app works but I wouldn't do this with a filter... If you have ID just use Vue to handle ajax call to your api to return username for that ID. – Primoz Rome Sep 22 '16 at 7:39
    
You can't use a filter for this, but you might like github.com/foxbenjaminfox/vue-async-computed – Roy J Sep 22 '16 at 13:10
    
@RoyJ I'm afraid this is not I want. I need similar feature with filter. – Ovilia Sep 23 '16 at 2:37
up vote 0 down vote accepted

Anything you can do with a filter you can do with a computed. In Vue 2.0, there won't be filters, so you'll need to use computeds instead.

Fetching data asynchronously into a computed is a somewhat messy problem, which is why there is the vue-async-computed plugin. The difficulty is that the computed has to return a value synchronously, when it hasn't finished fetching data.

The solution is to have the computed depend on a cache of fetched data. If the needed value isn't in the cache, the computed kicks off the async process to fetch it and returns some placeholder value. When the process adds a value to the cache, the computed should notice the change in the cache and return the complete value.

In the demo below, I had to make an auxiliary variable, trigger, which I reference in the computed just so I know there's been an update. The fetch process increments trigger, which triggers the computed to re-evaluate. The computed doesn't notice when values are added to or updated in decodedIds. There may be a better way to deal with that. (Using async computed should make it a non-issue.)

vm = new Vue({
  el: 'body',
  data: {
    messages: [
      'Thank you @id-3124324!'
    ],
    decodedIds: {},
    trigger: 0
  },
  computed: {
    decodedMessages: function() {
      return this.messages.map((m) => this.decode(m, this.trigger));
    }
  },
  methods: {
    decode: function(msg) {
      var re = /@(id\-\d+)/g;
      var matches = msg.match(re);
      for (const i in matches) {
        const p1 = matches[i].substr(1);
        if (!(p1 in this.decodedIds)) {
          // Indicate name is loading
          this.decodedIds[p1] = '(...)';
          // Mock up fetching data
          setTimeout(() => {
            this.decodedIds[p1] = 'some name';
            ++this.trigger;
          }, 500);
        }
      }
      return msg.replace(re, (m, p1) => this.decodedIds[p1]);
    }
  }
});

setTimeout(() => {
  vm.messages.push('Added @id-12345 and @id-54321.');
}, 1500);
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
<div v-for="message in decodedMessages">
  {{message}}
</div>

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.