简体   繁体   中英

Handlebars Array Length Conditional Helper

I have a scenario where I am trying to create a custom handlebars helper that looks at the length of an array and if more than three objects are present within that array, return just the first three elements, but if it is not, then return the full amount. Below was my attempt at doing just this and i'm getting back the right amount of objects when I pass in a value for limitAmount , but the values being returned are [object SequelizeInstance:blog_comment] for the amount of objects that are present. This is not what I was looking for and I'm now wondering if a for loop should be involved to pass back the values of the objects. Is this simply resolved with a for loop?

Detailed example of what is appearing:

[object SequelizeInstance:blog_comment],[object SequelizeInstance:blog_comment],[object SequelizeInstance:blog_comment]

Object structure example:

blog_comments: [
{
commentId: 1,
comment: 'Test',
userId: 2},
{ 
commentId:2, 
comment: '2nd Test', 
userId: 1
}]

Registered Handlebar:

hbs.registerHelper('commentLimit', function(comment, limitAmount, options){
        if(comment.length > limitAmount){
            return comment.slice(0,limitAmount);
        } else {
            return comment;
        }
    })

Use in Template:

{{#commentLimit blog_comments 2}}
        {{#ifeq userId @root.user.userId}}
        <a href="#" class="comment-delete" data-comment-id="{{commentId}}">Delete</a></p>
        {{/ifeq}}
        <p class="blog-comment">{{comment}}</p>
    {{/commentLimit}}

Solution 1. Yes. You need to use for loop inside helper,

hbs.registerHelper('commentLimit', function(comment, limitAmount, options) {
    let res = comment;
    if (comment.length > limitAmount) {
        res = comment.slice(0, limitAmount);
    }
    let out ='';
    for (var i = 0; i < res.length; i++) {
        out = out + options.fn(res[i]);
    }
    return out;
})

Solution 2. You can use built-in each helper to iterate

{{#each (commentLimit blog_comments 2)}}
        {{#ifeq userId @root.user.userId}}
        <a href="#" class="comment-delete" data-comment-id="{{commentId}}">Delete</a></p>
        {{/ifeq}}
        <p class="blog-comment">{{comment}}</p>
    {{/each}}

commentLimit helper is same as you got.

hbs.registerHelper('commentLimit', function(comment, limitAmount, options){
        if(comment.length > limitAmount){
            return comment.slice(0,limitAmount);
        } else {
            return comment;
        }
    })

Refining answer provided by @kumkanillam:

Handlebars.registerHelper('commentLimit', function (comment, limitAmount, options){
   var commentList = comment.slice(0, limitAmount + 1);
   return commentList.reduce(function(results, comment) {
     return results + options.fn(comment);
   }, '');
});

The idea is to return the concatenation of the results of each iteration. The 'reduce' function handles this task nicely.

You can think of the options call:

options.fn(comment)

as running the block of code between the {{#commentLimit ...}} and the {{/commentLimit}} with the context being the values supplied by the parameter (in this case, one of the entries in blog_comments').

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM