Search code examples
javascriptarraysknockout.jsko.observablearray

How to add a break between Array objects with knockout and tooltip


I have an array joined with commas in a tooltip. However I want each one be on it's own line. I've tried a few things but none seem to be working. The code is a knockout observable to which I am new too.

Here is my ko observable:

 this.campaignTagString = ko.observable("");
(function() {
    if(data.campaignTags != undefined) {
        var array = [];
        for(var tag in data.campaignTags){
            array.push(data.campaignTags[tag].name);
        }
        //Join our campaign tag name array
        var tagString = array.join(", " + '<br />');
        $('#tooltip-campaigntags').tooltip({ 
          content: function(callback) { 
             callback($(this).prop('title').replace('|', '<br />')); 
          }
        });
        var textCampaign = "Campaigns: ";
        o.campaignTagString(textCampaign + tagString);
    }
})();

I am calling it like so:

<span id="tooltip-campaigntags" class="label label-default label-mini" data-bind="html: '<i class=\'fa fa-tags\'></i> '+campaignTags().length, tooltip: { title: campaignTagString , placement: 'bottom' }" data-toggle="tooltip" data-placement="bottom" title="" >
</span>

Any help would be great, thanks!


Solution

  • Some tips:

    • You have an error in your code: if campaignTags is an object, campaignTags().length will not work; if it is an array, data.campaignTags[tag].name will not work.
    • You might find it useful to have a look at Knockout-Bootstrap, a Bootstrap adaptation that provides Knockout bindingHandlers for Bootstrap JS functions (used in demo below).
    • The Bootstrap documentation mentions the option {html: true} if you want your content not to be encoded into text.
    • Additionally, your IIFE (the function in which you wrapped the bootstrap tooltip functionality) should rather be a computed observable on your view model, as well as the icon html, and the string, all depending on campaignTags.

    Below are the resulting JS viewModel and HTML binding if you follow these tips:

    //params === object containing tag objects like -- tagX: {name: 'tag'}
    function VM(params) { 
        var self = this;
        this.campaignTags = params;
        this.campaignTagsArray = ko.computed(function() {
            var array = [];
            for(var tag in self.campaignTags) {
                array.push(self.campaignTags[tag].name);} 
            return array;});
        this.campaignTagString = ko.computed(function() { 
            return "Campaigns: <br>" + 
                   self.campaignTagsArray().join(", " + '<br />'); });
        this.html = ko.computed(function() { 
            return '<i class="fa fa-tags"></i>&nbsp; ' + 
                   self.campaignTagsArray().length });
    }
    

    And the HTML binding:

    <span class="label label-default label-mini" data-bind="
         html: html(), 
         tooltip: { html: true, title: campaignTagString() , placement: 'bottom'}">
    </span>
    

    Check out the fiddle for a demo.