Linkification & link-to component


#1

I need to be able to linkify a hashtag by going through the content being sent from the server and replacing each hashtag to a url that points to our site. That was easy to do, but I need to have it insert a link-to component for each hashtag so that a full page refresh does not occur.

To give an example, lets say the content is “this is a #cool #ember post” I need to be able to turn that into

"this is a <a href="/hashtags/cool">#cool</a> <a href="/hashtags/ember">#ember</a> post"

Here is my helper.

import Ember from 'ember';

export function linkifyText(params, hash) {
    var regex = /(^|\W)(#[a-z\d][\w-]*)/ig;
    var text = params[0];

    text = text.replace(regex, function (hashtag) {
        hashtag = hashtag.trim();
        var word = hashtag.split('#')[1];
        return ' <a href="/hashtag/' + word + '">' + hashtag + '</a> ';
   });
   return Ember.String.htmlSafe(text);
}

export default Ember.Helper.helper(linkifyText);

This works but it causes a full page refresh because we are not using link-to components. Is there a way I can insert a link-to component in the helper for each hashtag?

Another option would be to turn this into a component and use actions on each link that then go to a action handler in the component, but I can’t seem to grasp how I would generate the html to add the actions.


#3

First convert your text into

[
  { text: "chunk of text", isHash: false},
  { url: "/hashtags/cool", isHash: true }
]

then you can loop through in your template

{{#each tokens as |token|}}
  {{#if token.isHash}}{{link-to token.url}} {{else}} {{token.text }} {{/if}}
{{/each}}

#4

So here is what I ended up doing. Thank you varblob for helping!

I created a component called ‘hashtag-linkify’.

import Ember from 'ember';

export default Ember.Component.extend({
    click: function(event) {
        var target = $(event.target),
            hashtagId = '';
        if (target.is('a')) {
            event.preventDefault();
            hashtagId = target.data('hashtag-word');
            this.get('router').transitionTo('hashtag', hashtagId);
        }
    }
});

with a template of

{{linkify-text text}}

that uses the helper from above (I also added a data attribute onto the ‘a’ tag) then just injected the router into that component . So if it reads its an ‘a’ tag which any hashtag gets turned into, it will take over and re-route appropriately.