简体   繁体   English

使用可变长度字典渲染 Handlebars 模板

[英]Render Handlebars template with variable length dictionaries

I have not been using Handlebars and Javascript all that long but I have been able to cobble together a mostly working App.我一直没有使用 Handlebars 和 Javascript,但我已经能够拼凑出一个主要工作的应用程序。 However, after trying to add some more data I have hit a wall.但是,在尝试添加更多数据后,我遇到了麻烦。

I have a Handlebars template that renders multiple dictionaries from an array in order to display the results of multiple API calls.我有一个 Handlebars 模板,它从一个数组中呈现多个字典,以显示多个 API 调用的结果。 Based on another Stack Overflow article I read, I was able to write a helper function that broke the array into its component dictionaries and rendered them based on getting key:values from the dictionary.根据我阅读的另一篇 Stack Overflow 文章,我能够编写一个辅助函数,该函数将数组分解为其组件字典,并根据从字典中获取 key:values 来呈现它们。

This has worked well up until this point as the dictionaries that are the product of each API call have been the same length.到目前为止,这一直运行良好,因为作为每个 API 调用产品的字典长度相同。 I would like to add some data to them in the form of CC'd emails but not all objects will have the same amount of CC'd emails.我想以抄送电子邮件的形式向它们添加一些数据,但并非所有对象都具有相同数量的抄送电子邮件。

Is it possible to dynamically render a template with a different amount of key:values?是否可以使用不同数量的键:值动态呈现模板?

Here is where my array a built (this comes after an API call where I get other required values and initialize the final array. I also get the linkedTicketCcs array in the previous function and pass it in.):这是我构建数组的位置(这是在 API 调用之后,我获取其他所需值并初始化最终数组。我还在前一个函数中获取了 linksTicketCcs 数组并将其传入。):

        let requesterName = data['user']['name'];

        let requesterEmail = data['user']['email'];


        let dataDictionary = {'ticket_number': ticketId, 'name': requesterName, 'email': requesterEmail, 'subject': ticketSubject,
                                'status': ticketStatus, 'description': ticketDescription};

        for (let i = 0; i < linkedTicketCcs.length; i++) {
            dataDictionary[`linked_cc_${i}`] = linkedTicketCcs[i]
        }
        finalArray.push(dataDictionary);

This function runs in a for loop in another function so multiple dictionaries are built and then pushed to the final array.此函数在另一个函数的 for 循环中运行,因此会构建多个字典,然后将其推送到最终数组。 Each dictionary in the array now has the right number of CC'd emails.数组中的每个字典现在都有正确数量的抄送电子邮件。

This final array is then broken into its components using this helper function然后使用此辅助函数将最终数组分解为其组件

Handlebars.registerHelper("each", function (options) {
    let ret = "";

    for (let i = 0; i < finalArray.length; i++) {
        ret = ret + options.fn(finalArray[i]);
    }
    return ret;
});

The data is then injected into the following template:然后将数据注入以下模板:

    {{#each}}
    <table>
        <tr>
            <td><strong>Ticket: </strong> <a href="#" data-toggle="tooltip" data-trigger="hover focus" data-placement="top" title="View ticket" onclick="openTicket('{{ticket_number}}')">{{ticket_number}}</a> <strong>Status: </strong>{{status}}</td>
        </tr>
        <tr>
            <td><strong>Subject: </strong>{{subject}}</td>
        </tr>
        <tr>
            <td><strong>Requester: </strong><a href="mailto:{{email}}" class="no-link email">{{email}}</a></td>
        </tr>
     </table>
    {{/each}}   

As a workaround I can render something like this to add the CC'd emails:作为一种解决方法,我可以渲染这样的东西来添加抄送的电子邮件:

       {{#if linked_cc_0}}
        <tr>
            <td><strong>CC: </strong><a href="mailto:{{linked_cc_0}}" class="no-link email">{{linked_cc_0}}</a></td>
        </tr>
        {{/if}}
        {{#if linked_cc_1}}
        <tr>
            <td><strong>CC: </strong><a href="mailto:{{linked_cc_1}}" class="no-link email">{{linked_cc_1}}</a></td>
        </tr>
        {{/if}}
        {{#if linked_cc_2}}

Where each linked CC is rendered conditionally if the key:value exists in the data passed to the template.如果 key:value 存在于传递给模板的数据中,则有条件地呈现每个链接的 CC。 However, it seems like there should be a cleaner way to do this, perhaps using another helper function.然而,似乎应该有一种更简洁的方法来做到这一点,也许使用另一个辅助函数。

So what I need to be able to do is to render multiple template blocks coming from dictionaries in an array where the dictionaries will not always be the same length.所以我需要能够做的是在一个数组中呈现来自字典的多个模板块,其中字典的长度并不总是相同。 I assume this can be done but I am not sure how.我认为这可以做到,但我不确定如何做到。

Using the #each builtin , you should be able to get what you want:使用#each内置,你应该能够得到你想要的:

{{#eachArray}}
<table>
    <tr>
        <td><strong>Ticket: </strong> 
            <a href="#" data-toggle="tooltip" 
                        data-trigger="hover focus" 
                        data-placement="top" title="View ticket" 
                        onclick="openTicket('{{ticket_number}}')">{{ticket_number}}
            </a> <strong>Status: </strong>{{status}}
        </td>
    </tr>
    <tr>
        <td><strong>Subject: </strong>{{subject}}</td>
    </tr>
    <tr>
        <td><strong>Requester: </strong><a href="mailto:{{email}}" class="no-link email">{{email}}</a></td>
    </tr>
    {{#each ccList}}
    <tr>
        <td><strong>CC: </strong><a href="mailto:{{this}}" class="no-link email">{{this}}</a></td>
    </tr>
    {{/each}}
 </table>
{{/eachArray}}   

Your problem is made difficult by the data structure you are choosing.您选择的数据结构使您的问题变得困难。

By making each CC email a unique key on the email object ( linked_cc_0 , linked_cc_1 , etc) you are forcing your template to have to know all of these keys in order to render the values.通过使每个抄送电子邮件成为电子邮件对象( linked_cc_0linked_cc_1等)上的唯一键,您将迫使模板必须知道所有这些键才能呈现值。 This is not an ideal structure.不是理想的结构。

Since your CC emails are an arbitrarily long list of strings, why not structure your data as such?既然您的抄送电子邮件是一个任意长的字符串列表,为什么不这样构建您的数据呢?

If each email object has, for example, a linked_ccs key with an array value containing 0 or many strings, it is easy to handle this in your template with a simple #each .例如,如果每个电子邮件对象都有一个linked_ccs键,该键的数组值包含 0 个或多个字符串,那么在模板中使用简单的#each很容易处理。

You would need only assign the linkedTicketCss to the dataDictionary object at the linked_css key, as in:你只需要指定linkedTicketCssdataDictionary的对象linked_css键,如:

dataDictionary.linked_ccs = linkedTicketCcs;

Your template then becomes:您的模板将变为:

{{#each emails}}
  {{! existing email template here }}
  {{#each linked_ccs as |linked_cc|}}
    <tr>
      <td><strong>CC: </strong><a href="mailto:{{linked_cc}}" class="no-link email">{{linked_cc}}</a></td>
    </tr>
  {{/each}}
{{/each}

I have created a fiddle for your reference.我已经创建了一个小提琴供您参考。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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