简体   繁体   English

自定义 Bitbucket 合并检查 - 提交配置后动态字段呈现两次

[英]Custom Bitbucket Merge Check - dynamic fields render twice after submitting the configuration

I'm creating a custom Merge Check for Bitbucket.我正在为 Bitbucket 创建自定义合并检查。 I started by following this tutorial: https://developer.atlassian.com/server/bitbucket/how-tos/hooks-merge-checks-guide/我开始遵循本教程: https : //developer.atlassian.com/server/bitbucket/how-tos/hooks-merge-checks-guide/

I want the view to be dynamic, eg have button that creates multiple similar input fields (of specified IDs), which eventually get stored in the config.我希望视图是动态的,例如具有创建多个类似输入字段(指定 ID)的按钮,这些字段最终存储在配置中。

First of all, I used soy for this - I created static template with call to one eg .textField.首先,我为此使用了大豆 - 我创建了静态模板,并调用了一个,例如 .textField。 It worked okay, but I couldn't create new, similar fields on the fly (after pressing 'Add new' button).它工作正常,但我无法即时创建新的类似字段(按“添加新”按钮后)。

So I use JavaScript to get data from soy's config.所以我使用 JavaScript 从 soy 的配置中获取数据。 I rewrite the whole config to JS "map" and then render all the fields dynamically (by appending them to HTML code), filling them with values from configuration or creating new fields by pressing the button.我将整个配置重写为 JS“map”,然后动态呈现所有字段(通过将它们附加到 HTML 代码),使用配置中的值填充它们或通过按下按钮创建新字段。

It works - I get all the data saved in config for keys like field_[id], eg field_1, field_2 etc.它有效 - 我将所有数据保存在配置中,用于 field_[id] 等键,例如 field_1、field_2 等。

But there's a bug.但是有一个错误。 When I press the "Save" button and view the pop-up for editing once again, I can see the JavaScript get executed twice: I get all my fields rendered two times - first time during first execution and second time during the second, appearing just a few seconds later.当我按下“保存”按钮并再次查看用于编辑的弹出窗口时,我可以看到 JavaScript 被执行两次:我将所有字段呈现两次 - 第一次在第一次执行期间,第二次在第二次执行期间出现几秒钟后。 There's no such problem when I save the configuration, refresh the page and then view the pop-up once again.当我保存配置,刷新页面,然后再次查看弹出窗口时,没有这样的问题。

Here's my merge check's configuration in atlassian-plugin.xml file:这是我在atlassian-plugin.xml文件中的合并检查配置:

<repository-merge-check key="isAdmin" class="com.bitbucket.plugin.MergeCheck" name="my check" configurable="true">
        <config-form name="Simple Hook Config" key="simpleHook-config">
            <view>hook.guide.example.hook.simple.myForm</view>
            <directory location="/static/"/>
        </config-form>
    </repository-merge-check>

And my simplified .soy template code:还有我简化的 .soy 模板代码:

{namespace hook.guide.example.hook.simple}

/**
 * @param config
 * @param? errors
 */
{template .myForm}
    <script type="text/javascript">
            var configuration = new Object();

            {foreach $key in keys($config)}
                configuration["{$key}"] = "{$config[$key]}";
            {/foreach}

            var keys = Object.keys(configuration);

            function addNewConfiguration() {lb}
                var index = keys.length;
                addNewItem(index);
                keys.push("field_" + index);
            {rb}


            function addNewItem(id) {lb}
                var html = `<label for="field_${lb}id{rb}">Field </label><input class="text" type="text" name="field_${lb}id{rb}" id="branch_${lb}id{rb}" value=${lb}configuration["field_" + id] || ""{rb}><br>`;
                document.getElementById('items').insertAdjacentHTML('beforeend', html);
            {rb}

            keys.forEach(function(key) {lb}
                var id = key.split("_")[1];
                addNewItem(id);
            {rb});

             var button = `<button style="margin:auto;display:block" id="add_new_configuration_button">Add new</button>`;
             document.getElementById('add_new').innerHTML = button;
             document.getElementById('add_new_configuration_button').addEventListener("click", addNewConfiguration);

    </script>

    <div id="items"></div>
    <div id="add_new"></div>

    <div class="error" style="color:#FF0000">
        {$errors ? $errors['errors'] : ''}
    </div>
{/template}

Why does JavaScript get executed twice in this case?为什么在这种情况下 JavaScript 会被执行两次? Is there any other way of creating such dynamic views?有没有其他方法可以创建这样的动态视图?

The soy template will get loaded and executed again whenever you click to edit the configuration.每当您单击以编辑配置时,soy 模板将再次加载并执行。 Therefore the javascript will also get executed again.因此,javascript 也将再次执行。 To prevent this you can create a javascript file and put it next to your simpleHook-config.soy template file with the same filename, so simpleHook-config.js .为了防止这种情况,您可以创建一个 javascript 文件并将其放在您的simpleHook-config.soy模板文件旁边,文件名相同,即simpleHook-config.js The javascript file will be loaded automatically with your soy template, but once. javascript 文件将与您的大豆模板一起自动加载,但一次。 Therefore you can hold a global initialisation state within a new introduced js object.因此,您可以在新引入的 js 对象中保存全局初始化状态。

Furthermore, even though you are adding fields dynamically, you can still and should build the saved configuration inside the soy template already and not building it with javascript.此外,即使您正在动态添加字段,您仍然可以并且应该已经在 soy 模板中构建保存的配置,而不是使用 javascript 构建它。

For me this approach works quite good (I wrote the code more or less blindly, so maybe you need to adjust it a bit):对我来说,这种方法效果很好(我或多或少是盲目地编写代码,所以也许你需要稍微调整一下):

In .soy file:在 .soy 文件中:

{namespace hook.guide.example.hook.simple}

/**
 * @param config
 * @param? errors
 */
{template .myForm}
<div id="merge-check-config">
    <div id="items">
        {foreach $key in keys($config)}
        {let $id: strSub($key, strIndexOf($key, "_") + 1) /}
        {call .field}
            {param id: $id /}
            {param value: $config[$key] /}
        {/foreach}
    </div>

    <div id="add_new">
        <button style="margin:auto; display:block" id="add_new_configuration_button">Add new</button>
    </div>

    <div class="error" style="color:#FF0000">
        {$errors ? $errors['errors'] : ''}
    </div>

    <script>
        myPluginMergeCheck.init();
    </script>
</div>
{/template}

/**
 * @param id
 * @param? value
 */
{template .field}
<div>
    <label for="field_${id}">Field</label>
    <input class="text" type="text" name="field_${id}" id="branch_${id}" value="${value}">
</div>
{/template}

In .js file:在 .js 文件中:

myPluginMergeCheck = {
    initialized: false,
    init: function () {
        if (this.initialized) {
            return;
        }

        var me = this;
        AJS.$(document).on("click", "div#merge-check-config button#add_new_configuration_button"), function (event) {
            me.addNewItem();
        }
        this.initialized = true;
    },
    addNewItem: function() {
        var itemsDiv = AJS.$("div#merge-check-config div#items");
        var newId = itemsDiv.children("div").length;
        var html = hook.guide.example.hook.simple.field({id: newId});
        itemsDiv.append(html);
    }
};

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

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