Handlebars condition based on lookup

2019-07-11 18:35发布

问题:

I have the following data structure:

{
    things: [
        "desk",
        "chair",
        "pen",
        "book",
        "lamp"
    ],
    owners: [
        "Julia",
        "Sandra",
        "John",
        "Paul"
    ]
}

What's working:

This handleblars template:

{{#each things}}
    <p>This {{this}} belongs to {{lookup ../owners @index}}</p>
{{/each}}

Correctly outputs:

This desk belongs to Julia
This chair belongs to Sandra
This pen belongs to John
This book belongs to Paul
This lamp belongs to

What's not working:

Now, I'd like to add a condition because the last thing might not have an owner. The template would then look something like:

{{#each things}}
    {{#if lookup ../owners @index}}
        <p>This {{this}} belongs to {{lookup ../owners @index}}</p>
    {{else}}
        <p>...But this {{this}} belongs to nobody</p>
    {{/if}}
{{/each}}

And the ouput:

This desk belongs to Julia
This chair belongs to Sandra
This pen belongs to John
This book belongs to Paul
...But this lamp belongs to nobody

Unfortunately, this {{#if lookup ../owners @index}} thing doesn't work.

My question: is it possible to achieve this with built-in Handlebars helpers, or do I have to write a custom helper?

回答1:

I think it will be better if you were to change your data structure, for instance like this:

[
        {   
            thing:    "desk",
            owner: "Julia"
        },
        {   
            thing: "chair",
            owner:"Sandra"
        },
        {   
            thing:  "pen",
            owner:  "John"},
        {   
            thing:  "book",
            owner:  "Paul"},
        { 
            thing:  "lamp"
        }
]    

then your handlebar template will look like

{{#each this}}
  {{#if this.owner}}
    <p>This {{this.thing}} belongs to {{ this.owner}}</p>
{{else}}
 <p>...But this {{this.thing}} belongs to nobody</p>
{{/if}}
{{/each}}

this will output (I ran it on http://tryhandlebarsjs.com/)

<p>This desk belongs to Julia</p>
<p>This chair belongs to Sandra</p>
<p>This pen belongs to John</p>
<p>This book belongs to Paul</p>
<p>...But this lamp belongs to nobody</p>

Using handlebars helpers may look good to you, but moving logic from handlebars to javascript will be better in long run.



回答2:

You can indeed do just what you're trying to do, using subexpressions:

{{#if (lookup ../owners @index)}}

works like a charm. (source: Handlebars website)



回答3:

I believe the answer is a 'no' if you want to nest Handlebars lookup with an if.

But here, if you want to omit the last thing (or n things) which don't have an owner, you may reverse check the #each like below,

{{#each owners}}
  <p>This {{lookup ../things @index}} belongs to {{this}}</p>
{{/each}}

Which outputs,

<p>This desk belongs to Julia</p>
<p>This chair belongs to Sandra</p>
<p>This pen belongs to John</p>
<p>This book belongs to Paul</p>

Hope this helps.



回答4:

I have found an alternate solution by writing a custom helper, isIndexExist.

Handlebars.registerHelper("isIndexExist", function(array, value, options) {
  return value < array.length ? options.fn(this) : options.inverse(this);
});

And in the template, you can write,

{{#each things}}
  {{#isIndexExist ../owners @index}}
    <p>This {{this}} belongs to {{lookup ../owners @index}}</p>
  {{else}}
    <p>...But this {{this}} belongs to nobody</p>
  {{/isIndexExist}}
{{/each}}

Hope this helps.